Magpie-TTS متعدّد اللغات

NVIDIA Magpie-TTS متعدّد اللغات 357M بلغة Swift على Apple Silicon — نموذج تركيب كلام انحداريّ متعدّد الـ codebooks فوق Nano-Codec من NeMo بـ 22.05 kHz. تسع لغات (الإنجليزية والإسبانية والألمانية والفرنسية والإيطالية والفيتنامية والهندية والصينية المندرين واليابانية) مع خمس هويّات متحدّث مدمجة. يُشحن مُكمَّمًا بـ INT4 (~247 MB) أو INT8 (~411 MB). جاهز للبثّ بزمن استجابة الحزمة الأولى ~120 ms.

متى تختار Magpie

Magpie هو الخيار الصحيح حين تحتاج إلى حزمة واحدة صغيرة تتكلّم بتسع لغات بصوت ثابت. يحافظ المتحدّثون الخمسة المدمجون على هويّتهم عبر اللغات — مفيد للمساعدات متعدّدة اللغات وتطبيقات التعليم وسرد الكتب الصوتية مع تبديل اللغة. لاستنساخ الصوت بـ zero-shot استخدم بدلًا منه CosyVoice3 أو Qwen3-TTS Base أو VoxCPM2.

البنية

Magpie خطّ معالجة MLX من 4 حزم: مُرمِّز النصّ → مفكِّك بانتباه متقاطع → رأس codebook بـ LocalTransformer → كوديك صوت Causal HiFi-GAN. تتشارك الحزم أوزان المفكِّك بين نقطتي دخول prefill وstep لمطابقة تخطيط CoreML من FluidInference في المنبع.

المرحلةالوحدةالتفاصيل
1. الترميزMagpieTokenizerG2P لكلّ لغة (قاموس IPA / بايتات byT5 / pinyin / katakana)، مفردات مشتركة من 2360 رمزًا مع إزاحات لكلّ مُرمِّز، EOS يُضاف دائمًا
2. مُرمِّز النصّMagpieTextEncoder6 طبقات Transformer سببيّة، d=768، FFN تلافيفيّ k=3
3. Decoder prefillMagpieDecoder12 طبقة سببيّة بانتباه متقاطع. يُمهِّد ذاكرة KV بسياق المتحدّث المدمج (110 إطارات) + BOS.
4. LocalTransformerMagpieLocalTransformerرأس AR لـ codebook من طبقة واحدة، d=256. يُعاين الـ 8 codebooks لكلّ إطار تتابعيًّا بناءً على مخفيّ المفكِّك.
5. Decoder stepMagpieDecoderخطوة AR واحدة لكلّ إطار حتى EOS أو سقف 500 إطار (~23 ث).
6. NanoCodecMagpieNanoCodecعكس FSQ → HiFi-GAN سببيّ → موجة أحاديّة بـ 22.05 kHz.

اللغات وG2P

اللغات التسع كلّها تتمّ رحلة العودة عبر Qwen3-ASR في اختبار testMultilingualRoundTrip في الـ SDK. كلّ لغة تحظى بخطّ معالجة مُفصَّل:

اللغةالرمزخطّ معالجة G2P
الإنجليزيةenقاموس CMU IPA (125 ألف مدخل، مُضمَّن)
الإسبانيةesقاموس IPA إسبانيّ (مُضمَّن)
الألمانيةdeقاموس IPA ألمانيّ (مُضمَّن)
الفرنسيةfrمُرمِّز بايتات UTF-8 من byT5
الإيطاليةitمُرمِّز بايتات UTF-8 من byT5
الفيتناميةviمُرمِّز بايتات UTF-8 من byT5
الهنديةhiبحث codepoint للديفاناغاريّ + مفردات فرعية last-wins
الصينية المندرينzhتقسيم كلمات بـ NLTokenizer(.simplifiedChinese) + .mandarinToLatin من Apple + قاموس pinyin → IPA مُضمَّن + علامات نغمة #N
اليابانيةjaقراءة kanji بـ CFStringTokenizer + dakuten محفوظ بـ NFC + علامات نبر heiban + استبدالات للحروف الوظيفية/التحيات

المفردات المشتركة من 2360 مدخلًا تُلصق المُرمِّز الفرعيّ لكلّ لغة طرفًا إلى طرف مع إزاحة لكلّ لغة (مُسجَّلة في MagpieSubVocab). تُضيف تضمينات النصّ صفّين إضافيّين بعد المفردات لـ BOS / EOS؛ ويُضاف eos_id = 2361 إلى كلّ تسلسل إدخال.

المتحدّثون المدمجون

تُدمج نقطة المرجع خمسة سياقات متحدّث (110 إطارات × 768 بُعدًا لكلٍّ) تُستخدم كبادئة لكلّ فكّ ترميز AR. هويّة المتحدّث ثابتة عبر اللغات التسع.

الفهرساسم 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

تعتمد الحزمتان كَمَّنة MLX أفينية مسطّحة (mlx_affine_flat، حجم المجموعة 64) وتُفكَّك كَمَّنتها إلى FP32 عند التحميل — تنشيطات وقت التشغيل بدقّة كاملة. INT4 لا يُميَّز سمعيًّا عن INT8 في هذا النموذج؛ اختر INT4 ما لم يكن لديك مساحة تخزين فائضة.

استخدام CLI

# الإنجليزية، فكّ ترميز greedy
speech speak "Hello, world." --engine magpie --magpie-speaker aria \
    --magpie-temperature 0 -o out.wav

# الإسبانية (أيّ من اللغات التسع — اختر بـ --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

# تركيب بثّيّ مع التشغيل
speech speak "Streaming test" --engine magpie --stream --play

# سرد المتحدّثين الخمسة المدمجين
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 = greedy)
--magpie-top-k80مرشِّح top-k للمعاينة
--magpie-max-frames500سقف قاسٍ لإطارات الكوديك (~23 ث)
--magpie-min-frames4أدنى إطارات قبل السماح بـ EOS
--magpie-prephonemizedoffعامل الإدخال على أنه تيّار IPA / فونيمات؛ يتجاوز G2P لكلّ لغة
--languageenglishيختار خطّ المُرمِّز لكلّ لغة
--streamoffيُصدر AsyncStream<AudioChunk> بدلًا من ملفّ WAV واحد
--seedمعاينة Gumbel قابلة للتكرار
نصيحة لمعاينة اليابانية

المدخلات اليابانية الأطول من كلمة واحدة تحتاج فكّ ترميز عشوائيًّا (--magpie-temperature 0.6 --magpie-top-k 80 --seed 42 يُحاكي اختبار NeMo المرجعيّ). يعلق greedy عند العبارة الأولى لأن استدلاليّة نبر heiban تنحرف عن الحقيقة لكلّ كلمة.

استنساخ الصوت — غير مدعوم

لا يحوي Magpie اشتراط متحدّث بـ zero-shot داخل النموذج؛ تُشحن في الحزمة الهويّات الخمس المدمجة فقط. ترفض CLI الرايات المشتركة --voice-sample و--speaker و--instruct برسالة خطأ قابلة للتنفيذ توجِّه المستخدمين إلى راية --magpie-speaker أو إلى المحرّكات التي تدعم الاستنساخ (Qwen3-TTS Base، CosyVoice3، VoxCPM2).

الأداء (M4 Pro)

الإعدادالصوتالزمن الحقيقيّRTF
Batch، INT4، greedy، موجِّه قصير2.8 ث0.88 ث0.32
Batch، INT4، greedy، جملة5.8 ث1.35 ث0.23
Batch، INT4، مُعايَن، إخراج 23 ث23 ث5.6 ث0.24
بثّ، INT4، مُعايَن23 ث21.6 ث0.93

زمن استجابة الحزمة الأولى في وضع البثّ ≈120 ms بعد تحميل النموذج. RTF البثّ أعلى لأن الكوديك يُستدعى من جديد على ذاكرة الرموز الكاملة في كلّ إصدار حُزمة (نسخة مستقبلية قد تُخزِّن حالة الكوديك).

واجهة Swift

import MagpieTTS

let model = try await MagpieTTS.fromPretrained(variant: .int4)

// Batch synthesis (en/es/de/fr/it/vi/hi/zh — greedy works)
let audio = try model.synthesize(
    text: "Hello, world.",
    speaker: .aria,
    language: .english,
    params: MagpieTTSParams(temperature: 0, topK: 1, maxSteps: 500))

// Japanese — use stochastic sampling
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 is 22.05 kHz mono Float32
}

الواجهة الخلفية CoreML (--engine magpie-coreml)

إلى جانب حزمة MLX، يشحن Magpie حزمة CoreML (aufklarer/Magpie-TTS-Multilingual-357M-CoreML-8bit، ~342 MB 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:

الإصلاحات الثلاثة موثَّقة سطريًّا في وحدة Swift.

المصدر

الترخيص