
프로젝트 개요
이 워크플로는 자연스럽고 매끄러운 중영 이중 언어 친밀 음성을 제작하기 위한 것입니다. 핵심 원칙은 텍스트 음성 변환 모델이 모든 소리를 흉내 내게 하는 것이 아니라, 완성물을 서로 다른 역할의 트랙으로 나누는 것입니다. ElevenLabs는 대사와 호흡 표현을 담당하고, 실제 녹음 소재는 키스 소리와 환경음을 담당하며, ffmpeg는 자르기, 속도 변경, 믹싱 및 연결을 담당합니다. Whisper는 품질 검사 도구로 사용됩니다.
가장 중요한 결론: 음성 모델은 ‘말’과 말의 리듬에 자연스럽게 녹아드는 호흡만 담당해야 합니다. 키스 소리, 젖은 소리와 같은 비언어적 효과음은 별도로 제작한 뒤 사람 목소리와 믹싱해야 합니다.
README의 과정은 Mac mini에서 수행되었지만, 사용된 방법은 특정 Mac 모델에 의존하지 않습니다. 시스템에서 ElevenLabs API를 호출하고, ffmpeg를 실행하며, Whisper로 전사할 수 있다면 주요 단계를 재현할 수 있습니다.
핵심 도구와 역할
- ElevenLabs: Voice Design으로 음색을 만들고 텍스트 음성 변환 모델로 대사를 생성합니다.
- ffmpeg: 샘플링 레이트 통일, 속도 늦추기, 소재 자르기, 페이드 인·아웃, 믹싱 및 연결을 담당합니다.
- Whisper: 비언어적 소재가 모델에 의해 알아들을 수 있는 단어로 읽혔는지 확인합니다.
- 합법적으로 허가된 실제 녹음: 독립적인 환경음을 제공합니다. 원래 과정에서는 퍼블릭 도메인의 CC0 소재만 사용하고 출처를 기록했습니다.
시작 전 설치 및 준비
1. ElevenLabs 준비
ElevenLabs에 가입하고 Voice Design 및 텍스트 음성 변환 인터페이스를 호출할 수 있는 인증 정보를 발급받습니다. 실제로 사용할 인터페이스는 POST /v1/text-to-voice/design 및 POST /v1/text-to-voice입니다.
첫 단계에서는 voice_description과 미리 듣기 텍스트를 제출해 여러 후보 미리보기를 얻습니다. 후보를 선택한 뒤 해당 후보의 generated_voice_id로 정식 음색을 저장합니다. 저장이 완료되면 voice_id를 기록하고, 이후 모든 합성에 이 ID를 사용합니다.
2. ffmpeg 설치
터미널에서 ffmpeg를 직접 실행할 수 있는지 확인합니다. macOS에서는 일반적인 패키지 관리자를 통해 설치할 수 있습니다. 설치 후 다음 명령으로 확인합니다.
ffmpeg -version
3. Whisper 준비
이 과정에서 Whisper는 오디오를 생성하는 데 사용되지 않고 ‘음성 검사용 탐침’ 역할을 합니다. 후보 키스 또는 비언어적 구간을 확인해, 안정적으로 단어가 전사된다면 모델이 실제 비언어적 소리를 낸 것이 아니라 의성어를 읽고 있을 가능성이 높다고 판단합니다.
4. 소재 디렉터리 구성
파일을 역할별로 미리 분리하는 것이 좋습니다. 최소한 사람 목소리 출력, 키스 후보, 선별을 통과한 키스 소재, 원본 환경음, 잘라낸 환경음 구간, 최종 믹스 파일을 포함해야 합니다. 이렇게 하면 검토되지 않은 후보 소재가 완성물에 직접 사용되는 것을 막을 수 있습니다.
1단계: 중영 이중 언어 음색 설계
음색 라이브러리에서 고르기보다 텍스트로 설명하기
README의 테스트에 따르면 기존 중국어 음색은 영어에서 억양이 나타날 수 있지만, Voice Design으로 이중 언어 배경을 구체적으로 설명하면 중국어와 영어 모두 더 자연스러운 결과를 얻기 쉽습니다. 설명에는 네 가지 정보를 명시해야 합니다. 모국어 능력, 연령대, 인물 관계 또는 캐릭터 분위기, 목표 감정입니다.
다음은 원래 과정에서 사용한 설명이며, 캐릭터 요구에 맞게 조정할 수 있습니다.
Native bilingual speaker of Mandarin Chinese (standard putonghua) and American English,
both at native level, with no cross-language accent in either. Male, 35–40. Studio quality.
Persona: mature, dominant, doting. Emotion: composed, doting, low-burning.
Rich, chesty, slightly gravelly low voice; unhurried, even pacing with weight on key words
and a breathy softness at the ends of sentences.
미리 듣기 텍스트에는 광고 문구를 사용하지 않습니다. 캐릭터가 평소 실제로 말할 법한 문장을 선택하고, 동일한 설명으로 여러 후보를 생성해야 합니다. 미리 들을 때는 목소리가 낮거나 듣기 좋은지만 비교하기보다 목표 인물이 자연스럽게 말하는 것처럼 들리는지를 우선 판단합니다.
적절한 모델 선택
- 일반 대화: README에서는 v3를 권장합니다. 텍스트 내용에서 일상적인 감정을 표현하는 데 적합합니다.
- 실시간 통화 또는 친밀한 장면: v4를 권장합니다. 동일한 음색으로 중국어, 영어 및 중영 혼용을 처리하는 데 더 적합하며, 가벼운 음성 지시 태그도 더 쉽게 인식합니다.
- 순수 영어 장문: v4를 사용하지 않는다면
eleven_turbo_v2_5를 선택하고language_code=en을 명시해 영어에서 중국어 억양이 나타나는 것을 줄일 수 있습니다.
음색 매개변수 조정
README의 실제 테스트 시작점은 다음과 같습니다.
stability=0.35: 변화와 극적인 표현이 비교적 뚜렷합니다.stability=0.5: 일상적인 말투에 더 가까우며, ‘의도적으로 연기하는’ 느낌을 줄일 수 있습니다.similarity_boost=0.8: 목표 음색의 일관성을 유지하는 데 사용합니다.style=0.3: 원래 기록에 따르면 v3는 이 매개변수를 인식하지 않으므로 v3를 제어하는 데 의존해서는 안 됩니다.
디버깅할 때는 한 번에 변수 하나만 변경합니다. 이미 좋은 평가를 받은 기준 오디오를 보존한 뒤 안정도 또는 태그 중 하나만 조정해야 변화의 원인을 정확히 판단할 수 있습니다.
2단계: 호흡을 말의 리듬에 녹이기
말투가 바뀔 때만 태그 추가
모든 문장에 태그를 추가하지 않습니다. 여섯 문장에서 열 문장마다 두세 개의 가벼운 태그를 사용하는 것만으로도 충분한 경우가 많으며, 이후 문장은 앞선 말투를 이어갈 수 있습니다. 원래 과정에서 자주 사용한 단어는 low, close, quiet, soft, unhurried입니다.
[low and close to her ear, unhurried]
……过来。别躲。
……靠近一点。对。
[quiet laugh under the breath]
……急什么。
intense, heavy, growl, strained, rough과 같은 강한 단어를 전혀 사용할 수 없는 것은 아니지만, 원래 테스트에서는 목소리가 과장되기 쉬웠습니다. 더 안정적인 전략은 모델에 강하게 연기하라고 요구하는 대신 낮고 가깝게, 느리게 표현하도록 하는 것입니다.
구두점으로 호흡 만들기
heavy breathing을 반복해서 쓰는 것보다 문장 앞, 뒤 또는 중간에 적절한 ‘……’을 넣는 편이 자연스러운 멈춤을 얻기 쉽습니다. 각 그룹에는 뚜렷한 호흡을 두세 곳만 배치하고, 가볍게 내쉬기, 말하다가 멈추기, 잠시 숨 참기, 웃음 섞인 날숨, 반쯤 소리를 거두기처럼 표현 방식을 바꿉니다.
같은 숨소리가 연속해서 나오면 반복감이 드러납니다. 생성 후에는 한 문장만 확인하지 말고 전체를 끝까지 들어야 합니다.
가능하면 전체 구간을 한 번에 생성
전체 단락을 한 번에 생성하면 호흡, 감정 및 음높이가 더 자연스럽게 이어집니다. 여덟 문장을 각각 합성한 뒤 연결하면 각 조각이 매번 새로 시작하는 것처럼 들립니다. 실시간 통화에서 전체를 한 번에 생성할 수 없다면 두 문장 또는 약 40자의 중국어로 한 블록을 구성해 한 문장씩 나누는 일을 피합니다.
맥락 전달
v4는 previous_text와 next_text를 지원합니다. 블록 단위로 생성할 때 앞뒤 텍스트를 모델에 전달하면 기계적으로 읽는 느낌을 줄일 수 있습니다. README에서는 v3가 이 두 필드를 지원하지 않으며, v3에 전달하면 오류가 발생할 수 있다고 특별히 지적합니다. 따라서 모델별로 요청을 구성해야 합니다.
잘못된 언어 라우팅 방지
프로그램이 한자 비율로 모델 또는 언어를 결정한다면 먼저 대괄호 안의 영어 태그를 제거해야 합니다. 그렇지 않으면 매우 짧은 중국어 문장도 영어 태그가 많이 포함되어 영어로 잘못 판단될 수 있습니다. v4를 사용할 때는 동일한 모델을 그대로 유지해 중국어와 영어 간 전환을 줄일 수 있습니다.
3단계: 말하기 속도 제어
원래 테스트에서는 v4의 speed 매개변수가 예상대로 작동하지 않았습니다. v4를 느리게 하려면 먼저 텍스트에 자연스러운 멈춤을 추가한 다음 ffmpeg로 음높이를 유지하며 속도를 늦춥니다.
ffmpeg -i input.mp3 -filter:a "atempo=0.9" output.mp3
순수 영어에 turbo 모델을 사용할 때 README에 기록된 시작점은 speed=0.84이며, 문장 사이에 멈춤을 넣을 수도 있습니다.
<break time="0.4s"/>
한 구간에 멈춤 태그를 너무 많이 쌓지 않습니다. 원래 테스트에서는 최대 약 6개를 권장했으며, 너무 많으면 출력이 불안정해질 수 있습니다.
4단계: 재사용 가능한 키스 소재 상자 만들기
의성어를 직접 쓰지 않는 이유
텍스트 음성 변환 모델에 키스 의성어를 읽게 하면 자연스러운 비언어적 소리보다 알아들을 수 있는 음절 또는 문자처럼 들리는 결과가 흔히 나옵니다. 동작 태그만 작성해도 일반적인 흥얼거림으로 변질될 수 있습니다. 따라서 원래 프로젝트에서는 ‘먼저 대량 생성한 뒤 자르고 선별하는’ 소재 상자 방식을 사용했습니다.
제작 단계
- 동일한 음색과 키스 동작이 포함된 동일한 텍스트를 사용해 전체를 5~6회 생성합니다. 원래 과정에서는 v4와
stability=0.35를 사용했습니다. - 무음 감지 또는 오디오 편집 도구로 각 출력에서 후보 비언어적 구간을 잘라냅니다.
- Whisper로 각 구간을 전사합니다. 명확한 문자나 단어가 전사되는 구간은 즉시 제외합니다.
- 차분 에너지와 원본 에너지의 비율을 확인합니다. 원래 테스트에서 비교적 신뢰할 수 있는 구간은 대체로 0.2보다 높았고, 단어로 읽힌 구간은 약 0.12~0.16, 일반적인 흥얼거림은 대체로 0.1보다 낮았습니다. 이 수치는 특정 소재에서 나온 것이므로 초기 참고값으로만 사용해야 합니다.
- 사람이 직접 들어 통과한 소재를 확인하고 가벼운 키스, 더 깊은 키스, 위치 변화 등의 범주로 정리합니다.
- 호출할 때 최근 사용하지 않은 구간을 무작위로 선택하고, 음높이와 속도를 약 3% 이내에서 가볍게 변경합니다. 원래 과정에서는 느리게만 하고 빠르게 하지는 않았습니다.
자동 선별은 사람의 청취를 대신할 수 없습니다. README에는 지속적인 치찰음이 포함된 구간이 있었고, Whisper가 이미 Sssss와 유사한 결과를 전사했지만 검사 누락으로 완성물에 들어간 사례가 기록되어 있습니다. 올바른 과정에서는 전사 텍스트, 파형 지표 및 실제 청취 결과를 모두 확인해야 합니다.
5단계: 실제 환경음으로 이중 트랙 믹싱
소재 선택
원래 과정에서는 음성 모델로 시뮬레이션하는 방법, AI 효과음 생성을 사용하는 방법, 실제 녹음을 사용하는 방법 세 가지를 비교했습니다. 최종적으로는 사람 목소리가 없고 라이선스가 명확한 CC0 실제 소재를 선택했습니다. 외부 녹음을 사용하기 전에는 라이선스를 확인하고 출처 기록을 보관해야 합니다.
고정 음량 배율을 직접 적용하지 않기
환경 녹음은 평균 음량과 피크가 크게 다를 수 있고, 긴 무음 구간이 포함될 수도 있습니다. 고정 음량 계수를 바로 적용하면 소리가 전혀 들리지 않거나 사람 목소리를 덮을 수 있습니다. 더 안정적인 방법은 다음과 같습니다.
- 원본 소재에서 사람 목소리와 길이가 비슷한 두 구간을 무작위로 잘라냅니다.
- 두 구간의 피크를 측정하고 유효한 소리가 더 많은 구간을 선택합니다.
- 환경음의 피크가 현재 사람 목소리 피크보다 약 12dB 낮아지도록 게인을 계산합니다.
- 환경음에 0.5초 페이드 인을 추가합니다.
- 사람 목소리가 끝난 뒤 약 1초의 여운을 남기고 약 1.4초 페이드 아웃을 적용합니다.
- 키스 소재 자체에 해당 질감이 이미 있다면 환경음을 추가로 겹치지 않습니다.
ffmpeg 믹싱 예시
사람 목소리가 v.mp3이고, 이미 잘라낸 환경음 구간이 w.wav이며, GAIN이 피크 정렬 후 계산한 게인이고, END가 페이드 아웃 시작 위치라고 가정합니다.
ffmpeg -i v.mp3 -i w.wav -filter_complex \
"[1:a]volume=GAIN,afade=t=in:st=0:d=0.5,afade=t=out:st=END-1.4:d=1.4[w];\
[0:a]apad=pad_dur=1.0[v];[v][w]amix=inputs=2:duration=first:normalize=0[a]" \
-map "[a]" -c:a libmp3lame -q:a 2 out.mp3
normalize=0은 중요합니다. README의 테스트에 따르면 이를 생략하면 amix가 사람 목소리를 눈에 띄게 낮출 수 있습니다.
믹싱 태그와 낭독 태그 분리
작성 단계에서 [low, close, wet]과 같은 태그를 사용하고 wet을 후처리 믹싱 태그로 사용할 수 있습니다. 프로그램은 음성 모델에 요청하기 전에 이 단어를 삭제해야 합니다. 그렇지 않으면 모델이 효과음을 연기하려 할 수 있습니다. 사람 목소리가 반환된 뒤 태그에 따라 해당 실제 소재를 겹칩니다. 다음 태그에 해당 표시가 없으면 환경음도 페이드 아웃해야 합니다.
6단계: 완성된 음성 트랙 제작
스크립트를 세 가지 블록으로 나눕니다. 일반 대사 블록은 텍스트 음성 변환으로 보내고, 순수 비언어적 블록은 소재 상자에서 선택하며, 환경음 태그가 있는 블록은 먼저 사람 목소리를 생성한 뒤 이중 트랙 믹싱을 수행합니다.
서로 다른 출처의 오디오는 샘플레이트가 다를 수 있으므로, 이어 붙이기 전에 통일해야 합니다. 예를 들어 먼저 44100Hz로 변환합니다.
ffmpeg -i input.wav -ar 44100 output.wav
샘플레이트를 통일한 후에는 ffmpeg의 concat 필터를 사용해 스크립트 순서대로 하나의 오디오로 이어 붙입니다. 작업이 끝나면 처음부터 끝까지 들어 보면서 블록과 블록 사이의 음색, 배경 잡음, 음량, 호흡이 갑자기 변하지 않는지 중점적으로 확인해야 합니다.
7단계: 실시간 통화에 사용
실시간 모드의 핵심은 대기 시간을 줄이면서도 문맥을 유지하는 것입니다. 줄 단위로 독립된 태그를 기준으로 나누면, 새 태그가 없는 이후 문장도 현재 음색을 이어받게 할 수 있습니다. 두 문장 또는 약 40자의 중국어가 쌓이면 생성을 요청합니다.
- 현재 블록을 재생하는 동안 백그라운드에서 다음 블록을 미리 생성합니다.
- v4에 현재 블록의 이전 문장과 다음 문장을 전달합니다.
- 순수 비언어 블록은 소재 보관함에서 바로 가져오고, 음성 합성을 다시 요청하지 않습니다.
- 마지막 문장의 재생이 끝난 후 마이크를 켜서 음성이 서로 겹치지 않게 합니다.
- 합성에 실패하면 텍스트만 표시하거나 잠시 조용히 유지하고, 즉석에서 다른 음색으로 전환하지 않습니다.
중간에 음색을 바꾸면 발생하는 캐릭터의 단절이 보통 1초 안팎의 멈춤보다 더 두드러집니다. 따라서 캐릭터의 목소리를 일관되게 유지하는 것을 우선해야 합니다.
고급 디버깅 기법
고정 비교 샘플 만들기
이미 자연스럽다고 확인한 기준 오디오를 저장합니다. 매번 안정도, 태그, 문장 부호, 모델, 후처리 속도 중 한 항목만 변경하고 기준 버전과 블라인드 청취로 비교합니다.
생성 태그와 후처리 태그를 분리하기
음성 모델에는 모델이 연기해야 하는 음색 태그만 전달하고, 환경음, 소재 유형, 믹싱 강도는 후처리 메타데이터로 분류해 요청 전에 반드시 제거합니다. 이렇게 하면 모델이 제작 지시를 읽거나 효과음을 흉내 내려고 하는 일을 방지할 수 있습니다.
최근 사용 기록 저장하기
소재 보관함에 최근 사용 대기열을 유지합니다. 예를 들어 최근 사용한 10개의 클립은 피하도록 설정할 수 있습니다. 이렇게 하면 반복되는 느낌을 줄일 수 있으며, 매번 완전히 무작위로 추출하는 것보다 안정적입니다.
자동 품질 기준
다음 검사를 출력 파이프라인에 추가할 수 있습니다.
- Whisper가 존재해서는 안 되는 단어를 전사하지 않았는가.
- 사람 목소리와 환경음의 피크 차이가 목표값에 가까운가.
- 샘플레이트가 통일되었는가.
- 출력 끝에 자연스러운 잔향이 남아 있는가.
- 요청에 사용한 모델이 전달된 매개변수를 지원하는가.
- 언어를 감지하기 전에 영어 태그를 이미 삭제했는가.
비용, 라이선스 및 콘텐츠 범위
README에는 Creator 요금제를 사용하며 가격은 월 22달러, 할당량은 약 12만 자라고 기록되어 있습니다. 처음 음색을 설계할 때는 약 3천 자가 사용되고, 일상적인 사용량은 수백 자에서 2천 자까지 다양합니다. README에는 당시 v4에 기간 한정 할인이 있었다는 내용도 있으므로, 실제 가격, 할당량, 과금 방식은 사용 시점의 공식 페이지를 기준으로 해야 합니다.
모든 콘텐츠는 명확한 성인만 다뤄야 합니다. 미성년자로 해석될 수 있는 캐릭터 설정이나 모호한 연령 표현은 사용하지 마세요. 플랫폼은 텍스트를 기준으로 심사하며, 규정을 위반하면 계정이 정지될 수 있습니다.
타인의 녹음을 사용할 때는 반드시 허가를 확인해야 합니다. 소재를 무료로 다운로드할 수 있다고 해서 재배포나 상업적 이용이 허용되는 것은 아닙니다. 원래의 과정에서는 CC0 소재만 사용하고 각 파일의 출처를 기록합니다.
결론
자연스러운 친밀한 음성은 강한 태그를 쌓아 올린다고 만들어지지 않습니다. 더 신뢰할 수 있는 방법은 음성 모델이 대사, 가벼운 감정, 호흡 리듬에 집중하게 하고, 비언어적 소리는 전사와 수동 청취로 선별한 소재로 분리한 다음, ffmpeg로 피크 매칭, 페이드 인·아웃, 이어 붙이기를 수행하는 것입니다.
최소 버전부터 시작하세요. 먼저 안정적인 이중 음색을 만들고, 전체 구간 생성과 문맥 전달을 검증한 다음 소재 보관함과 환경음을 추가합니다. 각 단계에서 기준 샘플을 보존하고 한 번에 하나의 변수만 조정하면, 태그를 계속 늘리는 것보다 자연스럽고 일관되며 재사용 가능한 결과를 얻기 쉽습니다.
