Taewon Park - Portfolio

제로샷 한국어 보이스 클로닝 파이프라인

텍스트/음성 편지를 남기면 AI가 톤을 보정하고 음성을 복제해 디지털 타임캡슐로 전달하는 서비스입니다. Spring Boot 백엔드와 Kotlin Compose 프런트를 분리했고, MinIO-S3와 IPFS(Pinata)로 미디어를 안전하게 관리하며 JWT/OAuth2 인증과 예약 발송 스케줄러를 구현했습니다.

기간
2025년 9월 (4주, 팀 프로젝트)
역할
음성 합성/앱 개발 · 기여도 25% · Wear OS 개발 및 앱 제작/ 보이스 클로닝 AI
스택
Spring Boot · Kotlin · JWT/OAuth2 · MySQL · MinIO · IPFS · Docker · Jenkins

수상 · SSAFY 특화 프로젝트 우수상 (2등)

폐쇄망 경계 · 인바운드 차단서비스 서버Spring Boot편지 예약 · 전달작업 올리기결과 가져가기MinIO오브젝트 스토리지작업이 놓이는 우편함20초 주기 폴링작업 · 결과GPU 워커모델 1회 로드 후 폴링 루프에서 재사용① 문장 단위 360자 청크 분할긴 편지의 토큰 에러 · VRAM 사용 감소② CosyVoice2 제로샷 합성15초 샘플 · instruct 프롬프트 · [breath] 토큰실패 시 절반씩 재귀 분할 재시도 (최대 4단계)③ 피치 유지 0.9× · 오디오 병합낭독 속도를 늦추되 음색은 그대로기존 · 화자마다 수십 분 녹음 + 파인튜닝제로샷 · 15초 샘플, 화자별 학습 0해시 기반 완료 마커로 재합성 방지 (idempotent)
연결 방향을 뒤집어 방화벽 정책을 바꾸지 않고 폐쇄망 GPU를 그대로 썼고, 화자별 학습을 없애 사람이 늘어도 비용이 늘지 않게 했다.

문제 상황

개인 목소리로 편지를 읽어주려면 화자마다 수십 분 녹음과 파인튜닝이 필요했고, 합성용 GPU는 인바운드 접근이 불가능한 폐쇄망이었다.

통상적인 보이스 클로닝은 화자가 늘어날수록 녹음·학습 비용이 선형으로 증가한다. 서비스로 만들려면 이 비용 구조부터 깨야 했다.

동시에 GPU 서버는 외부에서 접속할 수 없는 망에 있었고, 방화벽 정책은 바꿀 수 없는 조건이었다.

해결

학습을 없애고, 연결 방향을 뒤집었다.

모델 선택

파인튜닝 대신 제로샷 — CosyVoice2-0.5B

여러 제로샷 TTS를 비교해 CosyVoice2-0.5B를 선택했다. 15초 내외의 샘플만으로 화자 음색을 재현해 화자별 학습 단계를 완전히 제거했다. 화자가 늘어도 추가 비용이 붙지 않는다.

폐쇄망 연결

MinIO를 우편함으로 두고 워커가 폴링

서비스 서버가 MinIO에 작업을 올리면 GPU 워커가 20초 주기로 폴링해 꺼내간다. 연결을 항상 워커가 걸기 때문에(아웃바운드 전용) 방화벽 정책을 바꾸지 않고 폐쇄망에서 동작한다. 두 서버는 서로를 직접 호출하지 않아 결합도 낮다.

합성 품질

낭독 톤을 만드는 instruct 프롬프트와 쉼 제어

inference_instruct2로 한국어 편지 낭독 톤을 zero-shot 합성하고, instruct 프롬프트와 [breath] 토큰·문장부호 치환으로 낭독 쉼을 유도했다. 속도는 피치를 유지하는 time-stretch로 0.9배 조정했다.

긴 편지

문장 단위 360자 청크로 나눠 배치 처리

긴 편지는 문장 단위로 나눠 360자 청크로 배치 처리해 토큰 에러와 VRAM 사용을 줄였다. 워커는 모델을 한 번만 로드해 폴링 루프에서 재사용한다.

결과

수십 분 → 15초
화자당 필요한 녹음 데이터
0
화자별 학습 시간 · GPU 비용
길이 무관
재귀 재시도로 합성 완주

제한된 GPU에서도 여러 사용자의 편지를 안정적으로 처리할 수 있음을 검증했다. 팀 프로젝트로 SSAFY 특화 프로젝트 우수상을 받았다.