Magpie-TTS Multilingual

NVIDIA Magpie-TTS Multilingual 357M в Swift на Apple Silicon — авторегрессионная мультикодбук TTS-модель поверх 22,05 кГц Nano-Codec от NeMo. Девять языков (английский, испанский, немецкий, французский, итальянский, вьетнамский, хинди, мандаринский, японский), пять встроенных голосовых идентичностей. Квантование INT4 (~247 МБ) или INT8 (~411 МБ). Стриминг с задержкой первого пакета ~120 мс.

Когда выбрать Magpie

Magpie — правильный выбор, когда нужна одна небольшая сборка, говорящая на девяти языках одним и тем же голосом. Пять встроенных голосов сохраняют идентичность между языками — полезно для многоязычных ассистентов, образовательных приложений и озвучки аудиокниг со сменой языка. Для zero-shot клонирования голоса используй CosyVoice3, Qwen3-TTS Base или VoxCPM2.

Архитектура

Magpie — это MLX-пайплайн из 4 бандлов: текстовый энкодер → декодер с cross-attention → LocalTransformer-голова кодбуков → причинный HiFi-GAN аудиокодек. Бандлы разделяют веса декодера между точками входа prefill и step для совместимости с CoreML-разметкой FluidInference upstream.

ЭтапМодульДетали
1. ТокенизацияMagpieTokenizerПоязычный G2P (IPA-словарь / byT5-байты / пиньинь / катакана), общий словарь на 2360 токенов + потокенайзерные смещения, EOS всегда добавляется
2. Текстовый энкодерMagpieTextEncoder6 каузальных Transformer-слоёв, d=768, conv FFN k=3
3. Decoder prefillMagpieDecoder12 каузальных слоёв с cross-attention. Засеивает KV-кеш 110-кадровым контекстом встроенного голоса + BOS.
4. LocalTransformerMagpieLocalTransformer1-слойная AR-голова кодбуков, d=256. Сэмплит 8 кодбуков на кадр последовательно из hidden декодера.
5. Decoder stepMagpieDecoderОдин AR-шаг на кадр до EOS или лимита в 500 кадров (~23 с).
6. NanoCodecMagpieNanoCodecFSQ-инверсия → каузальный HiFi-GAN → моно-волна 22,05 кГц.

Языки и G2P

Все девять языков проходят круговой обход через Qwen3-ASR в testMultilingualRoundTrip SDK. Для каждого свой пайплайн:

ЯзыкКодПайплайн G2P
АнглийскийenCMU IPA-словарь (125 тыс. записей, встроен)
ИспанскийesИспанский IPA-словарь (встроен)
НемецкийdeНемецкий IPA-словарь (встроен)
ФранцузскийfrКодировщик UTF-8-байтов byT5
ИтальянскийitКодировщик UTF-8-байтов byT5
ВьетнамскийviКодировщик UTF-8-байтов byT5
ХиндиhiПоиск по код-поинтам деванагари + last-wins под-словарь
МандаринскийzhСегментация слов NLTokenizer(.simplifiedChinese) + Apple .mandarinToLatin + встроенный словарь пиньинь → IPA + тоновые маркеры #N
ЯпонскийjaЧтение иероглифов через CFStringTokenizer + NFC-сохранение дакутэн + хейбан-маркеры высоты + переопределения частиц/приветствий

Общий словарь на 2360 токенов конкатенирует под-токенайзеры каждого языка со смещением (зафиксировано в MagpieSubVocab). Text-embedding добавляет две строки сверх словаря для BOS/EOS; eos_id = 2361 добавляется в каждую входную последовательность.

Встроенные голоса

Чекпойнт встраивает пять голосовых контекстов (по 110 кадров × 768 измерений), используемых префиксом каждого AR-декодирования. Идентичность голоса согласована на всех девяти языках.

ИндексИмя CLIИдентичность
0sofiaSofia (по умолчанию)
1ariaAria
2jasonJason
3leoLeo
4johnJohn Van Stan

Варианты модели

ВариантДискRAM (загрузка + декод)HuggingFace
INT4 (по умолчанию)~247 МБ~1,3 ГБaufklarer/Magpie-TTS-Multilingual-357M-MLX-4bit
INT8~411 МБ~1,6 ГБ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-variantint4Вариант квантования: int4 или int8
--magpie-speakersofiaВстроенный голос: sofia, aria, jason, leo, john
--magpie-temperature0.6Температура сэмплирования (0 = жадное)
--magpie-top-k80Top-k фильтр для сэмплирования
--magpie-max-frames500Жёсткое ограничение кадров кодека (~23 с)
--magpie-min-frames4Минимум кадров до разрешения EOS
--magpie-prephonemizedвыклСчитать вход потоком IPA/фонем; пропустить поязычный G2P
--languageenglishВыбор поязычного токенайзера
--streamвыклЭмитить AsyncStream<AudioChunk> вместо одного WAV
--seedВоспроизводимое Gumbel-сэмплирование
Совет по сэмплированию для японского

Японские входы длиннее одного слова требуют стохастического декодирования (--magpie-temperature 0.6 --magpie-top-k 80 --seed 42 зеркалит референс-тест NeMo). Жадное декодирование застревает на первой фразе, потому что хейбан-эвристика тона отклоняется от пословной истины.

Клонирование голоса — не поддерживается

В Magpie нет zero-shot кондиционирования голоса в модели; в бандле только 5 встроенных идентичностей. CLI отвергает общие флаги --voice-sample, --speaker, --instruct с действенной ошибкой, указывающей на --magpie-speaker или на движки с поддержкой клонирования (Qwen3-TTS Base, CosyVoice3, VoxCPM2).

Производительность (M4 Pro)

НастройкаАудиоВремяRTF
Батч, INT4, жадное, короткий промпт2.8 с0.88 с0.32
Батч, INT4, жадное, предложение5.8 с1.35 с0.23
Батч, INT4, сэмплинг, выход 23 с23 с5.6 с0.24
Стриминг, INT4, сэмплинг23 с21.6 с0.93

Задержка первого пакета в режиме стриминга ≈120 мс после загрузки модели. 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 — Float32 моно 22,05 кГц
}

CoreML-бэкенд (--engine magpie-coreml)

Помимо MLX-бандла, Magpie поставляет CoreML-бандл (aufklarer/Magpie-TTS-Multilingual-357M-CoreML-8bit, ~342 МБ INT8). Четыре пакета .mlmodelctext_encoder, decoder_prefill, decoder_step, nanocodec_decoder — выполняются на ANE / GPU; обратное FSQ на стороне Swift превращает сэмплированные коды в 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:

Порядок голосов соответствует speaker_info.json CoreML-бандла (0=John, 1=Sofia, 2=Aria, 3=Jason, 4=Leo — отличается от MLX); enum голосов мапится внутренне, чтобы CLI-имена работали для обоих движков.

Замечания по реализации

Три бага, о которых стоит знать при портировании NeMo-style многоязычного TTS:

Все три исправления задокументированы inline в Swift-модуле.

Источники

Лицензия