feat(tts): add NeuTTS-2E backend (emotional English TTS, Qwen3 + NeuCodec) - #822
feat(tts): add NeuTTS-2E backend (emotional English TTS, Qwen3 + NeuCodec)#822Alex-Wengg wants to merge 1 commit into
Conversation
New TtsBackend.neuTts: Qwen3 236M backbone emitting NeuCodec speech tokens autoregressively (top-k 50, temp 1.0, seeded SplitMix64), decoded to 24 kHz by the NeuCodec decoder. Seven emotions x four fixed speakers. Models from FluidInference/neutts-2e-coreml (converted in mobius models/tts/neutts-2e/coreml, mobius PR #79). - NeuTtsBpeTokenizer: minimal byte-level BPE encoder for the HF tokenizer.json (Qwen2 scheme: split-regex from JSON, GPT-2 bytes_to_unicode, merge ranks). Parity-tested against transformers-generated fixtures (NeuTtsTokenizerTests, skips when the tokenizer asset is not cached). - NeuTtsPrompt: upstream chat-template port (NFKC + curly-quote normalization, emotion token splice, contiguous speech-token ids). - NeuTtsSynthesizer: prefill (768-token window) -> MLState KV seeding (fp32 prefill KV -> per-layer fp16 state buffers) -> per-token stateful decode -> NeuCodec vocode. Runs on the caller's actor via #isolation; macOS 15+/iOS 18+ (MLState). - NeuTtsModels: mlmodelc download via ModelHub + individual fetch of samples/<speaker>.json (the repo walk only descends into required bundles); LM on GPU (ANE rejects the decode graph, ANECCompile -14), codec on ANE (~2x faster than GPU). - CLI: --backend neutts, --emotion, --voice as speaker, --seed. Verified e2e on M5 Pro: three speaker/emotion combos transcribe verbatim via parakeet-tdt-v3; 1.67x RT (5.76 s audio in 3.45 s), model load 4.8 s cold. Perth watermarking is upstream host-side postprocessing and intentionally not implemented.
ASR Benchmark Results
|
| Dataset | WER Avg | WER Med | RTFx | Status |
|---|---|---|---|---|
| test-clean | % | % | x | |
| test-other | % | % | x |
Parakeet v2 (English-optimized)
| Dataset | WER Avg | WER Med | RTFx | Status |
|---|---|---|---|---|
| test-clean | % | % | x | |
| test-other | % | % | x |
Streaming (v3)
| Metric | Value | Description |
|---|---|---|
| WER | % | Word Error Rate in streaming mode |
| RTFx | x | Streaming real-time factor |
| Avg Chunk Time | s | Average time to process each chunk |
| Max Chunk Time | s | Maximum chunk processing time |
| First Token | s | Latency to first transcription token |
| Total Chunks | Number of chunks processed |
Streaming (v2)
| Metric | Value | Description |
|---|---|---|
| WER | % | Word Error Rate in streaming mode |
| RTFx | x | Streaming real-time factor |
| Avg Chunk Time | s | Average time to process each chunk |
| Max Chunk Time | s | Maximum chunk processing time |
| First Token | s | Latency to first transcription token |
| Total Chunks | Number of chunks processed |
Streaming tests use 5 files with 0.5s chunks to simulate real-time audio streaming
files per dataset • Test runtime: • 07/25/2026, 06:32 PM EST
RTFx = Real-Time Factor (higher is better) • Calculated as: Total audio duration ÷ Total processing time
Processing time includes: Model inference on Apple Neural Engine, audio preprocessing, state resets between files, token-to-text conversion, and file I/O
Example: RTFx of 2.0x means 10 seconds of audio processed in 5 seconds (2x faster than real-time)
Expected RTFx Performance on Physical M1 Hardware:
• M1 Mac: ~28x (clean), ~25x (other)
• CI shows ~0.5-3x due to virtualization limitations
Testing methodology follows HuggingFace Open ASR Leaderboard
VAD Benchmark Results❌ Benchmark failed - no results generated |
Parakeet EOU Benchmark Results ❌Status: Benchmark failed (see logs) Performance Metrics
Streaming Metrics
Test runtime: • 07/25/2026, 06:32 PM EST RTFx = Real-Time Factor (higher is better) • Processing includes: Model inference, audio preprocessing, state management, and file I/O |
Supertonic3 Smoke Test ❌
Runtime: Note: CI VMs lack a physical Neural Engine; the ANE-bucketed VectorEstimator falls back to CPU here. This validates download + variant resolution + synthesis, not ANE residency/perf. |
PocketTTS Smoke Test ❌
Runtime: Note: PocketTTS uses CoreML MLState (macOS 15) KV cache + Mimi streaming state. CI VM lacks physical GPU — audio quality and performance may differ from Apple Silicon. |
Sortformer High-Latency Benchmark ResultsES2004a Performance (30.4s latency config)
Sortformer High-Latency • ES2004a • Runtime: N/A • 2026-07-25T22:34:47.045Z |
Offline VBx Pipeline ResultsSpeaker Diarization Performance (VBx Batch Mode)Optimal clustering with Hungarian algorithm for maximum accuracy
Offline VBx Pipeline Timing BreakdownTime spent in each stage of batch diarization
Speaker Diarization Research ComparisonOffline VBx achieves competitive accuracy with batch processing
Pipeline Details:
🎯 Offline VBx Test • AMI Corpus ES2004a • NaNs meeting audio • NaNs processing • Test runtime: N/A • 07/25/2026, 06:36 PM EST |
What
New
TtsBackend.neuTts— neuphonic/neutts-2e: an autoregressive Qwen3 236M backbone emits NeuCodec speech tokens (50/s, top-k 50 / temp 1.0 sampling, seeded), decoded to 24 kHz audio by the NeuCodec decoder. Seven emotions × four fixed speakers — the only backend with emotion control. Models come from FluidInference/neutts-2e-coreml (converted in mobius, see FluidInference/mobius#79).How
NeuTtsBpeTokenizer— minimal byte-level BPE encoder for the HFtokenizer.json(Qwen2 scheme: split regex read from the JSON, GPT-2 bytes_to_unicode, merge-rank loop). First BPE encoder in the repo; parity-tested againsttransformers-generated fixtures (NeuTtsTokenizerTests, skipped when the asset isn't cached).NeuTtsPrompt— upstream chat-template port: NFKC + curly-quote normalization,<|TEXT_PROMPT_START|>…<|EMOTION|>…<|SPEECH_GENERATION_START|>{ref codes}layout, contiguous speech-token id mapping.NeuTtsSynthesizer— prefill (768-token window) → seed 56 per-layer fp16MLStatebuffers from the fp32 prefill KV → per-token stateful decode until<|SPEECH_GENERATION_END|>→ NeuCodec vocode. Runs on the caller's actor via#isolation; requires macOS 15+/iOS 18+ (MLState).ANECCompile-14), codec on.cpuAndNeuralEngine(~2× faster than GPU despite the flexible code-length axis)..mlmodelcbundles).Verification (M5 Pro)
Notes
🤖 Generated with Claude Code