보이스 클로닝은 학습이 아니라 프롬프트다 — 요즘 TTS 는 소리를 토큰으로 바꾼 LLM
Fish Audio API 필드를 읽다 알게 된 것 — 목소리는 모델 id 가 아니라 참조 음성으로 넘긴다
「보이스 클로닝」 이라고 하면 내 목소리로 AI 를 몇 시간씩 학습시키는 장면을 떠올리기 쉽다. 나도 그랬다. 그런데 app10 에 Fish Audio 테스터를 만들면서 API 문서를 읽어 보니, 목소리를 지정하는 칸에 모델 id 가 아니라 참조 음성이 들어간다.
이 글을 읽으면 요즘 TTS(글을 음성으로 읽어 주는 기술)가 왜 LLM 과 같은 구조인지, 그리고 클로닝을 붙일 때 무엇을 준비하면 되는지 감이 온다.
소리를 단어처럼 만든다
출발점은 신경망 코덱이다. 오디오 파형을 짧은 구간마다 정해진 번호(코드) 하나로 바꾼다. 소리가 사전 속 단어처럼 된다. 이걸 오디오 토큰이라고 부른다.
소리가 토큰이 되면 TTS 는 텍스트 LLM 과 같은 문제가 된다. 앞의 토큰을 보고 다음 토큰을 맞히는 것.
클로닝은 이 구조에서 덤으로 나온다. 참조 음성을 토큰으로 바꿔 프롬프트 앞에 붙이면, 모델은 「이 목소리로 이어서 말하기」 를 한다. ChatGPT 에 예시 문장 몇 개를 주고 같은 문체로 써 달라고 하는 것과 같은 원리다.
API 모양이 증거다
Fish Audio 의 /v1/tts 요청을 보면 꽤 노골적이다. 2026-10-19 에 공식 문서로 다시 확인했다.
| 필드 | 하는 일 | LLM 에서 비슷한 것 |
|---|---|---|
reference_id |
미리 올려 둔 목소리 | 저장해 둔 시스템 프롬프트 |
references |
참조 음성과 그 대본을 요청에 직접 첨부 | few-shot 예시 |
temperature · top_p |
기본 0.7. 높이면 억양이 다양해진다 | 샘플링 온도 |
repetition_penalty · max_new_tokens |
반복 억제, 조각마다 만들 오디오 토큰 상한 | 이름까지 같다 |
chunk_length · condition_on_previous_chunks |
긴 글을 쪼개고, 앞 조각 음성을 문맥으로 넘긴다 | 컨텍스트 창 |
max_new_tokens 설명이 「오디오 토큰」 의 최대 개수다. 이 한 줄을 보고 확신했다.
막힌 곳이 하나 있었다. references 로 음성을 직접 첨부할 때는 요청을 JSON 이 아니라 MessagePack 으로 보내야 한다고 문서에 적혀 있다. 오디오 바이트를 그대로 싣기 때문이다. 테스터를 JSON 으로만 짜 두면 여기서 한 번 걸린다.
옛 TTS 와 무엇이 다른가
| 옛 TTS (연결형 · 파라메트릭) | LLM 형 TTS |
|---|---|
| 음소 사전 · 발음 규칙 | 텍스트를 그대로 토큰으로 |
| 화자마다 모델을 학습 | 참조 음성을 프롬프트로 |
| 억양이 평평하다 | temperature 로 억양 폭을 조절 |
| 같은 입력이면 같은 출력 | 샘플링이라 매번 조금씩 다르다 |
마지막 줄이 실무에서 은근히 크다. 같은 문장을 다시 만들면 다른 억양이 나올 수 있다. 녹음본이 고정돼야 하는 안내 음성이라면 한 번 만든 파일을 저장해 두고 다시 쓰는 편이 낫다.
그럼 파인튜닝은 언제 하나
GPT-SoVITS 처럼 내 데이터로 모델을 미세조정(파인튜닝)하는 방식도 여전히 있다. 고르는 기준은 단순하다.
일단 내 목소리로 읽히기만 하면 된다 → 참조 음성(프롬프트)부터. 준비물은 짧은 녹음 하나다
참조 음성으로는 원하는 톤이 안 나오거나, 오프라인에서 돌려야 한다 → 그때 파인튜닝형을 본다
솔직히 아직 실제로 음성을 뽑아 품질을 비교하진 않았다. temperature 0.1 과 0.9 의 억양 차이, 참조 음성 길이에 따른 차이는 직접 들어 본 뒤에 따로 적을 생각이다. 이 글은 API 모양에서 읽어 낸 구조 이야기다.
남의 목소리는 본인 동의 없이 복제하지 않는다. 만들기가 쉬워진 만큼 이 선은 더 분명히 그어 둔다.
TTS 를 서비스에 붙이려는데 프롬프트형으로 갈지 파인튜닝까지 할지 고민이라면 negabaro 에 편하게 물어봐도 된다 (문의).
핵심 개념
신경망 코덱이 오디오를 짧은 구간마다 번호 하나로 바꾼다 — 소리가 토큰이 된다
트랜스포머가 텍스트와 앞의 오디오 토큰을 보고 다음 오디오 토큰을 맞힌다
참조 음성 토큰을 프롬프트 앞에 붙이면 그 목소리로 이어 말한다 — 이게 클로닝
샘플링이라 같은 문장도 매번 조금 다르다 — 고정이 필요하면 파일을 저장해 쓴다