Qwen3-TTS
Qwen3-TTS는 고품질 텍스트 음성 합성을 위한 Mimi 디코더 기반 12Hz 코덱 언어 모델입니다. 기본 MLX 경로는 이제 1.7B Base bf16 번들을 사용하며, 더 작은 다운로드가 필요하면 8-bit 번들도 사용할 수 있습니다. int4는 TTS 품질 문제로 중단되었습니다.
파이프라인
음성 합성은 3단계 파이프라인을 따릅니다:
- Talker — 입력 텍스트를 12.5 Hz로 첫 번째 코드북 토큰으로 변환하는 28 레이어 트랜스포머
- Code Predictor — 첫 번째 코드북 은닉 상태로부터 나머지 15개 코드북을 예측하는 5 레이어 트랜스포머
- Mimi Codec Decoder — 16개 코드북 토큰을 모두 24 kHz 오디오 파형으로 변환
아키텍처
Talker
Talker는 텍스트 입력으로부터 코덱 토큰을 생성하는 핵심 자동 회귀 모델입니다.
| 파라미터 | 값 |
|---|---|
| 레이어 | 28 |
| 은닉 차원 | 1024 |
| Query 헤드 | 16 |
| Key/Value 헤드 | 8 (GQA) |
| MLP | SwiGLU |
| 위치 인코딩 | RoPE |
Code Predictor
첫 번째 코드북의 은닉 상태를 받아 나머지 15개 코드북을 병렬로 예측하는 경량 5 레이어 트랜스포머입니다. 이로써 스텝당 전체 Talker를 16번 실행하는 것을 피할 수 있습니다.
Mimi Codec Decoder
Mimi 디코더는 양자화된 코덱 토큰을 다시 오디오로 변환합니다:
- RVQ 디코드 (16 코드북)
- Pre-convolution (512 → 1024 채널)
- Pre-transformer (1024 → 512 병목, 8 레이어, SwiGLU + LayerScale)
- 업샘플 (2x, 2x)
- SEANet 디코더 (8x, 5x, 4x, 3x 업샘플 단계)
- 24 kHz 파형 출력
모델 변형
| 모델 | 크기 | HuggingFace |
|---|---|---|
| Qwen3-TTS-0.6B Base (8-bit) | 1.3 GB | aufklarer/Qwen3-TTS-12Hz-0.6B-Base-MLX-8bit |
| Qwen3-TTS-1.7B Base (8-bit) | 2.4 GB | aufklarer/Qwen3-TTS-12Hz-1.7B-Base-MLX-8bit |
| Qwen3-TTS-1.7B Base (bf16, default) | 3.9 GB | aufklarer/Qwen3-TTS-12Hz-1.7B-Base-MLX-bf16 |
| Qwen3-TTS-0.6B CustomVoice (bf16) | 1.8 GB | aufklarer/Qwen3-TTS-12Hz-0.6B-CustomVoice-MLX-bf16 |
| Qwen3-TTS CoreML (FP16) | 2.1 GB | aufklarer/Qwen3-TTS-CoreML |
CoreML 백엔드
CoreML은 컴파일된 구성 요소 6개를 실행합니다. 연산 장치는 선택한 번들에 따라 달라집니다.
- TextProjector — 텍스트 토큰 임베딩을 공유 은닉 공간으로 투영
- CodeEmbedder — 첫 번째 코드북 토큰과 제어 토큰을 임베딩
- MultiCodeEmbedder — 1–15번 코드북의 토큰을 임베딩
- CodeDecoder — 무상태 KV 캐시(최대 256 위치)를 갖는 28 레이어 자동 회귀 트랜스포머
- MultiCodeDecoder — 1–15번 코드북용 5 레이어 코드 프레딕터
- SpeechDecoder — Mimi 코덱 디코더, 16개 코드북 토큰을 24 kHz 오디오로 변환
# CoreML synthesis
.build/release/speech speak "Hello, world!" --engine coreml -o hello.wav
# CoreML uses temperature 0.8 by default (required for quality output)
.build/release/speech speak "Long text here." --engine coreml --temperature 0.9 -o out.wav
0.6B: CoreML CodeDecoder는 고정 256 위치 KV 캐시를 사용합니다. 긴 구문은 개별 문장으로 분할해야 합니다. 디코드 토큰은 프리필 이후 남은 캐시 슬롯에 맞도록 자동으로 제한됩니다.
실험적 1.7B CoreML 내보내기
FP16이 체크포인트 검증을 통과하지 못해 디코더는 FP32로 연산합니다. 캐시 텐서는 FP16을 유지합니다.
6개 구성 요소 변환기는 1.7B Base와 1024개 위치를 갖는 상태 유지 CodeDecoder를 지원합니다. Talker와 화자 임베딩은 2048차원이며, 1024차원 코드 예측기에는 학습된 입력 투영이 포함됩니다.
Swift는 0.6B/256 및 1.7B/1024 번들을 지원하며 기본값은 계속 0.6B입니다. 실험적인 1.7B 번들은 기본적으로 CPU를 사용하며, --speaker-embedding으로 미리 준비한 2048채널 Float32 .npy 화자 임베딩을 제공해야 합니다. GPU/ANE 및 iOS는 별도 검증이 필요합니다.
캐시에는 프롬프트와 오디오 위치가 포함됩니다. SpeechDecoder의 기본 한도는 별도로 125프레임(10초)이며, CodeDecoder 캐시를 늘려도 확장되지 않습니다.
speech qwen3-tts-coreml "Hello world" \
--model aufklarer/Qwen3-TTS-1.7B-CoreML \
--speaker-embedding speaker-17b.npy --output hello-17b.wav
CLI 사용법
텍스트로부터 음성 생성:
.build/release/speech speak "Hello, world!" --output hello.wav
옵션
| 플래그 | 설명 |
|---|---|
--engine | TTS 엔진: qwen3 (MLX, 기본값), coreml (CoreML/GPU), 또는 cosyvoice |
--output, -o | 출력 WAV 파일 경로 |
--language | 언어 (기본값: english). 화자의 네이티브 방언을 사용하려면 생략. |
--model | 모델 변형: base 또는 customVoice |
--speaker | 화자 음색 (--model customVoice 필요) |
--temperature | 샘플링 온도 (기본값: 0.3) |
--top-k | Top-k 샘플링 파라미터 |
--max-tokens | 생성할 최대 토큰 수 (기본값: 500) |
--stream | 스트리밍 활성화 — 생성 중 오디오 청크를 방출 |
--first-chunk-frames | 첫 스트림 청크의 프레임 수 |
--chunk-frames | 이후 스트림 청크당 프레임 수 |
--batch-file | 배치 합성을 위한 한 줄당 한 발화 텍스트 파일 경로 |
--batch-size | 배치 모드에서 병렬 처리되는 발화 수 |
예제
# Basic synthesis
.build/release/speech speak "The quick brown fox." -o fox.wav
# Streaming output
.build/release/speech speak "Long passage of text..." --stream -o stream.wav
# Batch synthesis from file
.build/release/speech speak --batch-file sentences.txt --batch-size 4 -o output_dir/
스트리밍
--stream 플래그는 생성 중 청크 단위 오디오 출력을 활성화합니다. 전체 발화가 완료될 때까지 기다리는 대신, 토큰이 생성되는 대로 오디오가 청크로 방출됩니다. 각 청크의 크기를 제어하려면 --first-chunk-frames와 --chunk-frames를 사용하세요.
배치 모드
여러 발화를 합성하려면 한 줄당 하나의 발화를 포함한 텍스트 파일과 함께 --batch-file을 사용하세요. --batch-size 플래그는 병렬로 처리되는 발화 수를 제어합니다.
성능
M2 Max에서 Qwen3-TTS는 약 0.55의 RTF(실시간 대비 속도)를 달성하며, 이는 실시간보다 빠르게 음성을 생성한다는 것을 의미합니다. compile() 워밍업을 사용하면 각 스텝은 약 37 ms가 소요됩니다.
기본 최대값은 500 토큰이며, 이는 12.5 Hz에서 약 40초의 오디오를 생성합니다. 더 높은 값을 설정하면 Metal GPU 워치독 타임아웃을 초과할 위험이 있으며, Apple Silicon에서 GPU가 컴포지터와 공유되기 때문에 시스템 재부팅이 발생할 수 있습니다.
언어
Qwen3-TTS는 다언어 텍스트-음성 합성을 지원합니다. 모델은 입력 언어를 자동으로 감지하여 그에 맞게 음성을 생성합니다.
Swift API
import Qwen3TTS
import AudioCommon
let model = try await Qwen3TTSModel.fromPretrained()
let audio = model.synthesize(text: "Hello, world!", language: "english")
try WAVWriter.write(samples: audio, sampleRate: 24000, to: URL(filePath: "hello.wav"))
로컬 전용 번들
앱이 모델 획득과 저장을 직접 관리할 때는 fromLocal을 사용하세요. 기본 TTS 모델과 음성 토크나이저 디렉터리를 따로 전달합니다. 이 호출은 캐시를 해석하거나 네트워크에 연결하지 않으며, MLX 모듈을 할당하기 전에 기본 번들의 config.json을 읽습니다.
let model = try Qwen3TTSModel.fromLocal(
modelDirectory: ttsDirectory,
tokenizerDirectory: speechTokenizerDirectory
)
fromLocal의 기본값은 .none이므로 프로세스 전체 Metal wired-memory 한도를 바꾸지 않습니다. fromPretrained는 .pin(fraction: 0.9) 기본값을 유지합니다. 두 사전 학습 로더 모두 별도의 tokenizerCacheDir을 받습니다.
진단
Qwen3-TTS는 모델 로딩 및 추론 진단을 stdout이나 stderr 대신 AudioLog.modelLoading과 AudioLog.inference로 보냅니다. 개수, 형상, 시간 정보는 표시되지만 호출자가 제공한 언어와 화자 값은 비공개로 유지되며 입력 텍스트는 기록되지 않습니다.