Magpie-TTS Multilingual
Apple Silicon 위의 NVIDIA Magpie-TTS Multilingual 357M Swift 구현 — NeMo의 22.05 kHz Nano-Codec을 기반으로 한 자기회귀 멀티 코드북 TTS 모델. 9개 언어(영어, 스페인어, 독일어, 프랑스어, 이탈리아어, 베트남어, 힌디어, 중국어, 일본어), 5개 내장 스피커. INT4(~247 MB) 또는 INT8(~411 MB)로 양자화. 스트리밍 지원, 첫 패킷 지연 ~120 ms.
9개 언어를 하나의 작은 번들로 일관된 음성으로 말해야 할 때 적합합니다. 5개 내장 스피커는 모든 언어에서 정체성이 안정적입니다 — 다국어 어시스턴트, 교육 앱, 코드 스위칭이 있는 오디오북 나레이션에 유용. 제로샷 음성 복제가 필요하면 CosyVoice3, Qwen3-TTS Base, VoxCPM2를 사용하세요.
아키텍처
Magpie는 4-bundle MLX 파이프라인입니다: 텍스트 인코더 → 크로스 어텐션 디코더 → LocalTransformer 코드북 헤드 → 인과적 HiFi-GAN 오디오 코덱. prefill과 step 진입점 사이에서 디코더 가중치를 공유하여 상위 FluidInference의 CoreML 레이아웃과 호환됩니다.
| 단계 | 모듈 | 세부 정보 |
|---|---|---|
| 1. 토큰화 | MagpieTokenizer | 언어별 G2P(IPA 사전 / byT5 바이트 / 병음 / 가타카나), 공유 2360-token 어휘 + tokenizer별 오프셋, 항상 EOS 추가 |
| 2. 텍스트 인코더 | MagpieTextEncoder | 인과적 Transformer 6층, d=768, k=3 conv FFN |
| 3. Decoder prefill | MagpieDecoder | 크로스 어텐션 인과적 12층. 110-frame 내장 스피커 컨텍스트 + BOS를 KV 캐시에 시드. |
| 4. LocalTransformer | MagpieLocalTransformer | 1층 코드북 AR 헤드, d=256. 디코더 hidden을 조건으로 프레임당 8개 코드북을 순차 샘플링. |
| 5. Decoder step | MagpieDecoder | EOS 또는 500-frame 한도(~23초)까지 프레임당 1회 AR 진행. |
| 6. NanoCodec | MagpieNanoCodec | FSQ 역변환 → 인과적 HiFi-GAN → 22.05 kHz 모노 파형. |
언어 및 G2P
SDK의 testMultilingualRoundTrip은 9개 언어 모두 Qwen3-ASR로 라운드트립됨을 검증합니다. 각 언어는 맞춤형 파이프라인을 가집니다:
| 언어 | 코드 | G2P 파이프라인 |
|---|---|---|
| 영어 | en | CMU IPA 사전(125k 항목, 번들 포함) |
| 스페인어 | es | 스페인어 IPA 사전(번들 포함) |
| 독일어 | de | 독일어 IPA 사전(번들 포함) |
| 프랑스어 | fr | byT5 UTF-8 바이트 인코더 |
| 이탈리아어 | it | byT5 UTF-8 바이트 인코더 |
| 베트남어 | vi | byT5 UTF-8 바이트 인코더 |
| 힌디어 | hi | 데바나가리 코드포인트 조회 + last-wins 서브 어휘 |
| 중국어 보통화 | zh | NLTokenizer(.simplifiedChinese) 단어 분할 + Apple .mandarinToLatin + 번들 병음→IPA 사전 + #N 성조 마커 |
| 일본어 | ja | CFStringTokenizer 한자 발음 + NFC 보존 탁음 + 평판 피치 마커 + 조사/인사 오버라이드 |
공유 2360-token 어휘는 각 언어의 서브 토크나이저를 오프셋과 함께 연결합니다(MagpieSubVocab에 기록). 텍스트 임베딩은 BOS / EOS용으로 2행을 추가하며, eos_id = 2361이 모든 입력 시퀀스 끝에 추가됩니다.
내장 스피커
체크포인트에 5개 스피커 컨텍스트(각 110프레임 × 768차원)가 내장되어 모든 AR 디코드의 접두사로 사용됩니다. 스피커 정체성은 9개 언어 모두에서 일관됩니다.
| 인덱스 | CLI 이름 | 정체성 |
|---|---|---|
| 0 | sofia | Sofia(기본값) |
| 1 | aria | Aria |
| 2 | jason | Jason |
| 3 | leo | Leo |
| 4 | john | John Van Stan |
모델 변형
| 변형 | 디스크 | RAM(로드+디코드) | HuggingFace |
|---|---|---|---|
| INT4(기본값) | ~247 MB | ~1.3 GB | aufklarer/Magpie-TTS-Multilingual-357M-MLX-4bit |
| INT8 | ~411 MB | ~1.6 GB | aufklarer/Magpie-TTS-Multilingual-357M-MLX-8bit |
두 번들 모두 MLX flat affine 양자화(mlx_affine_flat, group size 64)를 사용하며 로드 시 FP32로 역양자화 — 런타임 활성화는 풀 정밀도입니다. 본 모델은 INT4와 INT8가 청각적으로 구별되지 않으므로 저장 공간 여유가 없다면 INT4를 선택하세요.
CLI 사용법
# 영어, 탐욕적 디코딩
speech speak "Hello, world." --engine magpie --magpie-speaker aria \
--magpie-temperature 0 -o out.wav
# 스페인어(9개 언어 중 --language로 선택)
speech speak "Hola, mundo." --engine magpie --language es \
--magpie-speaker aria -o out.wav
# 일본어 — 확률적 디코딩 필요(탐욕적은 첫 구절에서 멈춤)
speech speak "こんにちは世界、これは音声合成システムです。" \
--engine magpie --language ja --magpie-temperature 0.6 \
--magpie-top-k 80 --seed 42 -o out.wav
# 스트리밍 합성 + 재생
speech speak "Streaming test" --engine magpie --stream --play
# 5개 내장 스피커 나열
speech speak --engine magpie --list-speakers
# 사전 음소화된 IPA는 언어별 G2P를 우회
speech speak "həˈloʊ" --engine magpie --magpie-prephonemized -o out.wav
옵션
| 옵션 | 기본값 | 설명 |
|---|---|---|
--magpie-variant | int4 | 양자화 변형: int4 또는 int8 |
--magpie-speaker | sofia | 내장 스피커: sofia, aria, jason, leo, john |
--magpie-temperature | 0.6 | 샘플링 온도(0 = 탐욕적) |
--magpie-top-k | 80 | Top-k 샘플링 필터 |
--magpie-max-frames | 500 | 코덱 프레임 하드 한도(~23초) |
--magpie-min-frames | 4 | EOS 허용 전 최소 프레임 수 |
--magpie-prephonemized | 꺼짐 | 입력을 IPA / 음소 스트림으로 처리; 언어별 G2P 건너뜀 |
--language | english | 언어별 토크나이저 선택 |
--stream | 꺼짐 | 단일 WAV 대신 AsyncStream<AudioChunk> 출력 |
--seed | — | 재현 가능한 Gumbel 샘플링 |
한 단어보다 긴 일본어 입력은 확률적 디코딩이 필요합니다(--magpie-temperature 0.6 --magpie-top-k 80 --seed 42는 NeMo의 참조 테스트와 일치). 탐욕적은 첫 구절에서 멈춤 — 평판 피치 휴리스틱이 단어별 진실값에서 벗어나기 때문.
음성 복제 — 지원 안 됨
Magpie는 모델 자체에 제로샷 스피커 컨디셔닝이 없습니다; 번들에는 5개 내장 정체성만 포함됩니다. CLI는 공유 --voice-sample, --speaker, --instruct 플래그를 거부하며 --magpie-speaker 또는 복제 지원 엔진(Qwen3-TTS Base, CosyVoice3, VoxCPM2)으로 안내합니다.
성능(M4 Pro)
| 설정 | 오디오 | 벽시계 | RTF |
|---|---|---|---|
| 배치 INT4 탐욕적, 짧은 프롬프트 | 2.8 s | 0.88 s | 0.32 |
| 배치 INT4 탐욕적, 문장 | 5.8 s | 1.35 s | 0.23 |
| 배치 INT4 샘플링, 23초 출력 | 23 s | 5.6 s | 0.24 |
| 스트리밍 INT4 샘플링 | 23 s | 21.6 s | 0.93 |
스트리밍 모드에서 모델 로드 후 첫 패킷 지연은 ~120 ms. 스트리밍 RTF가 높은 이유는 각 청크 출력 시 코덱이 전체 코드 버퍼에 재실행되기 때문(향후 상태 캐시로 개선 가능).
Swift API
import MagpieTTS
let model = try await MagpieTTS.fromPretrained(variant: .int4)
// 배치 합성(en/es/de/fr/it/vi/hi/zh — 탐욕적 작동)
let audio = try model.synthesize(
text: "Hello, world.",
speaker: .aria,
language: .english,
params: MagpieTTSParams(temperature: 0, topK: 1, maxSteps: 500))
// 일본어 — 확률적 샘플링 사용
let audioJA = try model.synthesize(
text: "こんにちは世界、これは音声合成システムです。",
speaker: .aria,
language: .japanese,
params: MagpieTTSParams(temperature: 0.6, topK: 80,
maxSteps: 300, seed: 42))
// 스트리밍(AsyncStream<AudioChunk>)
let stream = model.synthesizeStream(
text: "Streaming text",
speaker: .aria,
language: .english,
firstChunkFrames: 8,
framesPerChunk: 25)
for try await chunk in stream {
// chunk.samples는 22.05 kHz 모노 Float32
}
CoreML 백엔드 (--engine magpie-coreml)
MLX 번들과 함께 Magpie는 CoreML 번들도 제공합니다 (aufklarer/Magpie-TTS-Multilingual-357M-CoreML-8bit, ~342 MB INT8). 4개의 .mlmodelc 패키지 — text_encoder, decoder_prefill, decoder_step, nanocodec_decoder — 가 ANE / GPU에서 실행되고; Swift 측의 FSQ 역변환이 샘플링된 코드를 코덱이 사용하는 32차원 잠재 변수로 변환합니다.
# 8개 언어 (일본어 제외), 5명의 기본 화자
speech speak "Hello world." --engine magpie-coreml --magpie-speaker aria -o hi.wav
speech speak "Hola mundo." --engine magpie-coreml --language es --magpie-speaker leo -o es.wav
# --language ja는 자동으로 MLX 백엔드로 라우팅 (stderr 알림)
speech speak "こんにちは" --engine magpie-coreml --language ja -o ja.wav
--engine magpie와의 주의사항:
- 현재는 하이브리드 파이프라인. NeMo가 훈련하는 실제 코드북 샘플링 헤드인 1-레이어 LocalTransformer와 8개의 오디오 임베딩 테이블이 CoreML 번들에 포함되어 있지 않습니다. 첫 합성 시 CoreML 엔진은 두 가지를 모두 구동하기 위해 MLX INT4 번들을 지연 로드합니다. ASR 라운드트립은 MLX 백엔드와 비트 단위로 동일합니다; 차이점은 이 엔진이 MLX 번들도 다운로드한다는 점입니다. ANE 전용 iOS 배포를 위한 순수 CoreML 경로는 번들이
local_transformer/*.npy+audio_embedding_*.npy를 제공하고 Swift Accelerate LT가 필요합니다 (후속 작업 추적 중). - 스트리밍 미지원.
nanocodec_decoder.mlmodelc는 고정 64 프레임 윈도우로 추적됩니다. 더 긴 시퀀스는 내부적으로 청크로 나뉘지만, 청크 경계에서 발행하면 첫 패킷 지연 시간이 ~3초가 됩니다.--stream은 실행 가능한 오류로 거부됩니다. - 일본어 토크나이저 없음. CoreML 번들은 아직 JA 토크나이저 JSON을 제공하지 않습니다. 이 엔진에서
--language ja는 자동으로 MLX 백엔드로 폴백합니다.
화자 순서는 CoreML 번들의 speaker_info.json과 일치합니다 (0=John, 1=Sofia, 2=Aria, 3=Jason, 4=Leo — MLX와 다름); 화자 열거형은 내부적으로 매핑되어 CLI 이름이 두 엔진에서 모두 작동합니다.
구현 노트
NeMo 스타일 다국어 TTS 이식 시 알아둘 버그 3개:
- FSQ 바닥 나눗셈 — MLX-swift의
/는 실수 나눗셈(mlx_divide); NeMo의 FSQ 역변환은 Python//를 사용.MLX.floorDivide(...)를 사용하지 않으면 모든 FSQ 슬롯이 소수 오프셋으로 디코딩되어 코덱이 오디오를 흐리게 합니다. - 서브 어휘 오프셋 — NeMo의
AggregatedTTSTokenizer는 언어별 어휘를 오프셋과 함께 연결합니다. 단순한 전역 first-occurrence 맵은 항상 영어 영역에 떨어져 다른 언어에서 무의미한 오디오를 생성합니다. - 힌디어 last-wins 중복 제거 —
HindiCharsTokenizer는 자체 어휘 내에 중복 데바나가리 항목을 방출합니다(CHARSET와 PUNCT_LIST 중복). Python의{l: i for i, l in enumerate(tokens)}dict 컴프리헨션은 마지막 할당을 유지; 이를 따르고 first-occurrence를 사용하지 마세요.
세 가지 수정 모두 Swift 모듈에 인라인으로 문서화되어 있습니다.
출처
- 상위 가중치: nvidia/magpie_tts_multilingual_357m(NVIDIA Open Model License)
- 코덱: nvidia/nemo-nano-codec-22khz-1.89kbps-21.5fps
- 논문: NanoCodec: Towards High-Quality Ultra Fast Speech LLM Inference(2025)
- 참조 CoreML 이식: FluidInference/mobius
- Swift 모듈: MagpieTTS (MLX) + MagpieTTSCoreML (CoreML)
- CoreML 번들: aufklarer/Magpie-TTS-Multilingual-357M-CoreML-8bit
라이선스
- 모델 가중치: NVIDIA Open Model License(상업적 사용 가능; HuggingFace 페이지 참조)
- Swift 이식 + 번들 IPA / 병음 사전: 상위 NeMo와 동일(사전은 Apache 2.0, 모델은 NVIDIA OML)