오픈소스 TTS·ASR 직접 굴려봤다 — Qwen, Supertonic, 그리고 ElevenLabs와의 거리

요즘 음성 합성과 음성 인식 오픈소스가 쏟아져 나온다. 어떤 게 진짜 쓸 만한지 직접 굴려봐야 알 수 있어서, 가능한 것들을 4090 한 대에 올려 하루씩 돌려보고 정리했다. 결론부터 말하면, TTS는 Qwen3-TTS와 Supertonic 두 개가 살아남았고 Qwen이 미세하게 앞섰다. 하지만 Supertonic은 Swift를 지원해서 iOS on-device 가능성이 있어서, 그쪽이 더 흥미롭다. ASR은 Qwen3-ASR만 굴려봤는데, ElevenLabs 대비 50% 정도. 무료지만 회의록 용도로는 아직 부족하다.
TTS 1차전: 실패한 후보들#
먼저 떨어진 것부터.
VibeVoice — Microsoft가 공개한 오픈소스 음성 모델. 그런데 4090(24GB)에서도 VRAM이 부족해서 inference 자체가 안 됐다. 게다가 ASR 일부 기능만 잘 동작하고, TTS 쪽은 CPU 폴백이 너무 느려서 사용 불가 판정.
fish-speech — 인기 있는 오픈소스 TTS인데, 한국어 긴 텍스트에서 OOM이 자주 났다. 청크를 잘게 잘라도 음질이 들쑥날쑥해서 포기.
Edge TTS — Microsoft Edge가 내부적으로 쓰는 TTS를 비공식으로 호출하는 방식. 한국어 품질은 의외로 좋지만, 네트워크 의존이고 DRM 토큰을 우회하는 구조라 신뢰성이 낮다. 오프라인이 안 되니까 “오픈소스 TTS”를 찾는 목적에는 안 맞다.
남은 게 Supertonic과 Qwen3-TTS 두 개였다.
Supertonic — ONNX 경량, CPU에서도 도는 게 매력#
Supertone(슈퍼톤)이 공개한 supertonic 시리즈. 2026년 4월 말 v3가 나오면서 31개 언어로 확장됐고, 한국어도 포함된다. 핵심은 다음 셋이다.
- ONNX Runtime 기반. PyTorch 의존성 없이 ONNX만 있으면 돈다.
- ~99M 파라미터. 작다. CPU에서도 실시간에 가까운 속도가 나온다.
- 다양한 런타임. Python, Node.js, Browser(WASM), Java, C++, C#, Go, Swift, iOS, Rust, Flutter.
설치는 pip install supertonic 한 줄. 첫 실행 시 Hugging Face Hub에서 모델을 자동 다운로드한다.
from supertonic import TTS
tts = TTS() # 기본 모델이 supertonic-3
style = tts.get_voice_style("F1")
wav, dur = tts.synthesize("안녕하세요!", voice_style=style, lang="ko")
테스트로는 내 위키의 “다크 팩토리 패턴” 페이지 본문 1280자를 통째로 통과시켰다. 19개 청크로 자동 분할되어 2분 56초짜리 44.1kHz mono wav가 떨어졌다. CPU만으로 청크당 평균 약 9초. 4090 같은 게 없이도 노트북에서 돌릴 수 있다는 게 큰 장점이다.
품질은 “그럭저럭”. 사람 같지만 약간 단조롭고, voice style은 F1~F5, M1~M5 같은 코드명이라 캐릭터가 잘 드러나진 않는다. 표현 태그(<laugh>, <breath>, <sigh>)는 지원하지만 한국어에서 효과는 미미했다.
진짜 매력은 따로 있다. 위 런타임 목록을 보면 Swift, iOS가 있다. ONNX 99M 모델이라서 iPhone에 그대로 올릴 수 있을 가능성이 있다는 뜻이다. 아직 실제 iOS 빌드를 시도해 본 건 아니지만, 이게 성공하면 네트워크 없이 디바이스 안에서 TTS가 도는 앱을 만들 수 있다. ElevenLabs API 호출 비용도, 레이턴시도, 프라이버시 걱정도 없는 그림. 다음 실험에서 꼭 해보려는 항목.
Qwen3-TTS — LM 기반, 음색이 풍부#
Qwen3-TTS는 Alibaba Qwen 팀이 공개한 다국어 TTS LM이다. 1.7B / 0.6B 두 크기, CustomVoice / VoiceDesign / Base(클로닝) 세 변종. 한국어는 1급 지원 언어다.
설치는 uv pip install qwen-tts. 추가로 torch + CUDA가 필요하다. 4090에 bf16로 올리면 약 4GB VRAM을 먹는다.
from qwen_tts import Qwen3TTSModel
import torch
model = Qwen3TTSModel.from_pretrained(
"Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice",
device_map="cuda:0",
dtype=torch.bfloat16,
)
wavs, sr = model.generate_custom_voice(
text="안녕하세요. 다크 팩토리 패턴에 대해 이야기해 봅시다.",
language="korean",
speaker="sohee",
)
CustomVoice 모델에는 9개의 사전 학습 음색이 있다. 그중 sohee가 한국어 최적화 여성 음성으로 따로 표기되어 있고, 나머지(ryan, eric, aiden, dylan, uncle_fu 등)도 한국어를 잘 처리한다.
여기서 한 단계 더 갈 수 있다. 동일한 페이지를 이번엔 2인 대화 팟캐스트로 재구성하고, 호스트 소희(sohee) + 게스트 라이언(ryan) 페어로 합성했다. 24개 발화, 화자 전환 시 0.55초 침묵, 같은 화자 연속 시 0.25초. numpy로 이어 붙여서 4분 35초, 13MB, 24kHz mono wav가 나왔다. 추론은 GPU에서 약 3분.
이게 인상적이었다. 단순 낭독이 아니라 호스트가 묻고 게스트가 설명하는 자연스러운 흐름, 발화 사이의 적절한 호흡까지 들어가니까 진짜 짧은 팟캐스트처럼 들렸다. Supertonic으로 같은 페이지를 단일 화자로 합성한 것과 비교하면, 청취 경험이 한 단계 다르다.
추가로 VoiceDesign(자연어로 음색 묘사: “차분하고 따뜻한 여성”)과 Voice Cloning(3초 레퍼런스로 화자 복제)까지 지원하니, 표현의 폭이 Supertonic보다 훨씬 넓다.
TTS 결론 — Qwen이 약간 앞, 하지만 Supertonic의 iOS 가능성#
| 항목 | Supertonic | Qwen3-TTS |
|---|---|---|
| 모델 크기 | ~99M ONNX | 1.7B LM |
| 실행 환경 | CPU 가능 | GPU 필수 (bf16 ~4GB) |
| 음색 다양성 | F1 | 9개 명명 음색 + 자연어 설계 + 클로닝 |
| 멀티 화자 대화 | 가능 (호출 따로 + 후처리) | 가능 (호출 따로 + 후처리) |
| 출력 | 44.1kHz | 24kHz |
| 모바일 가능성 | Swift / iOS 공식 지원 | ❌ |
표만 보면 Qwen이 더 풍부하다. 음색 캐릭터도 더 살아 있고, 자연어로 음색을 설계하거나 보이스 클로닝까지 되는 건 Supertonic에서는 못 한다. 그래서 데스크톱 GPU에서 콘텐츠 제작용으로는 Qwen이 우위.
하지만 내 관심사는 다른 데 있다. Supertonic의 Swift 공식 지원이 검증되면, iPhone 안에서 네트워크 없이 한국어 TTS가 돌아가는 앱이 가능해진다. ONNX 99M짜리는 iPhone 칩에 충분히 올라가는 크기다. 이게 되면 ElevenLabs API에 매번 돈을 내고 호출하던 구조에서 벗어날 수 있다. 그래서 객관적으로는 Qwen이 미세하게 앞서지만, 다음에 시간을 쓸 곳은 Supertonic의 iOS 빌드다.
ASR — Qwen3-ASR-1.7B 한 가지만 직접#
ASR 쪽은 후보가 더 적었다. Qwen3-ASR를 직접 굴려봤고, 비교 기준으로는 ElevenLabs Scribe의 출력을 정답으로 두었다.
설치는 같은 패턴. uv pip install qwen-asr, GPU bf16에서 1.7B 모델이 약 13GB VRAM. 4090에서 충분히 돈다. 첫 실행 한국어 자동 감지도 잘 됐다.
from qwen_asr import Qwen3ASRModel
import torch
model = Qwen3ASRModel.from_pretrained(
"Qwen/Qwen3-ASR-1.7B",
dtype=torch.bfloat16,
device_map="cuda:0",
max_inference_batch_size=1,
max_new_tokens=2048,
)
r = model.transcribe(audio="voice.wav", language="korean")
print(r[0].text)
테스트 대상은 37분짜리 한국어 회의 통화 녹음. 같은 파일을 ElevenLabs Scribe에 통과시킨 결과를 정답으로 두고, Qwen 출력과 비교했다.
함정 하나: 긴 오디오 자동 청크의 함정#
Qwen3-ASR에는 자체 청크 분할 로직이 있어서 긴 오디오를 그대로 넣어도 된다고 한다. 그런데 1.7B 모델이 1200초(20분) 청크에서 한국어 합성을 하다가 한 문장이 무한히 반복되는 repetition collapse에 빠졌다.
출력 끝부분: ”…피지나 전쟁에서의 원래 기능과 유아의 스스로 싸움을 잘 해야 한다. 피지나 전쟁에서의 원래 기능과 유아의 스스로 싸움을 잘 해야 한다…” (30회 반복)
해결은 단순했다. ffmpeg -f segment -segment_time 300으로 5분 단위 사전 분할 후 세그먼트별로 transcribe를 호출, 결과를 ## [mm:ss] 헤더와 함께 이어 붙였다. 5분 청크에서는 repetition이 안 나타난다.
정확도 비교 — ElevenLabs vs Qwen3-ASR#
같은 5분 구간을 두 출력에서 줄지어 보면 격차가 명확하다.
| 항목 | ElevenLabs | Qwen3-ASR-1.7B |
|---|---|---|
| 타임스탬프 | 발화 단위 SRT | 5분 청크 헤더만 |
| 화자 분리 | [Speaker 0] 라벨 | ❌ |
| 구두점·문장 | . , ? 완전 | ❌ 띄어쓰기만 |
| 비언어 표시 | [기침] | ❌ |
| 영어·고유명사 | ExPedia, Wiki.js, PDF 원형 보존 | 모두 한글 음차 |
핵심 단어 매칭은 더 안 좋다. 회의에서 자주 등장한 단어들을 보면:
| 정답 (ElevenLabs) | Qwen3-ASR 출력 |
|---|---|
| 법무정보시스템 | 본무정고 시태 |
| ExPedia | 이익스피디아 |
| 미전처 | 미전차 |
| Wiki.js | 위키백스 |
| PHP | 피지피 |
| 콘텐츠 | 관제체 |
| 갱신 | 게시 (의미 정반대!) |
| 유휴지 | 유유지 |
| 딥페이크 필터 | 채집필터 |
같은 오인이 통화 내내 반복됐다. “본무정고 시태”는 50회 넘게, “유유지”는 50회 넘게 등장한다. 한 번 잘못 잡으면 그 단어가 계속 그 형태로 나온다.
대략적인 WER을 매겨보면 30~40% 정도. 일반 조사·동사 어미는 정확하지만, 명사·고유명사·영어 단어에서 누적되는 오류가 너무 많다.
전처리로 살릴 수 있을까#
후처리(LLM으로 고유명사 보정)보다 먼저 오디오 전처리로 풀 수 있는지 시도해봤다.
먼저 원본 진단. 회의 통화 녹음의 RMS가 −36 dB(정상 −20 ~ −25), Peak −10.9 dB, SNR이 약 8 dB로 매우 낮다. 노이즈 floor와 발화 수준의 차이가 8 LU 정도밖에 안 되는 전형적인 원거리 폰 녹음이다.
전처리 6변형으로 같은 5분 구간을 굴려봤다.
- A: 원본 그대로
- B:
loudnorm(음량 정규화) - C:
afftdn(FFT 노이즈 감쇠) - D:
highpass=80, lowpass=8000(밴드패스) - E: B + C 결합
- F: HPF + afftdn + compand + loudnorm (풀 파이프라인)
5분 결과를 36분 전체로 확장해 키워드 매칭(정답 단어 +회 / 알려진 오인 단어 −회)을 세어봤다.
| 전처리 | 정답 매칭 | 오인 매칭 |
|---|---|---|
| baseline (전처리 없음) | +24 | −46 |
| D_bandpass (80~8kHz) | +40 (+67%) | −24 (−48%) |
| F_full (HPF+denoise+compand+norm) | +12 (누락 과다) | −4 |
의외의 결과 1: 단순 밴드패스 필터(80Hz HPF + 8kHz LPF) 하나로 한국어 고유명사 정답률이 67% 증가했다. baseline에서 “본무정고 시태”로 50회 오인되던 게 “법무정보”로 4회 정확히 잡혔고, “미전처”도 4회 정답, “위키피디아”도 4회 정답.
의외의 결과 2: 풀 파이프라인(F)은 오히려 역효과였다. compand의 다이내믹 압축이 작은 발화를 과압축해서 일부 음성이 모델에 도달하지 못했다. 출력 길이가 baseline 대비 31% 줄었다. “최대한 처리”가 항상 좋은 게 아니다.
한계: 영어 단어(ExPedia, Wiki.js, PHP, RAG)와 발음이 동일한 한국어 고유명사(“유휴지” ↔ “유유지”)는 어떤 전처리에서도 미해결. 이건 1.7B 모델의 어휘 학습 부족이지 오디오 품질 문제가 아니다.
ASR 결론 — 50% 수준, 회의록은 ElevenLabs#
ElevenLabs를 100점이라고 하면 Qwen3-ASR-1.7B는 체감 50% 정도. 전처리(밴드패스)로 끌어올려도 60% 정도까지. 차이가 가장 큰 부분은 셋이다.
- 영어 코드스위치 미지원 — 영어 단어가 다 한글 음차로 나온다.
- 고유명사 학습 부족 — 회사·기관명을 일반 단어로 치환.
- 구두점·화자 분리 없음 — 회의록으로 쓰려면 거의 다 후처리해야 한다.
회의 통화 녹음에는 부족하지만, 깨끗한 오디오(예: YouTube 강의나 인터뷰, 방송 음원)에는 충분히 쓸 만하지 않을까 기대한다. 자막 1차 패스나 음성 인덱싱 정도라면.
그리고 무엇보다, 무료다. ElevenLabs는 분당 과금되지만 Qwen3-ASR은 4090만 있으면 무제한이다. 37분짜리 회의 통화를 GPU에서 100초 정도면 끝낸다(16배 실시간). 정확도가 50%라도, 콘텐츠 검색용 인덱싱이나 대주제 파악용으로는 충분히 가치 있다.
정리#
- TTS: Qwen3-TTS와 Supertonic 두 개가 살아남았고, Qwen이 미세하게 앞섰다. 하지만 다음 실험은 Supertonic Swift 빌드로 iOS on-device TTS 가능성을 확인하는 쪽.
- ASR: Qwen3-ASR-1.7B는 ElevenLabs 대비 50% 수준. 회의록은 어렵다. 깨끗한 오디오 자막용, 검색 인덱싱용으로는 무료의 가치 있음.
- 공통: 1.7B 정도의 모델은 영어 코드스위치와 한국어 고유명사에서 학습 부족이 드러난다. 더 큰 모델이나 도메인 fine-tuning이 다음 단계.
- 전처리 인사이트: ASR 정확도 개선은 “최대한 처리”가 아니라 “필요한 만큼만 처리”가 맞다. 단순 밴드패스 한 줄이 풀 파이프라인보다 잘 먹혔다.
오픈소스 음성 도구는 빠르게 좋아지고 있다. 1년 전만 해도 fish-speech도 못 굴렸는데, 지금은 Qwen 1.7B 모델이 4090 한 대에서 실시간보다 빠르게 돈다. 이 추세면 내년쯤엔 ElevenLabs 수준의 회의록까지 오픈소스로 가능할지도 모른다.
당분간은 ElevenLabs 구독을 끊을 수는 없을 것 같다. 하지만 Supertonic 위에 iOS TTS 앱을 한 번 올려보고 싶다는 마음은 이 실험에서 가장 크게 남은 것이다.