본문으로 건너뛰기

© 2026 Molayo

Zenn헤드라인2026. 06. 10. 01:29

완전 무료 로컬 AI로 '이모티콘으로 웃는' 자작 걸(Gal) 목소리를 흔들림 없이 양산하는 이야기

요약

본 글은 상상하는 대로 목소리를 만들고 제어할 수 있는 로컬 TTS 시스템 구축 과정을 다룹니다. 기존의 음성 선택 방식의 한계를 극복하기 위해, Irodori-TTS로 '목소리 설계'를 하고 GPT-SoVITS로 이를 안정적으로 복제하여 비언어적 표현까지 구현하는 방법을 제시합니다.

핵심 포인트

  • Irodori-TTS: 참조 음성 없이 캡션만으로 목소리를 설계할 수 있음.
  • GPT-SoVITS: 몇 초 분량의 음성에서 안정적인 Zero-shot Voice Clone이 가능함.
  • 두 로컬 TTS 조합을 통해 비언어적 표현(웃음, 숨쉬기)까지 제어 가능.
  • 클라우드 기반 서비스 대신 무료/로컬 툴 사용으로 비용 부담 최소화.

「원하는 목소리」가 기존 AI 음성에는 없었다

게임 소개 영상의 나레이션을 AI 음성으로 만들어 보고 싶었습니다. 처음 눈을 돌린 곳은 시판되는 유료 소프트웨어였는데, 2만 엔 정도 하는 것도 있어서 취미로 개인 개발을 시작하는 단계에서는 부담이 되었습니다. 금세 포기하고 다음으로 접한 것이 무료로 평이 좋은 AivisSpeech였습니다. 자연스럽고 품질도 높아서, 설치만 하면 다양한 목소리를 사용할 수 있는 우수한 소프트웨어였습니다.

하지만 한동안 사용하면서 깨달은 것은 「기존의 목소리 중에서 고르는 것」 방식의 한계였습니다. 배포된 목소리는 확실히 풍부했지만, 「내가 상상하는, 딱 이 목소리」가 도무지 찾을 수 없었습니다. 간절한 부분을 채워주지 못했습니다.

그래서 방향을 바꿨습니다. 없으면 만들면 된다.목소리를 고르는 것」이 아니라 「목소리를 만드는 것」으로 방향을 틀게 된 것입니다. 이것이 상상 이상으로 긴 여정이었습니다. 결론부터 말하자면, AivisSpeech를 시작점으로 삼아, 최종적으로 두 가지 로컬 TTS(Text-to-Speech)를 조합하게 됩니다.

그리고 여기서 사용하는 것은 모두 로컬에서 작동하는 무료 툴입니다. ElevenLabs 같은 클라우드 음성은 품질 자체는 높지만, 상용 이용은 유료/사용량 기반 과금입니다. 반면 이것들은 월정액도 사용량 기반 과금도 제로에 가깝고, 무제한 생성 가능하며 (전기 요금을 제외하면) 실질적으로 0엔입니다. 「과금이 두려운」 개인 개발자에게는 이것이 가장 효과적입니다.

등장하는 툴

역할라이선스
Irodori-TTS문장(caption)에서 목소리를 설계할 수 있다. 이모티콘으로 웃음/숨쉬기 같은 비언어적 표현이 가능하다MIT
GPT-SoVITS몇 초 분량의 참조 음성으로부터, 그 목소리로 안정적으로 읽는다 (Zero-shot Clone)MIT

둘 다 로컬에서 작동하며 상용 이용이 가능합니다. 실행 환경은 Windows 11 / RTX 4070 (12GB VRAM)입니다.

참고로 이름에 「GPT」가 들어가 있지만, GPT-SoVITS는 OpenAI와 무관합니다. OpenAI의 GPT가 아니라, 자기회귀적으로 음성 토큰을 생성하는 부분이 포함된 구성이라는 의미이며, 로컬에서 작동하는 무료 OSS(Open Source Software)입니다.

제1막: Irodori로 「존재하지 않는 목소리」를 설계하다

Irodori-TTS의 VoiceDesign 모델은 흥미로워서, 참조 음성 없이 문장의 지시(caption)만으로 목소리를 생성할 수 있습니다. 누군가의 목소리를 흉내 내는 '클론'이 아니라, 제로에서 '설계'하는 형태입니다.

uv run --no-sync python infer.py \
--hf-checkpoint Aratako/Irodori-TTS-600M-v3-VoiceDesign \
--text 

「1本の良い参照音声から、どんな台本でも同じ声で読む」——これはまさに**GPT-SoVITS의 본래 설계 목적**입니다. 제1막에서 만든 gal_07을 단 1개만 씨앗(種)으로 사용하여 복제하자, **대본이 바뀌어도 목소리가 안정적**이었습니다. 드리프트 문제는 해결했습니다.

…하지만 이번에는 역의 문제가 발생합니다.

-
**이모티콘의 웃음이나 한숨이 나오지 않습니다.** GPT-SoVITS의 일반적인 텍스트 전처리는 이모티콘을 비언어적 표현으로 취급하지 않고 무시했습니다. - 기세를 내려고 `!`를 많이 사용하면 **억양이 부자연스러워집니다.** - 말 속도(`speed_factor`)나 온도(`temperature`)를 높여 텐션을 더하면, **음조가 무너집니다.** - 고텐션의 참조 음성으로 교체하면, 음질이 드리프트하여 **gal_07의 허스키함이 약해집니다.**

제1막의 '표현력은 있지만 불안정'과 정확히 반대되는 '**안정적이지만, 이번 용도에는 표정 표현이 부족합니다**'. 어느 한쪽만으로는 원하는 것을 얻을 수 없습니다.

🔊 **제2막: GPT-SoVITS의 목소리** — 목소리는 안정적이었지만, 같은 대본의 `🤭`가 무시되어 표정이 없는 읽어주기였습니다.

## 제3막: Speaker Inversion으로 두 마리 토끼를 잡다

여기서 Irodori v3가 **공식적으로 제공하는** **Speaker Inversion**이라는 기능에 도달합니다(전용 학습 config `train_500m_v3_speaker_inversion.yaml`과 학습 스크립트가 포함되어 있습니다). 이는 '**화자의 identity를 나타내는 작은 임베딩 토큰(이번 설정에서는 16개・약 49KB)만 학습**하고, 베이스 모델은 동결한 채로, 그 임베딩을 사용하여 임의의 텍스트를 읽게 하는' 메커니즘입니다.

핵심은, **임베딩으로 화자를 고정하면 목소리가 흔들리지 않는다**는 것입니다. 그리고 **이모티콘의 비언어적 표현은 베이스 모델 측 기능이므로, 임베딩을 사용해도 효과가 유지되었다**는 점입니다(최소한 이번 조건에서는). 즉 '안정성'과 '이모티콘 뉘앙스'가 양립할 가능성이 생겼습니다.

문제는 학습 데이터입니다. Speaker Inversion에는 대상 화자의 음성 코퍼스가 필요하지만, Irodori 단독으로는(드리프트 때문에) gal_07의 다양한 클립을 안정적으로 만들 수 없습니다. 그래서——

GPT-SoVITS(안정적)로 대량의 gal_07 클립을 만든 다음, 그것을 Irodori의 Speaker Inversion 학습 데이터로 사용합니다.

이런 2단계 구조를 취했습니다. 안정적인 생성은 GPT-SoVITS에 맡기고, 그 출력으로 Irodori에게 'gal_07이라는 화자'를 기억하게 하는 것입니다. 최종적인 양산은 Irodori(=이모티콘 사용 가능)에서 진행합니다.

### 파이프라인 전체

학습 코퍼스는 **114개** (각 3~8초, 이모티콘 없는 클린한 짧은 문장)입니다. 여기서 이 파이프라인의 은근한 장점이 발휘됩니다. **GPT-SoVITS에 읽게 한 대본이 그대로 정답 텍스트(쓰기어 표시 라벨)가 되므로**, 라벨링 작업이 필요 없어 데이터셋 작성 수고가 거의 제로였습니다. 학습은 Speaker Inversion의 **16 토큰만** (나머지 약 5억 파라미터는 동결)으로, RTX 4070에서 **3000 스텝・약 25분**이 소요되었습니다. 완성된 임베딩은 **단 49KB**입니다.

최종적인 양산 명령어는 이렇습니다:

uv run --no-sync python infer.py
--hf-checkpoint Aratako/Irodori-TTS-500M-v3
--ref-embed voice_embeds/gal07.speaker.safetensors
...


대본을 바꿔도 목소리는 안정적이고, `🤭`로 제대로 웃습니다. 의도대로 '**이모티콘으로 웃는, 흔들림 없는 갸루 목소리**'가 되었습니다.

🔊 **제3막: Speaker Inversion (최종 형태)의 목소리** — 같은 대본・같은 `🤭`로, 목소리가 안정된 상태에서 자연스럽게 웃습니다. 발화 템포도 조정했습니다.

## Windows에서 빠진 함정

로컬 TTS × Windows 조합으로 몇 번 시간을 허비했습니다. 같은 실수를 반복하는 분들을 위해 남깁니다.

-
: 학습용 latent 전처리가 HuggingFace `prepare_manifest.py`가 작동하지 않는 `datasets`

의성어/효과음 음성 디코딩에 **torchcodec (FFmpeg 공유 DLL 의존)**을 사용한다. 로컬 FFmpeg이 정적 빌드라 DLL이 없어 모든 파일 디코드 실패. →**soundfile로 직접 latent화**하여 회피(WAV라면 FFmpeg 불필요). -
: 학습 시작 시 DataLoader의 워커 프로세스가 각각 torch/CUDA를 읽어와 커밋 메모리가 고갈되어 크래시 발생. →`WinError 1455`

(페이지 파일이 너무 작음)으로 해결. `--num-workers 0`
-
**로컬 12GB VRAM 환경에서는 두 가지 동시 구동 불가**: GPT-SoVITS 서버를 실행한 상태에서 Irodori를 돌리면 세그폴트. →**코퍼스 생성(GPT-SoVITS)과 학습(Irodori)은 순차적으로** 실행한다. -
**장문을 한 번에 생성하면 후반부가 무너짐**: Irodori에 긴 나레이션을 통째로 넣으면, 중간부터 목소리가 파탄되어 들을 수 없게 됨. →**문 단위(**으로 분할하여 개별 생성하고, 무음을 넣어 연결

)に分割して個別生成し、無音を挟んで連結

## 「その声、◯◯のコピーじゃないの?」と言われないために

AI 음성에서 흔히 발생하는 우려는 '특정 성우/스트리머의 클론이 아닌가?'라는 지적입니다. 이를 피할 수 있도록 설계도 처음부터 적용했습니다.

-
**실존하는 목소리를 소재로 사용하지 않음**. gal_07은 `--no-ref`

(참조 음성 제로)으로, 문장의 지시와 난수로부터 합성한 것입니다. 특정 누군가의 녹음을 학습하거나 클론하지 않았습니다. -
**재현 가능성 자체가 증거가 됨**. caption・seed・텍스트를 기록해 두었으며, **완전히 동일한 생성 명령을 실행하면 비트 단위로 완전히 같은 음성이 재현될 수 있습니다**(실제로 해시 일치를 확인했습니다). 목소리가 '특정 사람의 녹음'이 아니라 '문장과 난수로부터 결정론적으로 만들어진 것'임을 누구나 재현할 수 있는 형태로 보여줄 수 있습니다. 이는 복사나 도용이 아니라는 강력한 설명 자료가 됩니다(※ 대본까지 완전히 일치시킨 경우의 재현성입니다. 대본을 바꾸면 목소리가 드리프트하는 것은 제1막과 같습니다. 또한 학습 데이터에서 유래된 유사성이나 우연한 근접함까지 제로 증명할 수는 없습니다). -
⚠️ 한편으로,
**전자 워터마크는 '복사가 아님을 증명'하지 않습니다**. Irodori 출력물에는 SilentCipher 전자 워터마크가 자동 부착되며, 이는

AI 자동 생성 콘텐츠

본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0