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。

何时使用 Magpie

当你需要一个小型 bundle 用同一种声音流利地说 9 种语言时,Magpie 是首选。5 个预设说话人在所有语言间保持身份一致 — 适合多语言助手、教育应用,或需要语言切换的有声书叙述。需要零样本声音克隆请使用 CosyVoice3Qwen3-TTS BaseVoxCPM2

架构

Magpie 是 4-bundle MLX 流水线:文本编码器 → 带交叉注意力的解码器 → LocalTransformer 码本头 → 因果 HiFi-GAN 音频编解码器。bundle 在 prefill 与 step 入口之间共享解码器权重,与上游 FluidInference 的 CoreML 布局保持兼容。

阶段模块说明
1. 分词MagpieTokenizer逐语言 G2P(IPA 词典 / byT5 字节 / 拼音 / 片假名),共享 2360-token 词表 + 逐 tokenizer 偏移,始终追加 EOS
2. 文本编码器MagpieTextEncoder6 层因果 Transformer,d=768,k=3 卷积 FFN
3. Decoder prefillMagpieDecoder12 层因果 + 交叉注意力。将 110-frame 预设说话人上下文 + BOS 写入 KV cache。
4. LocalTransformerMagpieLocalTransformer1 层码本 AR 头,d=256。基于解码器 hidden 顺序采样每帧 8 个码本。
5. Decoder stepMagpieDecoder每帧一次 AR 推进,直到 EOS 或 500-frame 上限(约 23 秒)。
6. NanoCodecMagpieNanoCodecFSQ 逆变换 → 因果 HiFi-GAN → 22.05 kHz 单声道波形。

语言与 G2P

SDK 的 testMultilingualRoundTrip 验证全部 9 种语言均能通过 Qwen3-ASR 进行往返。每种语言都有专属的 G2P 流水线:

语言代码G2P 流水线
英语enCMU IPA 词典(12.5 万条,已内置)
西班牙语es西班牙语 IPA 词典(已内置)
德语de德语 IPA 词典(已内置)
法语frbyT5 UTF-8 字节编码器
意大利语itbyT5 UTF-8 字节编码器
越南语vibyT5 UTF-8 字节编码器
印地语hi梵文码点查表 + last-wins 子词表
汉语普通话zhNLTokenizer(.simplifiedChinese) 分词 + Apple .mandarinToLatin + 内置拼音→IPA 词典 + #N 声调标记
日语jaCFStringTokenizer 汉字读音 + NFC 保留浊音 + 平板调标记 + 助词/问候语覆盖

共享 2360-token 词表把各语言的子 tokenizer 按偏移量拼接(记录在 MagpieSubVocab)。文本嵌入在词表之后多出两行用作 BOS / EOS;eos_id = 2361 会被追加到每个输入序列末尾。

预设说话人

权重内嵌 5 个说话人上下文(每个 110 帧 × 768 维),作为每次 AR 解码的前缀。说话人身份在 9 种语言间保持一致。

序号CLI 名身份
0sofiaSofia(默认)
1ariaAria
2jasonJason
3leoLeo
4johnJohn Van Stan

模型版本

版本磁盘内存(加载+解码)HuggingFace
INT4(默认)约 247 MB约 1.3 GBaufklarer/Magpie-TTS-Multilingual-357M-MLX-4bit
INT8约 411 MB约 1.6 GBaufklarer/Magpie-TTS-Multilingual-357M-MLX-8bit

两个 bundle 都使用 MLX 平坦仿射量化(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-variantint4量化版本:int4int8
--magpie-speakersofia预设说话人:sofiaariajasonleojohn
--magpie-temperature0.6采样温度(0 = 贪心)
--magpie-top-k80Top-k 采样过滤
--magpie-max-frames500码本帧数硬上限(约 23 秒)
--magpie-min-frames4允许 EOS 之前的最少帧数
--magpie-prephonemized把输入视作 IPA / 音素流,跳过逐语言 G2P
--languageenglish选择逐语言 tokenizer
--stream输出 AsyncStream<AudioChunk> 而不是单个 WAV
--seed可复现 Gumbel 采样
日语采样提示

日语输入超过一个词时需要随机解码(--magpie-temperature 0.6 --magpie-top-k 80 --seed 42 复刻 NeMo 参考测试)。贪心会卡在第一段,因为平板调启发式与逐词真值有偏差。

不支持声音克隆

Magpie 模型本身没有零样本说话人条件;bundle 只内置 5 个预设身份。CLI 会拒绝通用的 --voice-sample--speaker--instruct 标志并给出可执行的错误信息,提示改用 --magpie-speaker 或换用支持克隆的引擎(Qwen3-TTS BaseCosyVoice3VoxCPM2)。

性能(M4 Pro)

设置音频耗时RTF
批处理 INT4 贪心,短提示2.8 s0.88 s0.32
批处理 INT4 贪心,整句5.8 s1.35 s0.23
批处理 INT4 采样,23 s 输出23 s5.6 s0.24
流式 INT4 采样23 s21.6 s0.93

流式模式下加载模型后首包延迟约 120 ms。流式 RTF 较高是因为每次 chunk 输出时编解码器会对完整 code buffer 重跑(后续可加状态缓存优化)。

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)。四个 .mlmodelc 包 — text_encoderdecoder_prefilldecoder_stepnanocodec_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 的注意事项:

说话人排序与 CoreML 套件的 speaker_info.json 一致(0=John, 1=Sofia, 2=Aria, 3=Jason, 4=Leo — 与 MLX 不同);说话人枚举在内部进行映射,因此 CLI 名称在两个引擎中均可使用。

实现要点

移植 NeMo 风格多语言 TTS 时三个值得注意的坑:

三个修复都内联记录在 Swift 模块中。

来源

许可证