Magpie-TTS Multilingual
NVIDIA Magpie-TTS Multilingual 357M ใน Swift บน Apple Silicon — โมเดลข้อความเป็นเสียงพูดแบบ autoregressive หลาย codebook บน Nano-Codec 22.05 kHz ของ NeMo รองรับ 9 ภาษา (อังกฤษ สเปน เยอรมัน ฝรั่งเศส อิตาลี เวียดนาม ฮินดี จีนกลาง ญี่ปุ่น) พร้อมเอกลักษณ์ผู้พูดสำเร็จรูป 5 ตัว ปล่อยในรูปแบบที่ผ่านการลดความละเอียดเป็น INT4 (~247 MB) หรือ INT8 (~411 MB) พร้อมรองรับ streaming และมีหน่วงของแพ็กเก็ตแรกประมาณ 120 ms
Magpie คือตัวเลือกที่ถูกต้องเมื่อคุณต้องการ bundle ขนาดเล็กตัวเดียวที่พูดได้ 9 ภาษาด้วยเสียงสม่ำเสมอ ผู้พูดสำเร็จรูปทั้ง 5 คนยังคงเอกลักษณ์เสถียรข้ามภาษา — เป็นประโยชน์สำหรับผู้ช่วยหลายภาษา แอปการศึกษา หรือการบรรยายหนังสือเสียงที่มีการสลับภาษา สำหรับการโคลนเสียงแบบ zero-shot ให้ใช้ CosyVoice3, Qwen3-TTS Base หรือ VoxCPM2 แทน
สถาปัตยกรรม
Magpie คือ pipeline MLX 4 bundle: text encoder → decoder cross-attention → หัว codebook LocalTransformer → codec เสียง Causal HiFi-GAN bundle เหล่านี้ใช้ trọng số decoder ร่วมกันระหว่างจุดเข้า prefill และ step เพื่อให้ตรงกับ layout CoreML ของ FluidInference upstream
| ขั้นตอน | โมดูล | รายละเอียด |
|---|---|---|
| 1. Tokenisation | MagpieTokenizer | Per-language G2P (IPA dict / byT5 bytes / pinyin / katakana), shared 2360-token vocab with per-tokenizer offsets, always-appended EOS |
| 2. Text encoder | MagpieTextEncoder | 6 causal Transformer layers, d=768, k=3 conv FFN |
| 3. Decoder prefill | MagpieDecoder | 12 causal layers with cross-attention. Seeds the 110-frame baked speaker context + BOS into the KV cache. |
| 4. LocalTransformer | MagpieLocalTransformer | 1-layer codebook AR head, d=256. Samples the 8 codebooks per frame sequentially given the decoder hidden. |
| 5. Decoder step | MagpieDecoder | One AR step per frame until EOS or 500-frame cap (~23 s). |
| 6. NanoCodec | MagpieNanoCodec | FSQ inverse → causal HiFi-GAN → 22.05 kHz mono waveform. |
ภาษาและ G2P
ทั้ง 9 ภาษาผ่านการ round-trip ผ่าน Qwen3-ASR ใน testMultilingualRoundTrip ของ SDK แต่ละภาษามี pipeline ที่ปรับแต่งเฉพาะ:
| ภาษา | รหัส | Pipeline G2P |
|---|---|---|
| อังกฤษ | en | พจนานุกรม CMU IPA (125k รายการ มาด้วย) |
| สเปน | es | พจนานุกรม IPA สเปน (มาด้วย) |
| เยอรมัน | de | พจนานุกรม IPA เยอรมัน (มาด้วย) |
| ฝรั่งเศส | fr | ตัวเข้ารหัสไบต์ UTF-8 byT5 |
| อิตาลี | it | ตัวเข้ารหัสไบต์ UTF-8 byT5 |
| เวียดนาม | vi | ตัวเข้ารหัสไบต์ UTF-8 byT5 |
| ฮินดี | hi | การค้นหา codepoint Devanagari + sub-vocab last-wins |
| จีนกลาง | zh | การแบ่งคำ NLTokenizer(.simplifiedChinese) + Apple .mandarinToLatin + พจนานุกรม pinyin → IPA ที่มาด้วย + เครื่องหมายเสียงวรรณยุกต์ #N |
| ญี่ปุ่น | ja | การอ่าน kanji ผ่าน CFStringTokenizer + dakuten ที่รักษา NFC + เครื่องหมาย pitch heiban + override สำหรับคำเชื่อม/คำทักทาย |
Vocab ที่ใช้ร่วมกัน 2360 รายการเชื่อม sub-tokenizer ของแต่ละภาษาตามลำดับด้วย offset เฉพาะภาษา (บันทึกใน MagpieSubVocab) Text-embedding เพิ่มอีก 2 แถวหลัง vocab สำหรับ BOS / EOS; eos_id = 2361 ถูกเพิ่มเข้าทุกลำดับอินพุต
ผู้พูดสำเร็จรูป
Checkpoint ฝัง context ผู้พูด 5 ตัว (110 frame × 768 มิติแต่ละตัว) ใช้เป็น prefix ของทุกการถอดรหัส AR เอกลักษณ์ผู้พูดสม่ำเสมอทั่วทั้ง 9 ภาษา
| ดัชนี | ชื่อ CLI | เอกลักษณ์ |
|---|---|---|
| 0 | sofia | Sofia (ค่าเริ่มต้น) |
| 1 | aria | Aria |
| 2 | jason | Jason |
| 3 | leo | Leo |
| 4 | john | John Van Stan |
รุ่นย่อยของโมเดล
| รุ่นย่อย | ดิสก์ | RAM (load + decode) | 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 |
ทั้งสอง bundle ใช้การลดความละเอียดแบบ flat affine ของ MLX (mlx_affine_flat, group size 64) และคืนความละเอียดกลับเป็น FP32 เมื่อโหลด — activation ในเวลา runtime อยู่ที่ความละเอียดเต็ม INT4 แยกไม่ออกจาก INT8 ทางการได้ยินสำหรับโมเดลนี้; เลือก INT4 เว้นแต่คุณมีพื้นที่จัดเก็บเหลือเฟือ
การใช้งาน CLI
# ภาษาอังกฤษ การถอดรหัสแบบ greedy
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
# ญี่ปุ่น — ต้องการการถอดรหัสแบบสุ่ม (greedy ติดอยู่ที่วลีแรก)
speech speak "こんにちは世界、これは音声合成システムです。" \
--engine magpie --language ja --magpie-temperature 0.6 \
--magpie-top-k 80 --seed 42 -o out.wav
# การสังเคราะห์แบบ streaming พร้อมเล่นเสียง
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 = greedy) |
--magpie-top-k | 80 | ตัวกรอง top-k สำหรับการสุ่ม |
--magpie-max-frames | 500 | ขีดจำกัดสูงสุดของจำนวน frame ของ codec (~23 s) |
--magpie-min-frames | 4 | จำนวน frame ขั้นต่ำก่อนอนุญาต EOS |
--magpie-prephonemized | off | ถือว่าอินพุตเป็นสตรีม IPA / phoneme; ข้าม G2P เฉพาะภาษา |
--language | english | เลือก pipeline tokenizer ตามภาษา |
--stream | off | ส่งออก AsyncStream<AudioChunk> แทน WAV เดียว |
--seed | — | การสุ่ม Gumbel ที่สามารถทำซ้ำได้ |
อินพุตภาษาญี่ปุ่นที่ยาวเกินคำเดียวต้องการการถอดรหัสแบบสุ่ม (--magpie-temperature 0.6 --magpie-top-k 80 --seed 42 สะท้อนการทดสอบอ้างอิงของ NeMo) Greedy ติดอยู่ที่วลีแรกเพราะ heuristic ของ pitch-accent heiban ออกนอกความจริงตามคำ
การโคลนเสียง — ไม่รองรับ
Magpie ไม่มีการกำหนดเงื่อนไขผู้พูดแบบ zero-shot ในโมเดล; มีเพียงเอกลักษณ์สำเร็จรูป 5 ตัวที่มาใน bundle CLI ปฏิเสธแฟล็กที่ใช้ร่วมกัน --voice-sample, --speaker และ --instruct พร้อมข้อผิดพลาดที่สามารถปฏิบัติได้ ชี้ผู้ใช้ไปที่แฟล็ก --magpie-speaker หรือ engine ที่รองรับการโคลน (Qwen3-TTS Base, CosyVoice3, VoxCPM2)
ประสิทธิภาพ (M4 Pro)
| การตั้งค่า | เสียง | เวลาจริง | RTF |
|---|---|---|---|
| Batch, INT4, greedy, prompt สั้น | 2.8 s | 0.88 s | 0.32 |
| Batch, INT4, greedy, ประโยค | 5.8 s | 1.35 s | 0.23 |
| Batch, INT4, sampled, เอาต์พุต 23 s | 23 s | 5.6 s | 0.24 |
| Streaming, INT4, sampled | 23 s | 21.6 s | 0.93 |
หน่วงของแพ็กเก็ตแรกในโหมด streaming อยู่ที่ ≈120 ms หลังโหลดโมเดล RTF ของ streaming สูงกว่าเพราะ codec ถูกเรียกใหม่บน buffer code ทั้งหมดในทุกการส่ง chunk (เวอร์ชันในอนาคตสามารถ cache สถานะ codec ได้)
API Swift
import MagpieTTS
let model = try await MagpieTTS.fromPretrained(variant: .int4)
// การสังเคราะห์แบบ batch (en/es/de/fr/it/vi/hi/zh — greedy ใช้ได้)
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))
// Streaming (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 เป็น Float32 mono 22.05 kHz
}
Backend CoreML (--engine magpie-coreml)
ควบคู่ไปกับ bundle MLX, Magpie ปล่อย bundle CoreML (aufklarer/Magpie-TTS-Multilingual-357M-CoreML-8bit, ~342 MB INT8) สี่แพ็กเกจ .mlmodelc — text_encoder, decoder_prefill, decoder_step, nanocodec_decoder — ทำงานบน ANE / GPU; FSQ inverse ฝั่ง Swift แปลง code ที่สุ่มแล้วเป็น latent 32 มิติที่ codec ใช้
# 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 จะ route อัตโนมัติไปยัง backend MLX (มีโน้ตใน stderr)
speech speak "こんにちは" --engine magpie-coreml --language ja -o ja.wav
ข้อควรระวังเทียบกับ --engine magpie:
- Pipeline แบบ hybrid ในปัจจุบัน LocalTransformer 1 layer (หัวลำเลียงตัวอย่าง codebook ที่ NeMo ฝึกจริง) และตาราง audio embedding 8 ตารางไม่ได้ปล่อยภายใน bundle CoreML ในการสังเคราะห์ครั้งแรก engine CoreML จะ lazy-load bundle MLX INT4 เพื่อขับเคลื่อนทั้งสองส่วน Round-trip ASR เหมือนกันบิตต่อบิตกับ backend MLX; ความแตกต่างคือ engine นี้ดึง bundle MLX มาด้วย เส้นทาง CoreML ล้วนสำหรับการ deploy บน iOS แบบ ANE-only ต้องการ bundle ที่ปล่อย
local_transformer/*.npy+audio_embedding_*.npyและ LT แบบ Swift Accelerate (ติดตามต่อไป) - ไม่รองรับ streaming
nanocodec_decoder.mlmodelcถูก trace ที่หน้าต่างคงที่ 64 frame เราแบ่งลำดับที่ยาวกว่าภายใน แต่หน่วงของแพ็กเก็ตแรกจะอยู่ที่ ~3 s หากเราปล่อยที่ขอบเขตของ chunk--streamถูกปฏิเสธพร้อมข้อผิดพลาดที่ปฏิบัติได้ - ไม่มี tokenizer ภาษาญี่ปุ่น Bundle CoreML ยังไม่ปล่อย JSON ของ tokenizer JA
--language jaกับ engine นี้จะ fallback อัตโนมัติไปที่ backend MLX
ลำดับผู้พูดตรงกับ speaker_info.json ของ bundle CoreML (0=John, 1=Sofia, 2=Aria, 3=Jason, 4=Leo — ต่างจาก MLX) และ enum ผู้พูดถูก map ภายในเพื่อให้ชื่อ CLI ใช้ได้กับทั้งสอง engine
หมายเหตุการนำไปใช้
สามบั๊กที่ควรรู้หากคุณกำลัง port TTS หลายภาษาสไตล์ NeMo:
- การหารแบบ floor ของ FSQ —
/ของ MLX-swift เป็นการหารจริง (mlx_divide); FSQ inverse ของ NeMo ใช้//ของ Python ใช้MLX.floorDivide(...)มิฉะนั้นทุกช่อง FSQ จะถอดรหัสเป็น offset เศษส่วนและ codec จะทำให้เสียงเบลอ - Offset ของ sub-vocab —
AggregatedTTSTokenizerของ NeMo เชื่อม vocab ตามภาษากับ offset แมป first-occurrence ทั่วโลกแบบง่ายจะลงเอยในพื้นที่ภาษาอังกฤษเสมอและสร้างเสียงไร้สาระสำหรับภาษาอื่น - Hindi last-wins dedup —
HindiCharsTokenizerปล่อยรายการ Devanagari ซ้ำ (CHARSET ซ้อนกับ PUNCT_LIST) Dict-comprehension{l: i for i, l in enumerate(tokens)}ของ Python เก็บการกำหนดค่าครั้งสุดท้าย; สะท้อนสิ่งนั้น อย่าใช้ first-occurrence
การแก้ทั้งสามอย่างได้รับการบันทึก inline ใน โมดูล Swift
แหล่งที่มา
- น้ำหนัก upstream: nvidia/magpie_tts_multilingual_357m (NVIDIA Open Model License)
- Codec: nvidia/nemo-nano-codec-22khz-1.89kbps-21.5fps
- Paper: NanoCodec: Towards High-Quality Ultra Fast Speech LLM Inference (2025)
- Port CoreML อ้างอิง: FluidInference/mobius
- โมดูล Swift: MagpieTTS (MLX) + MagpieTTSCoreML (CoreML)
- Bundle CoreML: aufklarer/Magpie-TTS-Multilingual-357M-CoreML-8bit
สัญญาอนุญาต
- น้ำหนักโมเดล: NVIDIA Open Model License (อนุญาตให้ใช้เชิงพาณิชย์; ดู PDF ที่ลิงก์ในหน้า HuggingFace)
- พอร์ต Swift + พจนานุกรม IPA / pinyin ที่มาด้วย: เหมือนกับ NeMo upstream (Apache 2.0 สำหรับพจนานุกรม, NVIDIA OML สำหรับโมเดล)