Releases: soniqo/speech-swift
Release list
v0.0.26
Fixes two defects in the full-duplex VoiceChat CLI.
--no-aec captured no audio and hung. The playback graph was attached after engine.start(), an ordering only AUVoiceProcessingIO tolerates because it is a combined I/O unit that pulls audio regardless. With voice processing disabled the input tap never fired, so the session reported frames 0 and never exited, since frame-driven limits like --max-seconds only advance once frames arrive. The playback graph is now attached before starting when AEC is off; the enabled path is unchanged.
Tool calls were unbounded per user turn. A checkpoint that fell into a repetition pattern could issue dozens of successful calls in a row — one observed session searched reminders for "8 PM", "9 PM", and onward past "36 PM" before crashing. Repeat protection was write-only and the function-start gate arms only on failures, so nothing bounded successful reads. Every tool is now limited to five calls per accepted user turn, resetting on fresh acoustic activity, and returns a structured call_budget_exhausted result beyond it.
v0.0.25
Highlights
- Adds
speech voice-chat, a local full-duplex Soniqo VoiceChat demo for Nemotron VoiceChat 11B INT5 with native MCP tool calling, Apple Reminders example configuration, human-readable real-time metrics, and optional debug timelines. - Includes the VoiceChat turn-taking, overload recovery, asynchronous tool execution, audio-continuity, and regression coverage developed for the live CLI demo.
- Pins matching stable MLX dependencies and hardens clean release/Homebrew builds against moving upstream branches and stale SwiftPM caches.
The v0.0.24 binary packaging attempt was superseded by this release.
What's Changed
- docs: list AnythingLLM compatibility by @ivan-digital in #417
- Stride-aware Sortformer output reads and an experimental Ultra 8-speaker variant by @ivan-digital in #418
- Add timestamped independent audio capture by @ivan-digital in #419
- Add match-only ReDimNet embeddings for short utterances by @ivan-digital in #421
- feat: add LocalVQE acoustic echo cancellation by @ivan-digital in #422
- fix: prevent LocalVQE CoreML buffer exhaustion by @ivan-digital in #424
- Add native MOSS Transcribe CoreML runtime by @ivan-digital in #426
- Add Cohere Transcribe and Voxtral Mini ASR by @ivan-digital in #423
- Report diarization DER by speaker count by @ivan-digital in #420
- Add CSM (Conversational Speech Model) runtime by @ivan-digital in #425
- Add long-context MLX runtime for MOSS by @ivan-digital in #427
- Add native Nemotron MLX streaming runtime by @ivan-digital in #428
- feat: add MLX engine for DeepFilterNet3 speech enhancement by @ivan-digital in #430
- Fix microphone resampling drift by @ivan-digital in #429
- Fix Qwen3-TTS model downloads by @mchernyavskaya in #431
- Consolidate model downloads onto one transfer engine by @ivan-digital in #433
- Read chat model quantization from the checkpoint instead of assuming INT4 by @ivan-digital in #434
- Default the Qwen3.5 chat MLX loader to INT5 instead of INT4 by @ivan-digital in #435
- Band Gemma 4's sliding attention instead of masking a full score matrix by @ivan-digital in #436
- Order adopters by stars across every README by @ivan-digital in #437
- Merge Gemma 4's BPE through a queue instead of rescanning every pair by @ivan-digital in #438
- Sample Gemma 4 on the GPU instead of copying the vocabulary per token by @ivan-digital in #439
- Append Gemma 4's KV cache in place and bound its sliding layers by @ivan-digital in #440
- Set the sliding-window logit bound from what blocking actually costs by @ivan-digital in #441
- Add Canary ASR, and hold the mel front end to the training contract by @ivan-digital in #446
- Make Qwen async generation cooperatively cancellable by @ThorFuchs in #444
- Add deterministic local Qwen3-TTS loading by @ThorFuchs in #442
- Route Qwen diagnostics through unified logging by @ThorFuchs in #443
- Add complete VoiceChat 11B duplex speech-to-speech runtime for MLX by @ivan-digital in #447
- Make VoiceChat INT5 faster than real time by @ivan-digital in #449
- Compile Qwen3-TTS code predictor frames by @ivan-digital in #450
- Bound the MLX buffer pool in Qwen3TTS E2E suites by @enrzh in #448
- Add SpeechBrain ECAPA language identification by @ivan-digital in #451
- Give VoiceChat real-time inference headroom by @ivan-digital in #452
- Add full-duplex VoiceChat CLI with native MCP tools by @ivan-digital in #455
- Make release builds reproducible by @ivan-digital in #456
New Contributors
- @mchernyavskaya made their first contribution in #431
- @ThorFuchs made their first contribution in #444
- @enrzh made their first contribution in #448
Full Changelog: v0.0.23...v0.0.25
v0.0.24
Important
Superseded by v0.0.25. The v0.0.24 packaging run failed and this release has no binary asset. Use v0.0.25 instead.
Highlights
- Adds the Nemotron VoiceChat 11B full-duplex MLX runtime and Soniqo terminal voice-chat demo, with model-native turn taking, configurable MCP tools, Apple Reminders integration, and structured latency and acoustic-quality benchmarks.
- Adds MOSS, Cohere, Voxtral, Canary, and native Nemotron speech-recognition paths, plus timestamped audio capture and LocalVQE acoustic echo cancellation.
- Adds the CSM speech runtime, an MLX DeepFilterNet3 engine, SpeechBrain ECAPA language identification, and substantial Qwen and Gemma inference performance and reliability improvements.
What's Changed
- docs: list AnythingLLM compatibility by @ivan-digital in #417
- Stride-aware Sortformer output reads and an experimental Ultra 8-speaker variant by @ivan-digital in #418
- Add timestamped independent audio capture by @ivan-digital in #419
- Add match-only ReDimNet embeddings for short utterances by @ivan-digital in #421
- feat: add LocalVQE acoustic echo cancellation by @ivan-digital in #422
- fix: prevent LocalVQE CoreML buffer exhaustion by @ivan-digital in #424
- Add native MOSS Transcribe CoreML runtime by @ivan-digital in #426
- Add Cohere Transcribe and Voxtral Mini ASR by @ivan-digital in #423
- Report diarization DER by speaker count by @ivan-digital in #420
- Add CSM (Conversational Speech Model) runtime by @ivan-digital in #425
- Add long-context MLX runtime for MOSS by @ivan-digital in #427
- Add native Nemotron MLX streaming runtime by @ivan-digital in #428
- feat: add MLX engine for DeepFilterNet3 speech enhancement by @ivan-digital in #430
- Fix microphone resampling drift by @ivan-digital in #429
- Fix Qwen3-TTS model downloads by @mchernyavskaya in #431
- Consolidate model downloads onto one transfer engine by @ivan-digital in #433
- Read chat model quantization from the checkpoint instead of assuming INT4 by @ivan-digital in #434
- Default the Qwen3.5 chat MLX loader to INT5 instead of INT4 by @ivan-digital in #435
- Band Gemma 4's sliding attention instead of masking a full score matrix by @ivan-digital in #436
- Order adopters by stars across every README by @ivan-digital in #437
- Merge Gemma 4's BPE through a queue instead of rescanning every pair by @ivan-digital in #438
- Sample Gemma 4 on the GPU instead of copying the vocabulary per token by @ivan-digital in #439
- Append Gemma 4's KV cache in place and bound its sliding layers by @ivan-digital in #440
- Set the sliding-window logit bound from what blocking actually costs by @ivan-digital in #441
- Add Canary ASR, and hold the mel front end to the training contract by @ivan-digital in #446
- Make Qwen async generation cooperatively cancellable by @ThorFuchs in #444
- Add deterministic local Qwen3-TTS loading by @ThorFuchs in #442
- Route Qwen diagnostics through unified logging by @ThorFuchs in #443
- Add complete VoiceChat 11B duplex speech-to-speech runtime for MLX by @ivan-digital in #447
- Make VoiceChat INT5 faster than real time by @ivan-digital in #449
- Compile Qwen3-TTS code predictor frames by @ivan-digital in #450
- Bound the MLX buffer pool in Qwen3TTS E2E suites by @enrzh in #448
- Add SpeechBrain ECAPA language identification by @ivan-digital in #451
- Give VoiceChat real-time inference headroom by @ivan-digital in #452
- Add full-duplex VoiceChat CLI with native MCP tools by @ivan-digital in #455
New Contributors
- @mchernyavskaya made their first contribution in #431
- @ThorFuchs made their first contribution in #444
- @enrzh made their first contribution in #448
Full Changelog: v0.0.23...v0.0.24
v0.0.23
Highlights
- Adds an OpenAI-compatible
POST /v1/audio/speechendpoint tospeech-server, supporting WAV and raw PCM output for drop-in local TTS integrations. - Adds incremental Sortformer streaming, Nemotron emission-aligned word timestamps, and the ReDimNet2-B6 speaker identity encoder.
- Improves cached Whisper model startup.
What's Changed
- Optimize cached Whisper model loading by @ivan-digital in #410
- Add ReDimNet2-B6 speaker identity encoder by @ivan-digital in #409
- Add incremental Sortformer streaming session by @ivan-digital in #411
- docs: add public integration showcase and Homebrew stats by @ivan-digital in #412
- docs: remove zero-star adoption references by @ivan-digital in #413
- Expose emission-aligned word timestamps from Nemotron streaming by @ivan-digital in #414
- feat: add OpenAI-compatible speech synthesis by @ivan-digital in #415
Full Changelog: v0.0.22...v0.0.23
v0.0.22
DeepFilterNet3 quality
DeepFilterNet3 speech enhancement now matches the reference libdf DSP conventions while retaining the compact Core ML model: 8-bit palettized weights with FP16 compute. On the documented VoiceBank-DEMAND 20-clip benchmark, the Swift path reaches PESQ-WB 3.097, STOI 0.964, and SI-SDR 19.12 dB.
What's Changed
- Create FUNDING.yml by @ivan-digital in #316
- Improve realtime websocket error handling by @ivan-digital in #315
- Fix funding configuration syntax in FUNDING.yml by @ivan-digital in #317
- Keep realtime websockets alive during cold starts by @ivan-digital in #318
- Keep realtime inference off websocket event loops by @ivan-digital in #320
- Disable Hummingbird auto-ping on realtime websocket by @ivan-digital in #321
- Lift realtime websocket keepalive to session scope by @ivan-digital in #322
- feat(qwen3-tts): ship 1.7B bf16, drop degrading 1.7B int4 by @ivan-digital in #324
- sortformer: high-throughput offline variant + proper streaming state (#319) by @ivan-digital in #326
- FunctionGemma — on-device tool-calling LLM (Gemma 3 270M, CoreML) by @ivan-digital in #327
- fix(sortformer): default to ANE-only compute units (#319) by @ivan-digital in #328
- feat(cosyvoice): honor style instructions on cloned voices via instruct2 by @ivan-digital in #323
- docs(tts): refresh roundtrip benchmark for the 1.7B int4 drop by @ivan-digital in #325
- feat(sortformer): preload(), computeUnits, balanced variant by @ivan-digital in #329
- fix(qwen3): correct 1.7B speaker-encoder dims and conv layout for voice cloning by @ivan-digital in #330
- fix(qwen3): pin voice-clone tests to one model to stop x-vector collapse by @ivan-digital in #332
- chore(tts): decommission int4 for TTS models (defaults → bf16/int8) by @ivan-digital in #333
- docs(tts): drop int4 from the TTS model catalog after the decommission by @ivan-digital in #334
- FunctionGemma: render full developer/declaration block via FunctionGemmaPrompt by @ivan-digital in #335
- chore(tts): point CustomVoice at the new bf16 bundle (int4 fully decommissioned) by @ivan-digital in #336
- feat(downloader): support HF_ENDPOINT mirror for users in China by @hanrw in #331
- fix(function-gemma): route loadFromHub through HF_ENDPOINT mirror by @ivan-digital in #337
- Qwen3-ASR: add 5-bit MLX quantization variant by @xzjh in #262
- skill(benchmark): /benchmark asr now reports WER + peakRSS + throughput by @ivan-digital in #338
- feat(asr): wire 5-bit MLX variants into AsrBenchmark + docs by @ivan-digital in #340
- Add SupertonicTTS-3 (CoreML) — non-autoregressive flow-matching TTS by @ivan-digital in #341
- fix(qwen3-icl): reimplement the Mimi codec encoder so voice clone is target-only by @ivan-digital in #339
- docs(readme): swap Product Hunt badge for Trendshift badge by @ivan-digital in #344
- feat(forced-aligner): CoreML runtime + speech align --engine coreml by @ivan-digital in #345
- ChatterboxTTS: multilingual voice cloning in Swift/MLX by @ivan-digital in #343
- Fix Qwen3.5 streaming decode corruption + empty replies by @ivan-digital in #346
- ChatterboxTTS: fix from-pretrained dropping model.safetensors by @ivan-digital in #347
- Add Qwen3 dense MLX runtime (Qwen3-4B chat) + quant/sampler fixes by @ivan-digital in #348
- OmniVoiceTTS: MLX-Swift port of OmniVoice (600+ language NAR diffusion TTS) by @ivan-digital in #349
- Fix OmniVoice instruct conditioning by @ivan-digital in #351
- Fix nightly E2E shard stability by @ivan-digital in #352
- Group README models by capability by @ivan-digital in #354
- Add daily benchmark dashboard by @ivan-digital in #353
- Add Gemma 4 chat backend by @ivan-digital in #355
- Add local benchmark runner by @ivan-digital in #357
- Use Silero VAD v6.2.1 CoreML by default by @ivan-digital in #359
- Add Hindi emotion TTS candidates by @ivan-digital in #358
- Add Indic-Mio raw reference cloning by @ivan-digital in #360
- Add Fish Audio S2 Pro runtime by @ivan-digital in #361
- Use Silero VAD v6.2.1 MLX by default by @ivan-digital in #362
- Split Kokoro fixture from Qwen ASR tests by @ivan-digital in #363
- Update model documentation coverage by @ivan-digital in #364
- Add resumable Fish Audio downloads by @ivan-digital in #365
- Speed up ranged Hugging Face downloads by @ivan-digital in #366
- Add WhisperASR CoreML port by @ivan-digital in #367
- Honor PersonaPlex demo offline cache by @ivan-digital in #370
- Speed up diarization: batch segmentation windows, memoize clustering distances by @JimLiu in #371
- Add communication guidelines and PR review skill by @ivan-digital in #373
- Fix streaming audio startup de-click by @ivan-digital in #374
- Support Chatterbox multilingual frontends by @ivan-digital in #375
- Add Audio2Face-3D avatar motion runtime by @ivan-digital in #376
- Skip CosyVoice LLM micro-test in nightly by @ivan-digital in #377
- CosyVoice: seeded long-form synthesis + upstream parity fixes by @ivan-digital in #378
- Fix Chatterbox CoreML int8 SDK compatibility by @ivan-digital in #380
- Add Chatterbox Flash voice cloning bridge by @ivan-digital in #381
- Update AGENTS.md to match current codebase by @rymalia in #379
- Clarify agent testing commands by @ivan-digital in #382
- Add native IndexTTS2 voice cloning runtime by @ivan-digital in #384
- Add voice cloning candidate runtimes by @ivan-digital in #383
- Add native F5-TTS voice cloning runtime by @ivan-digital in #385
- Add Mandarin pinyin frontend to F5-TTS by @ivan-digital in #386
- State current F5-TTS language support without legacy-bundle caveats by @ivan-digital in #387
- Add native Higgs TTS 3 voice cloning runtime by @ivan-digital in #389
- Pipeline the Higgs decode loop and tune voice-cloning TTS performance by @ivan-digital in #390
- Cache and batch the IndexTTS2 semantic GPT decode by @ivan-digital in #391
- Rewrite BigVGAN FIR resampling as dense convolution by @ivan-digital in #392
- Optimize Qwen3-ASR batch decode CPU sync by @hhh2210 in #234
- Cleanup follow-ups for Qwen3-ASR batched decode by @ivan-digital in #236
- Expose IndexTTS2 S2Mel flow steps by @ivan-digital in #393
- Add isolated E2E regression runner by @ivan-digital in #394
- Fix Magpie Chinese frontend to match NeMo tokenization by @ivan-digital in #395
- Fix CustomVoice: retire phantom 8bit bundle, stabilize float16 decode by @ivan-digital in #396
- Cut IndexTTS2 GPT step overhead, default S2Mel to 15 steps by @ivan-digital in #397
- Harden downloader against large-shard stalls and partial bundles by @ivan-digital in #398
- Finalize empty Qwen pipeline generations by @ivan-digital in https://github.com/soniqo/speech-swift/pu...
v0.0.21
What's Changed
Fix
- Parakeet TDT CoreML — M5 ANE crash (#314, refs #313). The
aufklarer/Parakeet-TDT-v3-CoreML-INT8repo rebuilt with a multi-encoder iOS18 layout (encoder.mlmodelc30s +encoder_5s.mlmodelc+encoder_15s.mlmodelc); the priorEnumeratedShapesiOS17 build SIGSEGV'd inbnns::GraphCompileon M5 ANE. Single-shape-30sand-iOS-5srepos were unaffected and continue to ship unchanged.
New
encoderVariant:parameter onParakeetASRModel.fromPretrained. Pick a shape-specific encoder from the multi-encoder repo for short voice-pipeline chunks:let model = try await ParakeetASRModel.fromPretrained( modelId: "aufklarer/Parakeet-TDT-v3-CoreML-INT8", encoderVariant: "5s")
nil(default) keeps the previousencoder.mlmodelcpath so single-shape repos work unchanged.
Performance
- macOS now prefers
.cpuAndNeuralEnginewith.cpuAndGPUfallback (was pinned to GPU only because of the historical ANE crash class). M5 Pro warm encoder forward: 8 ms at 5s / 24 ms at 15s / 74 ms at 30s, all on ANE. ~540 MB less peak RSS than GPU on the 30s shape. - WER unchanged on LibriSpeech test-clean n=200: 2.37% / 116× RTF / 916 MB peak, matching the published baseline.
CLI
brew upgrade speech # once homebrew-core formula bumps to v0.0.21
# or build from source
git clone --branch v0.0.21 https://github.com/soniqo/speech-swift.git
cd speech-swift && make build
./.build/release/speech transcribe meeting.wav --engine parakeetFull Changelog: v0.0.20...v0.0.21
v0.0.20
What's Changed
New
- Nemotron-3.5 ASR Streaming (multilingual) — 40 language-locales, native punctuation and capitalization, cache-aware FastConformer-RNN-T (600 M) on the Apple Neural Engine. New
NemotronStreamingASRtarget. Default model is the CoreML INT8 bundle (612 MB, RTF ≈ 0.07 on M5 Pro). Language is a BCP-47 tag (en-US,de-DE,ja-JP, ...). #294 - English-only Nemotron bundle still supported through the same target — the runtime introspects the encoder's input description for
language_maskand adapts. Older bundles continue to work without code changes. #295
Performance & quality
- Qwen3-ASR CoreML encoder rebuild — chunked-attention encoder + bench scaffold for cross-engine ASR comparison (Qwen3-ASR, Parakeet TDT, Nemotron, Whisper). #292
- Parakeet TDT CoreML — default to a single fixed-shape 30 s export (drop
EnumeratedShapes) to fix ANE-compile hangs on iOS. #290
Docs
- CoreML encoder interface description refreshed; M2 Max baselines retired in favour of current M-series numbers. #293
CI
CLI
brew upgrade soniqo/tap/speech
speech transcribe recording.wav --engine nemotron --language en-US
speech transcribe meeting.wav --engine nemotron --language de-DE
speech transcribe interview.wav --engine nemotron --language ja-JP--engine nemotron defaults to the multilingual CoreML INT8 bundle from aufklarer/Nemotron-3.5-ASR-Streaming-0.6B-CoreML-INT8 (downloaded on first use, cached under ~/Library/Caches/qwen3-speech/).
v0.0.19
What's Changed
New
- HTDemucs (Demucs v4) — higher-quality music source separation, +3.01 dB SDR over Open-Unmix (largest gains on bass/drums).
speech separate --engine htdemucs. #288 - OpenAI-compatible transcription —
/v1/audio/transcriptionsserver endpoint. #273 - Qwen3-TTS on CoreML — full Apple Neural Engine routing + chunked decode. #269
Performance & quality
- 7× faster CoreML ASR — split + batched-prefill decoder, ANE-safe. #282
- Mastering-grade resampler — drains the filter tail, exact output length, phase-aligned stereo; mastering SRC for music/upsampling, standard for speech. #284
- Qwen3-TTS bf16 / non-quantized support + ICL stability. #272
- CosyVoice bf16 bundle support. #280
Fixes
- Abort wedged Hugging Face downloads instead of hanging. #283
- Stride-aware, NaN-safe argmax in the CoreML ASR decoder. #278
CLI
speech separate song.wav --engine htdemucs # Demucs v4 (higher quality)
speech separate song.wav # UMX (default)v0.0.18
What's Changed
- StableAudio3MusicGen: Stable Audio 3 Medium INT8 as the new default music-gen engine for `speech compose`. Bit-perfect parity with Stability AI's pure-MLX Python reference, ~16× realtime, stereo 44.1 kHz. MAGNeT stays available via `--engine magnet`. #270
CLI
```bash
speech compose "lofi house loop" # SA3 (default)
speech compose "ambient pad" --engine magnet # old engine
speech compose "..." --sa3-variant medium-int4 --seconds 30
```
v0.0.17
What's Changed
- release: ship all .bundle resources (fixes compose/magnet on brew) by @ivan-digital in #267
Full Changelog: v0.0.16...v0.0.17