{"slug": "crispasr-one-c-binary-for-multilingual-asr-and-tts-models", "title": "CrispASR: One C++ binary for multilingual ASR and TTS models", "summary": "CrispASR, a C++ speech engine forked from whisper.cpp, now supports 54 ASR backends and 55 TTS engines in a single binary with no Python dependencies, according to the project's documentation. The tool, which also offers multilingual text translation, compiles to WebAssembly for browser use and includes a live demo on HuggingFace Space.", "body_md": "**One C++ binary, 54 ASR backends + 55 TTS engines + multilingual text translation, zero Python dependencies.**\n\nCrispASR started as a fork of [whisper.cpp](https://github.com/ggml-org/whisper.cpp) and extends that base into a **unified speech engine** called `crispasr`\n\n, backed by full ggml C++ runtimes for major open-weights ASR *and* TTS architectures. One build, one binary, one consistent CLI — pick the backend at the command line or let CrispASR auto-detect it from your GGUF file. See [Text-to-Speech](#text-to-speech-models) for the TTS side.\n\n``` bash\n$ crispasr -m ggml-base.en.bin          -f samples/jfk.wav                    # OpenAI Whisper\n$ crispasr -m parakeet-tdt-0.6b.gguf    -f samples/jfk.wav                    # NVIDIA Parakeet\n$ crispasr -m canary-1b-v2.gguf         -f samples/jfk.wav                    # NVIDIA Canary\n$ crispasr -m voxtral-mini-3b-2507.gguf -f samples/jfk.wav                    # Mistral Voxtral\n$ crispasr --backend qwen3 -m auto      -f samples/jfk.wav                    # -m auto downloads\n$ crispasr --backend kokoro -m auto --tts \"Hello world\" --tts-output out.wav  # TTS\n```\n\nNo Python. No PyTorch. No separate per-model binary. No `pip install`\n\n. Just one C++ binary and a GGUF file.\n\n**Browser**: All backends compile to WebAssembly (4.3 MB) via `build-wasm.sh`\n\n.\nMultithreaded, runs entirely client-side with COOP/COEP headers.\n\n**Demo**: [HuggingFace Space](https://huggingface.co/spaces/cstr/CrispASR) —\nlive transcription + TTS + language detection, auto-deployed from `hf-space/`\n\n.\n\n| Project | What it does |\n|---|---|\n|\nThis repo — C++ speech engine. 54 ASR + 55 TTS backends, CLI + HTTP server + C-ABI + Python/Rust/Dart/Go/Ruby/Java bindings. |\n|\nCross-platform Flutter transcription app built on CrispASR. Desktop + mobile, model browser with download queue, mic capture, SRT/VTT/JSON export, diarization, batch processing. Fully offline. |\n|\nText-related engine via ggml — same philosophy as CrispASR but for embeddings, retrieval, OCR and OMR, Math and Music Notation. Numerous architectures (XLM-R, Qwen3-Embed, Gemma3, ModernBERT, ...), dense + sparse + ColBERT + reranking. PP-OCR, Tesseract, EasyOCR, InternVL2, etc. Python/Rust/Dart bindings. |\n|\nPython ASR GUI with 9 backends (faster-whisper, mlx-whisper, voxtral, insanely-fast-whisper, ...). The Python counterpart to CrispASR's C++ approach. |\n\n— new to CrispASR? Two commands to your first working audio, no repo clone needed**Start here**[Supported backends](#supported-backends)—[ASR](#asr-backends)+[TTS](#text-to-speech-models)+[translation](#translation)+[post-processing](#post-processing-models)+[music & audio analysis](#music--audio-analysis)[Feature matrix](#feature-matrix)[Install & build](#install--build)— quick install (full guide in[docs/install.md](/CrispStrobe/CrispASR/blob/main/docs/install.md));— the[which prebuilt Linux tarball to download](/CrispStrobe/CrispASR/blob/main/docs/install.md#prebuilt-linux-tarballs--which-one-to-download-355)`-hip`\n\n/`-vulkan`\n\nbuilds require the matching GPU driver and do**not** fall back to CPU (the`-cuda`\n\ntarballs do, since v0.8.30)[Quick start — ASR](#quick-start)[Troubleshooting](/CrispStrobe/CrispASR/blob/main/docs/troubleshooting.md)— it printed the banner and stopped, reading the exit code,`--no-gpu`\n\nbisect, which Windows zip— 52 engines: Kokoro, Qwen3-TTS, VibeVoice, dots.tts, Orpheus, Chatterbox, IndexTTS, Irodori, VoxCPM2, CosyVoice3, CSM, Dia, Zonos, Bark, Piper, MeloTTS, and more**Text-to-Speech (TTS)**[Streaming & live transcription](/CrispStrobe/CrispASR/blob/main/docs/streaming.md)[Server mode (HTTP API)](/CrispStrobe/CrispASR/blob/main/docs/server.md)[Concurrency, parallelism & scaling](/CrispStrobe/CrispASR/blob/main/docs/concurrency.md)— how one transcription uses multiple cores, concurrent server requests (`--server-workers`\n\n), bulk offline transcription, replicas behind a load balancer[CLI reference](/CrispStrobe/CrispASR/blob/main/docs/cli.md)— flags, VAD, CTC alignment, output formats, auto-download, audio formats[Environment variables](/CrispStrobe/CrispASR/blob/main/docs/environment-variables.md)— the`CRISPASR_<BACKEND>_<FEATURE>`\n\nconvention, global knobs, and every per-backend variable[Language bindings](/CrispStrobe/CrispASR/blob/main/docs/bindings.md)— Python / Rust / Dart / Go / Java / JavaScript / Ruby / mobile[Benchmarking CrispASR](/CrispStrobe/CrispASR/blob/main/docs/benchmarking.md)— how to measure transcribe time (not cold start): server/in-process reps, proof-of-work rules, phase-timing env vars[Architecture](/CrispStrobe/CrispASR/blob/main/docs/architecture.md)— layered layout,`src/core/`\n\nprimitives, regression discipline[Contributing — adding a new backend](/CrispStrobe/CrispASR/blob/main/docs/contributing.md)— 5-file recipe, ground-truth diff workflow[Regression matrix](/CrispStrobe/CrispASR/blob/main/docs/regression-matrix.md)—`tools/test-all-backends.py`\n\ncapability tiers— synthetic-audio marking (watermark + C2PA + spoken disclaimer), what counts as a voice clone, the speaker-biometrics boundary, why there is no emotion recognition, and what stays your duty as deployer**EU AI Act**[Quantize models](/CrispStrobe/CrispASR/blob/main/docs/quantize.md)—`crispasr-quantize`\n\nfor all backends[GPU backend selection](#gpu-backend-selection)[Debugging & profiling](#debugging--profiling)[Credits](#credits)\n\nEverything below this section is a catalogue — 100+ backends, browse it when you\nneed one. If you just want CrispASR *working*, this is the whole path. No repo\nclone, no Python, no model hunting.\n\nDownload one file from [ Releases](https://github.com/CrispStrobe/CrispASR/releases/latest)\nand unzip it:\n\n| Platform | Download | Notes |\n|---|---|---|\nWindows |\n`crispasr-windows-x86_64-cpu.zip` |\nNeeds AVX2 (2013+ Intel / 2015+ AMD). Older CPU → `…-cpu-legacy.zip` |\nWindows + NVIDIA |\n`crispasr-windows-x86_64-cuda.zip` |\nSelf-contained; a CUDA Toolkit install is not required. CUDA-13-native build: `…-cuda13.zip` (Turing+) |\nmacOS |\n`crispasr-macos.tar.gz` |\nMetal GPU support built in |\nLinux |\n`crispasr-linux-x86_64.tar.gz` |\n`…-cuda.tar.gz` / `…-vulkan.tar.gz` for GPU |\n\nPrefer to build it yourself? See [Install & build](#install--build). The `-hip`\n\nand `-vulkan`\n\nbuilds require the matching driver and do **not** fall back to CPU;\nthe Linux `-cuda`\n\ntarballs do fall back.\n\nCheck it runs — this should print a version banner and exit:\n\n```\ncrispasr --version          # Windows: .\\crispasr.exe --version\n```\n\n`-m auto`\n\ndownloads the model on first use (~135 MB here) and reuses it\nafterwards — nothing to find or install. It lands in `~/.cache/crispasr/`\n\n(`%USERPROFILE%\\.cache\\crispasr`\n\non Windows).\n\n```\ncrispasr --backend kokoro -m auto --tts \"The quick brown fox jumps over the lazy dog.\" --tts-output hello.wav\n# crispasr: TTS output written to 'hello.wav' (78000 samples @ 24000 Hz, 3.25 sec)\n```\n\nPlay `hello.wav`\n\n. That is the TTS half working.\n\n```\ncrispasr --backend parakeet -m auto -f hello.wav -l en\n# crispasr: transcribed 3.2s audio in 0.32s (10.1x realtime)\n# The quick brown fox jumps over the lazy dog.\n```\n\n(~467 MB on first run. `-l en`\n\nskips language auto-detection, which would\notherwise fetch a small extra model.) Both halves now work — swap in your own\n`.wav`\n\nand you are running.\n\n| You want to… | Go to |\n|---|---|\n| Clone a voice from a recording |\n`--i-have-rights` |\n\n[Which backend should I pick?](#which-backend-should-i-pick)[docs/cli.md](/CrispStrobe/CrispASR/blob/main/docs/cli.md)[docs/streaming.md](/CrispStrobe/CrispASR/blob/main/docs/streaming.md)[docs/server.md](/CrispStrobe/CrispASR/blob/main/docs/server.md)`crispasr --list-backends`\n\nAdd `-v`\n\nto any command for verbose progress, and `--dry-run-resolve`\n\nto print\nwhich model files it would open (and whether they're on disk) without loading\nanything.\n\nIf a command printed its banner and then simply stopped — no error, no output\nfile — that is a crash, not a refusal, and the exit code identifies it in one\nstep. See ** docs/troubleshooting.md**.\n\nCrispASR ships **54 ASR backends** for transcription/translation and\n**55 TTS engines** for synthesis. It also ships audio-to-audio S2S backends,\nincluding Sidon restoration and the VoxCPM2 AudioVAE speech upscaler; see the [feature matrix](/CrispStrobe/CrispASR/blob/main/docs/feature-matrix.md)\nfor the complete capability list.\nPick at the CLI with `--backend NAME`\n\n, or omit it to let the binary auto-detect\nfrom the GGUF metadata. Jump to the [TTS table](#text-to-speech-models) for the synthesis side.\n\n| Backend | Model | Architecture | Languages | License |\n|---|---|---|---|---|\nwhisper |\n`ggml-base.en.bin` |\n\n**whisper**`distil-whisper/distil-large-v3`\n\n**parakeet**`nvidia/parakeet-tdt-0.6b-v3`\n\n**parakeet**`nvidia/parakeet-tdt-0.6b-v2`\n\n**parakeet**`nvidia/parakeet-tdt-1.1b`\n\n**parakeet**`nvidia/parakeet-tdt_ctc-110m`\n\n**parakeet**`nvidia/parakeet-tdt_ctc-1.1b`\n\n**parakeet**`nvidia/parakeet-tdt_ctc-0.6b-ja`\n\n**reazonspeech**`reazon-research/reazonspeech-nemo-v2`\n\n**fastconformer-ctc**`nvidia/parakeet-ctc-0.6b`\n\n**fastconformer-ctc**`nvidia/parakeet-ctc-1.1b`\n\n**fastconformer-ctc**`grider-transwithai/parakeet-ctc-1.1b-ja`\n\n**canary**`nvidia/canary-1b-v2`\n\n`-sl/-tl`\n\n)**canary-qwen**`nvidia/canary-qwen-2.5b`\n\n**lfm2-audio**`LiquidAI/LFM2.5-Audio-1.5B`\n\n**lfm2-audio**`LiquidAI/LFM2.5-Audio-1.5B-JP`\n\n**mini-omni2**`gpt-omni/mini-omni2`\n\n**cohere**`CohereLabs/cohere-transcribe-03-2026`\n\n**cohere**`efwkjn/cohere-asr-ja-v0.1`\n\n**granite**[,](https://huggingface.co/ibm-granite/granite-speech-3.3-2b)`ibm-granite/granite-speech-{3.2-8b,3.3-2b,3.3-8b}`\n\n`granite-4.0-1b-speech`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#granite--granite-41--granite-41-plus--granite-41-nar))**granite-4.1**`ibm-granite/granite-speech-4.1-2b`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#granite--granite-41--granite-41-plus--granite-41-nar))**granite-4.1-plus**`ibm-granite/granite-speech-4.1-2b-plus`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#granite--granite-41--granite-41-plus--granite-41-nar))**granite-4.1-nar**`ibm-granite/granite-speech-4.1-2b-nar`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#granite--granite-41--granite-41-plus--granite-41-nar))**fastconformer-ctc**`nvidia/stt_en_fastconformer_ctc_large`\n\n**voxtral**`mistralai/Voxtral-Mini-3B-2507`\n\n**voxtral4b**`mistralai/Voxtral-Mini-4B-Realtime-2602`\n\n**qwen3**`Qwen/Qwen3-ASR-0.6B`\n\n**qwen3-1.7b**`Qwen/Qwen3-ASR-1.7B`\n\n**qwen3-ja-anime**`jaykwok/Qwen3-ASR-1.7B-JA-Anime-Galgame-hf`\n\n**mega-asr**`zhifeixie/Mega-ASR`\n\n**higgs-stt**`bosonai/higgs-audio-v3-stt`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#higgs-stt))**wav2vec2**`jonatasgrosman/wav2vec2-large-xlsr-53-english`\n\n**wav2vec2**`facebook/data2vec-audio-base-960h`\n\n**wav2vec2**`facebook/hubert-large-ls960-ft`\n\n**glm-asr**`zai-org/GLM-ASR-Nano-2512`\n\n**kyutai-stt**`kyutai/stt-1b-en_fr`\n\n**kyutai-stt**`kyutai/stt-2.6b-en`\n\n**firered-asr**`FireRedTeam/FireRedASR2-AED`\n\n**moonshine**`UsefulSensors/moonshine-{tiny,base}`\n\n**moonshine‑de**`fidoriel/moonshine-base-de`\n\n**moonshine‑tiny‑de**`fidoriel/moonshine-tiny-de`\n\n**moonshine-streaming**`UsefulSensors/moonshine-streaming-{tiny,small,medium}`\n\n**gemma4-e2b**`google/gemma-4-E2B-it`\n\n**gemma4-e4b**`google/gemma-4-E4B-it`\n\n`--backend gemma4-e2b`\n\n**omniasr**`omniASR-CTC-1B-v2`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#omniasr-ctc--llm--unlimited))**1600+****omniasr‑300m**`omniASR-CTC-300M-v2`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#omniasr-ctc--llm--unlimited))**1600+****omniasr-llm**`omniASR-LLM-300M-v2`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#omniasr-ctc--llm--unlimited))**1600+****omniasr-llm**`omniASR-LLM-Unlimited-300M-v2`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#omniasr-ctc--llm--unlimited))**1600+****vibevoice**`microsoft/VibeVoice-ASR`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#vibevoice))**vibevoice-bitnet**`VibeVoice-ASR-BitNet`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#vibevoice))**mimo-asr**`XiaomiMiMo/MiMo-V2.5-ASR`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#mimo-asr))**ark-asr*** experimental/WIP*[(base](https://huggingface.co/cstr/ark-asr-3b-GGUF)`cstr/ark-asr-3b-GGUF`\n\n[)](https://huggingface.co/AutoArk-AI/ARK-ASR-3B)`AutoArk-AI/ARK-ASR-3B`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#ark-asr))**moss-audio**`OpenMOSS-Team/MOSS-Audio-4B-Instruct`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#moss-audio))**moss-transcribe**`OpenMOSS-Team/MOSS-Transcribe-preview-2B`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#moss-transcribe))**moss-diarize**`OpenMOSS-Team/MOSS-Transcribe-Diarize-0.9B`\n\n**whisper***(tiron)** experimental*[(base](https://huggingface.co/cstr/tiron-GGML)`Trelis/tiron`\n\n[)](https://huggingface.co/Trelis/tiron)`Trelis/tiron`\n\n**funasr**`FunAudioLLM/Fun-ASR-Nano-2512`\n\n**fun-asr-mlt-nano**`FunAudioLLM/Fun-ASR-MLT-Nano-2512`\n\n**paraformer**`funasr/paraformer-zh`\n\n**foxnose***(speaker diarization)*`Wespeaker/wespeaker-voxceleb-resnet34-LM`\n\n`--diarize-method foxnose`\n\n: WeSpeaker ResNet34-LM 256-d embeddings + GMM/BIC speaker counting + spectral clustering + Viterbi temporal smoothing ([more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#foxnose-diarize)). 3.18 % DER on VoxConverse dev vs the upstream reference implementation's 3.07 %**gigaam**[(base](https://huggingface.co/cstr/gigaam-v3-GGUF)`ai-sage/GigaAM-v3`\n\n[)](https://huggingface.co/ai-sage/GigaAM-v3)`ai-sage/GigaAM-v3`\n\n`e2e_rnnt`\n\n/ `e2e_ctc`\n\nemit punctuation + casing + ITN from a SentencePiece vocab, `rnnt`\n\n/ `ctc`\n\nemit bare lowercase Cyrillic ([more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#gigaam))**sensevoice**`FunAudioLLM/SenseVoiceSmall`\n\n`-oj`\n\nJSON expose the tags as separate fields. Upstream's emotion classifier is **not exposed**— see[EU AI Act](/CrispStrobe/CrispASR/blob/main/docs/eu-ai-act.md#41-emotion-recognition--removed-not-gated)| Backend | Model | Architecture | Input / output | License |\n|---|---|---|---|---|\nsidon |\n`KevinAHM/Sidon-GGUF` |\n\n[)](https://huggingface.co/sarulab-speech/sidon-v0.1)\n\n`sarulab-speech/sidon-v0.1`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#sidon))**voxcpm2-vae**[, converted with](https://huggingface.co/openbmb/VoxCPM2)`openbmb/VoxCPM2`\n\n`--vae-only`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#voxcpm2-vae))\n\n```\nhuggingface-cli download KevinAHM/Sidon-GGUF sidon-v0.1-f16.gguf --local-dir models\ncrispasr -m models/sidon-v0.1-f16.gguf -f input.wav --s2s --s2s-output restored.wav\n\npython models/convert-voxcpm2-to-gguf.py --input openbmb/VoxCPM2 \\\n  --output models/voxcpm2-vae-f32.gguf --vae-only\ncrispasr -m models/voxcpm2-vae-f32.gguf -f input.wav --s2s \\\n  --s2s-output upscaled.wav\n```\n\nSynthesis backends, driven by the `--tts`\n\nflag and a `--tts-output PATH.wav`\n\n.\nSee the dedicated [Text-to-Speech](#text-to-speech-models) section below for\nquick-start commands and engine selection guidance.\n\n| Backend | Models | Architecture | Languages | License |\n|---|---|---|---|---|\nmiotts |\n`MioTTS-0.6B` |\n\n**vibevoice-tts**[,](https://huggingface.co/cstr/vibevoice-realtime-0.5b-GGUF)`VibeVoice-Realtime-0.5B`\n\n`VibeVoice-1.5B`\n\n**kugelaudio**`kugelaudio-0-open`\n\n**qwen3-tts**[,](https://huggingface.co/cstr/qwen3-tts-0.6b-base-GGUF)`Qwen3-TTS-12Hz-0.6B-Base`\n\n[,](https://huggingface.co/cstr/qwen3-tts-1.7b-base-GGUF)`1.7B-Base`\n\n`1.7B-VoiceDesign`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#qwen3-tts))**qwen3-tts-customvoice**`1.7B-CustomVoice`\n\n`--voice <name>`\n\n); optional style via `--instruct`\n\n(e.g. \"spoke very slowly\") ([more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#qwen3-tts))**moss-tts**`OpenMOSS-Team/MOSS-TTS-v1.5`\n\n`--voice ref.wav`\n\n; `--backend moss-tts -m <backbone> --codec-model <codec>`\n\n**moss-tts-local**`OpenMOSS-Team/MOSS-TTS-Local-Transformer-v1.5`\n\n`--backend moss-tts-local -m <backbone> --codec-model <codec>`\n\n**omnivoice**`k2-fsa/OmniVoice`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#omnivoice))**melotts**[EN_V2](https://github.com/myshell-ai/MeloTTS)`myshell-ai/MeloTTS`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#melotts))**piper**[community voices](https://github.com/rhasspy/piper)`rhasspy/piper`\n\n`--g2p-dict`\n\n)**kokoro**[+ German backbones](https://huggingface.co/hexgrad/Kokoro-82M)`hexgrad/Kokoro-82M`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#kokoro))**orpheus**[+](https://huggingface.co/cstr/orpheus-3b-0.1-ft-GGUF)`Orpheus-3B-FT`\n\n`SNAC 24 kHz`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#orpheus))**chatterbox**[+ Nano/turbo/fine-tune variants](https://huggingface.co/cstr/chatterbox-GGUF)`cstr/chatterbox-GGUF`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#chatterbox--chatterbox-turbo--chatterbox-nano--chatterbox-finnish-nano--kartoffelbox-turbo--lahgtna-chatterbox))`chatterbox-finnish-nano`\n\n) fine-tunes**indextts**`cstr/indextts-1.5-GGUF`\n\n**voxcpm2-tts**`cstr/voxcpm2-GGUF`\n\n`--voice <wav>`\n\n**voxtral-tts**`mistralai/Voxtral-4B-TTS-2603`\n\n**cosyvoice3-tts**`cstr/cosyvoice3-0.5b-2512-GGUF`\n\n`--voice <name>`\n\n, or any WAV via `--voice ref.wav --ref-text \"<exact transcript>\"`\n\n. `--backend cosyvoice3-tts-rl`\n\nselects upstream's RL-tuned talker (same companions)**csm**`cstr/csm-1b-GGUF`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#csm))**lfm2-audio**[+](https://huggingface.co/cstr/lfm2-audio-1.5b-GGUF)`cstr/lfm2-audio-1.5b-GGUF`\n\n`jp`\n\n**dia**`nari-labs/Dia-1.6B`\n\n`[S1]`\n\n/`[S2]`\n\ntags (use >100-char prompts)**zonos-tts**[+](https://huggingface.co/cstr/zonos-v0.1-transformer-GGUF)`cstr/zonos-v0.1-transformer-GGUF`\n\n`cstr/dac-44khz-GGUF`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#zonos-tts))**bark**`cstr/bark-small-GGUF`\n\n`.npz`\n\nprompts (`--voice <file.npz>`\n\n)**speecht5**`cstr/speecht5-tts-GGUF`\n\n`--voice <xvector.bin>`\n\n)**fastpitch**`cstr/fastpitch-en-GGUF`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#fastpitch))**bananamind-tts**`Banaxi-Tech/BananaMind-TTS-V2.1-Preview`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#bananamind-tts))**parler-tts**`cstr/parler-tts-mini-v1.1-GGUF`\n\n`--instruct`\n\n)**outetts**`cstr/outetts-0.3-1b-GGUF`\n\n`--voice <speaker.json>`\n\n)**pocket-tts**`cstr/pocket-tts-GGUF`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#pocket-tts))**tada**[+](https://huggingface.co/cstr/tada-tts-1b-GGUF)`cstr/tada-tts-1b-GGUF`\n\n`HumeAI/tada-3b-ml`\n\n`tada-ref.gguf`\n\n, custom voices via `--voice <tada-ref.gguf>`\n\nbuilt with `models/convert-tada-ref-to-gguf.py`\n\n([more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#tada))**TTS feature matrix**\n\n| Backend | Voice cloning | Sampling | kHz | Auto-download | Flash attn |\n|---|---|---|---|---|---|\n| vibevoice-tts | yes | temp | 24 | yes | yes |\n| qwen3-tts | yes* | temp | 24 | yes | yes |\n| omnivoice | yes | temp | 24 | — | — |\n| kokoro | — | — | 24 | yes | — |\n| orpheus | — | temp | 24 | yes | yes |\n| chatterbox | yes | temp | 24 | yes | yes |\n| outetts | yes (JSON) | temp | 24 | yes | yes |\n| indextts | yes | temp | 24 | yes | yes |\n| voxcpm2-tts | yes | — | 48 | yes | — |\n| cosyvoice3-tts | yes | temp | 24 | yes | yes |\n| f5-tts | yes | — | 24 | yes | — |\n| irodori-tts | yes (WAV) | VoiceDesign: `--instruct` |\n48 | yes | — |\n| csm | — | temp | 24 | yes | — |\n| dia | — | temp | 44 | yes | — |\n| bark | yes (.npz) | temp | 24 | yes | — |\n| speecht5 | yes (xvec) | — | 16 | yes | — |\n| parler-tts | — | temp | 44 | yes | — |\n| fastpitch | — | — | 22 | — | — |\n| piper | — | — | 22 | — | — |\n| pocket-tts | yes | temp | 24 | yes | — |\n| tada | yes | temp | 24 | yes | — |\n| dots-tts | yes (`--voice ref.wav` ) |\n16-step CFG Euler | 48 | yes | — |\n| confucius4-tts | yes (`--voice ref.wav` ) |\n25-step CFG Euler | 22.05 | yes | — |\n\n* CustomVoice variant only; Base uses baked speakers via `--voice <name>`\n\n.\n\n**Output language.** `-tl <lang>`\n\n(or `-l`\n\n) selects the language to speak;\n`cosyvoice3-tts`\n\n, `qwen3-tts`\n\nand `moss-tts`\n\nact on it natively. For\ncross-lingual **cloning** — an English reference clip speaking German, the\nsubtitle-dubbing case — also pass `-sl <lang>`\n\nfor the language the reference is\nspoken in, so cosyvoice3 drops the reference transcript instead of carrying its\naccent. Over HTTP: `\"language\"`\n\n+ `\"source_lang\"`\n\non `POST /v1/audio/speech`\n\n.\nSee [ docs/tts.md](/CrispStrobe/CrispASR/blob/main/docs/tts.md#output-language-and-cross-lingual-cloning--tl---sl).\n\nText-to-text translation, distinct from the audio-side `--translate`\n\nflag (which routes audio → English text on whisper / canary / etc.).\nDriven by `--text \"...\" -sl <src> -tl <tgt>`\n\n.\n\n| Backend | Models | Architecture | Languages | License |\n|---|---|---|---|---|\nm2m100 |\n`facebook/m2m100_418M` |\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#m2m100--wmt21))**m2m100-wmt21**[+](https://huggingface.co/cstr/wmt21-dense-24-wide-en-x-GGUF)`facebook/wmt21-dense-24-wide-en-x`\n\n`facebook/wmt21-dense-24-wide-x-en`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#m2m100--wmt21))`en-x`\n\n/ `x-en`\n\ncheckpoints)**madlad**`google/madlad400-3b-mt`\n\n[more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#madlad))\n\n```\n# m2m100 base (production-ready)\n./build/bin/crispasr --backend m2m100 -m auto \\\n    --text \"Hello world, how are you today?\" \\\n    -sl en -tl de\n# → Hallo Welt, wie bist du heute?\n\n# WMT21 dense (English ↔ X, 4.7B — auto-downloads ~2.5 GB).\n# Two separate checkpoints: en-x for English-source, x-en for\n# English-target. Pick the one matching your `-sl`/`-tl` direction\n# (or pass an explicit `-m <path>` to load the other manually).\n./build/bin/crispasr --backend m2m100-wmt21 -m auto \\\n    --text \"The president said he would not attend.\" \\\n    -sl en -tl de   # uses wmt21-dense-24-wide-en-x\n\n./build/bin/crispasr --backend m2m100-wmt21 \\\n    -m models/wmt21-dense-24-wide-x-en-q4_k.gguf \\\n    --text \"Le président a dit qu'il ne serait pas présent.\" \\\n    -sl fr -tl en   # uses wmt21-dense-24-wide-x-en\n\n# MADLAD-400 3B (419 languages, bit-token-identical to Python SP)\n./build/bin/crispasr --backend madlad -m auto \\\n    --text \"Hello world.\" \\\n    -sl en -tl ta\n```\n\nFor 2-stage pipelines (e.g., ASR → m2m100), use the dedicated\n`--tr-sl`\n\n/ `--tr-tl`\n\nflags; they fall back to `-sl`\n\n/ `-tl`\n\nwhen\nunset, so single-stage standalone usage is just `-sl/-tl`\n\n.\n\nWork with all backends.\n\n| Model | Task | Architecture | Languages | License | HuggingFace |\n|---|---|---|---|---|---|\nFireRedPunc |\nPunctuation restoration | BERT-base (12L, d=768), 5 classes | Chinese + English | Apache-2.0 |\n`cstr/fireredpunc-GGUF` |\n\n**fullstop-punc**`cstr/fullstop-punc-multilang-GGUF`\n\n**punctuate-all**`cstr/punctuate-all-GGUF`\n\n**PCS**`--punc-model pcs`\n\n**truecaser‑lstm**`--truecase-model lstm`\n\n**truecaser‑crf**`--truecase-model crf`\n\n**truecaser‑de**`--truecase-model auto`\n\n**CLD3**`cstr/cld3-GGUF`\n\n**GlotLID-V3**`cstr/glotlid-GGUF`\n\n**LID-176**`cstr/fasttext-lid176-GGUF`\n\nShared codec modules used by TTS backends. Also available standalone for encode/decode.\n\n| Model | Architecture | Sample Rate | Token Rate | License | HuggingFace |\n|---|---|---|---|---|---|\nMioCodec v2 |\nWavLM encoder → FSQ(12800) → Transformer decoder + AdaLN-Zero + SnakeBeta upsampler + iSTFT | 44.1 kHz | 25 Hz (341 bps) | MIT |\n`cstr/miocodec-v2-44k-GGUF` |\n\n**SNAC 24 kHz**`cstr/snac-24khz-GGUF`\n\nAll runtimes share ggml-based inference. The speech-LLM backends (**qwen3**, **voxtral**, **voxtral4b**, **granite**, **glm-asr**, **kyutai-stt**) inject audio encoder frames directly into an autoregressive language model's input embeddings, instead of using a dedicated CTC/transducer/seq2seq decoder. The **fastconformer-ctc** backend hosts the NeMo FastConformer-CTC standalone ASR family — `stt_en_fastconformer_ctc_{large,xlarge,xxlarge}`\n\nand the architecturally-identical `parakeet-ctc-{0.6b,1.1b}`\n\n(different training data + tokenizer, same encoder + head shape) — with greedy CTC decoding. Same C++ runtime as the canary-ctc aligner.\n\nBeyond speech, CrispASR runs several music/audio analysis tasks — each a small\nGGUF with the architecture auto-detected, no Python. See [ docs/cli.md](/CrispStrobe/CrispASR/blob/main/docs/cli.md)\nfor the per-task flags and output formats.\n\n**Source separation**(`--separate`\n\n) — split a mix into stems (`<input>_<stem>.wav`\n\n) via**mel-band-roformer**(vocal/instrumental, MIT) or** htdemucs**(4-stem).`--stems vocals,drums`\n\nselects a subset;`--sep-output-dir`\n\nsets the output location.**Piano transcription**(`--backend piano-transcription`\n\n) — piano audio → MIDI note events (88 keys @ 100 fps, ByteDance/Kong CRNN; F16 GGUF ≈ 77 MB).**Guitar tablature**(`--tab`\n\n) — per-frame fret-per-string grid via**TabCNN**(Wiggins & Kim, ISMIR 2019; CC BY 4.0 weights). The backend emits per-string emission scores, not a decided tablature — run your own constrained Viterbi via`crispasr_session_tab_emissions()`\n\nfor playable output.**Beat / downbeat tracking**(`--beats`\n\n) — beat grid via**Beat This!**(CPJKU, ISMIR 2024; MIT for code*and*weights, no patent-encumbered DBN).**Chord recognition**(`--chords`\n\n) — chord timeline (`.lab`\n\n) via**BTC**(ISMIR 2019). Weights are CC-BY-NC-SA, gated behind`--accept-license cc-by-nc-sa-4.0`\n\n.**Pitch / F0 estimation**(`--pitch`\n\n) — monophonic pitch track via**CREPE**(MIT).\n\nRun `crispasr --list-backends`\n\nto see it live. Each backend declares capabilities at runtime; if you ask for a feature the selected backend does not support, CrispASR prints a warning and silently ignores the flag.\n\n**Sortable / filterable view:** [ docs/feature-matrix.html](/CrispStrobe/CrispASR/blob/main/docs/feature-matrix.html) — click any column header to sort, type to filter rows, click cap pills to require a capability. Generated from\n\n`crispasr --list-backends-json`\n\n(single source of truth — drift impossible). Regenerate via `python tools/gen-feature-matrix.py`\n\n. A Markdown twin lives at [.](/CrispStrobe/CrispASR/blob/main/docs/feature-matrix.md)\n\n`docs/feature-matrix.md`\n\nThe static table below is a curated subset focusing on the ASR backends and the cross-cutting features that matter for ASR pipelines. The full 109-backend × 27-cap surface is in the generated views.\n\n| Feature | whisper | parakeet | canary | cohere | granite | granite‑4.1 | voxtral | voxtral4b | qwen3 | fc‑ctc | wav2vec2 | glm‑asr | kyutai‑stt | firered | moonshine | moon‑stream | omniasr | omniasr‑llm | vibevoice | gemma4‑e2b | mimo‑asr | funasr | paraformer | sensevoice |\n|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|\n| Native timestamps | ✔ | ✔ | ✔ | ✔ | ✔ | |||||||||||||||||||\n| CTC timestamps | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ||||\n| Word-level timing | ✔ | ✔ | ✔ | ✔ | `-am` |\n✔† | `-am` |\n`-am` |\n`-am` |\n`-am` |\n`-am` |\n`-am` |\n✔ | `-am` |\n`-am` |\n`-am` |\n`-am` |\n`-am` |\n`-am` |\n`-am` |\n`-am` |\n`-am` |\n||\n| Per-token confidence | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ||||\n| Language auto-detect | ✔ | ✔ | LID | LID | LID | LID | LID | LID | ✔ | LID | LID | ✔ | LID | LID | LID | LID | LID | LID | LID | ✔ | LID | LID | LID | ✔ |\n| Speech translation | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ||||||||||||||||||\n| Speaker diarization | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |\n| Grammar (GBNF) | ✔ | |||||||||||||||||||||||\n| Temperature sampling | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | |||||\n| Beam search | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | |||||||||||||\n| Flash attention | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ||\n| Punctuation toggle | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | |||||||||\n| Punc restoration | pp | pp | pp | pp | pp | pp | pp | pp | pp | pp | pp | pp | pp | pp | pp | pp | pp | pp | pp | pp | pp | pp | pp | pp |\n| Source / target language | ✔ | ✔ | ✔ | ✔ | ✔ | |||||||||||||||||||\nAudio Q&A (`--ask` ) |\n* | * | ✔ | * | * | * | * | |||||||||||||||||\n| Streaming | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |\nAuto-download (`-m auto` ) |\n✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |\nKV quant (`CRISPASR_KV_QUANT` , plus per-half `_K` / `_V` ) |\n✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ||||||||||||||\nmmap weights (`CRISPASR_GGUF_MMAP` ) |\n✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | |\n| TTS | ✔ |\n\nThe matrix above covers 24 ASR backends. **Additional ASR backends** not shown: `nemotron`\n\n(39-lang streaming ASR with cache-aware FastConformer + RNN-T), `lfm2-audio`\n\n(ASR + TTS + S2S in one model), `moss-audio`\n\n(audio understanding + ASR), `moss-transcribe`\n\n(Qwen3-Omni encoder + Qwen3-1.7B ASR), `mini-omni2`\n\n(ASR + TTS + S2S), `kugelaudio`\n\n(7B audio understanding). See [ docs/feature-matrix.md](/CrispStrobe/CrispASR/blob/main/docs/feature-matrix.md) for the full 109-backend matrix.\n\n**TTS-only backends**(\n\n`kokoro`\n\n, `qwen3-tts`\n\n+ variants, `vibevoice-tts`\n\n, `orpheus`\n\n+ DE variants, `chatterbox`\n\n/ `chatterbox-turbo`\n\n/ `chatterbox-nano`\n\n/ `kartoffelbox-turbo`\n\n/ `lahgtna-chatterbox`\n\n, `dia`\n\n, `bark`\n\n, `outetts`\n\n, `zonos`\n\n, `csm`\n\n, `f5-tts`\n\n, `irodori-tts`\n\n, `parler-tts`\n\n, `speecht5`\n\n, `piper`\n\n, `fastpitch`\n\n, `pocket-tts`\n\n, `melotts`\n\n, `cosyvoice3`\n\n, `voxcpm2`\n\n, `tada-tts`\n\n) all carry the TTS, AUTO_DOWNLOAD, TEMPERATURE, and FLASH_ATTN caps; per-backend cloning + voice-pack support is documented in the [Text-to-Speech models](#text-to-speech-models)table above and\n\n[. The vibevoice and lfm2-audio columns mark dual-mode (ASR + TTS) backends.](/CrispStrobe/CrispASR/blob/main/docs/tts.md)\n\n`docs/tts.md`\n\n**Key:** ✔ = native/built-in, `-am`\n\n= via CTC forced aligner (`-am canary-ctc-aligner.gguf`\n\nor `-am qwen3-forced-aligner.gguf`\n\n), **LID** = via external language identification pre-step (`-l auto`\n\n), **pp** = via `--punc-model`\n\npost-processor (FireRedPunc or fullstop-punc), * = experimental or partial support, † = PLUS variant only (native `[T:N]`\n\nword timestamps with `-owts`\n\n; base uses `-am`\n\n). granite-4.1 covers both the regular and `-plus`\n\nvariants; granite-4.1-nar is a non-autoregressive variant with encoder+projector only (no LLM decode features). The **KV quant** row marks backends that honor `CRISPASR_KV_QUANT={f16,q8_0,q4_0}`\n\n— CTC-style backends without a KV cache (parakeet, fc-ctc, wav2vec2, kyutai-stt, firered, moonshine variants, omniasr-CTC) don't apply. The same backends also honor the per-half `CRISPASR_KV_QUANT_K`\n\n/ `CRISPASR_KV_QUANT_V`\n\noverrides (llama.cpp `--cache-type-k`\n\n/ `--cache-type-v`\n\nparity) for asymmetric K-vs-V precision; common recipe `K=q8_0 V=q4_0`\n\nsaves ~40 % more KV memory than symmetric Q8_0. The **mmap weights** row marks backends consuming `core_gguf::load_weights()`\n\nand therefore honoring `CRISPASR_GGUF_MMAP=1`\n\n; whisper itself uses upstream's loader and is unaffected. See [ docs/cli.md](/CrispStrobe/CrispASR/blob/main/docs/cli.md) Memory footprint for usage + recommended combos.\n\n**Speaker diarization** as a post-processing step via `--diarize`\n\n:\n\n`energy`\n\n/`xcorr`\n\n— stereo-only, no extra deps`foxnose`\n\n—**best accuracy, no external deps**: WeSpeaker ResNet34-LM embeddings + GMM/BIC speaker counting + spectral clustering + Viterbi smoothing. Estimates the speaker count rather than needing it up front;`--diarize-embedder auto`\n\nfetches the GGUF (24 MB, CC-BY-4.0). 7.3 % DER on VoxConverse dev where`pyannote`\n\n+ TitaNet scores 7.8 %, and 3.18 % vs the upstream reference's 3.07 % when scored on turns ([more](/CrispStrobe/CrispASR/blob/main/docs/architecture.md#foxnose-diarize))`pyannote`\n\n— native GGUF (no Python, no sherpa-onnx); add`--diarize-embedder auto`\n\n(TitaNet) or`--diarize-embedder indextts`\n\n(ECAPA-TDNN) for globally stable speaker IDs across long files`sherpa`\n\n/`ecapa`\n\n— external[sherpa-onnx](https://github.com/k2-fsa/sherpa-onnx)subprocess; runs once globally on full audio for consistent speaker IDs (#110)`vad-turns`\n\n— mono-friendly gap-based proxy\n\nThe server endpoint supports `response_format=diarized_json`\n\nfor structured speaker-labelled output with normalised speaker letters (A, B, C …) — see [ docs/server.md](/CrispStrobe/CrispASR/blob/main/docs/server.md#diarized-json-format-206).\n\nFull reference + tuning knobs (cluster threshold, max speakers, pluggable embedder adapters): see [ docs/cli.md#diarization](/CrispStrobe/CrispASR/blob/main/docs/cli.md#diarization).\n\n**Language identification** for backends without native LID: `--lid-backend whisper`\n\n(default, 75 MB ggml-tiny.bin), `--lid-backend silero`\n\n(native GGUF, 16 MB, 95 languages), or `--lid-backend firered`\n\n(FireRedLID, 1.7 GB, 120 languages — Conformer encoder + Transformer decoder).\n\n**Voice activity detection**: `--vad`\n\nuses the default Silero VAD (~885 KB, auto-downloaded). Each VAD segment is transcribed independently, producing separate SRT/VTT entries with correct timestamps. Use `--vad --split-on-punct`\n\nfor best subtitle output. Four VAD backends: Silero (default), FireRedVAD (`-vm firered`\n\n, recommended), MarbleNet (`-vm marblenet`\n\n, 439 KB, 6 languages), Whisper-VAD-EncDec (`-vm whisper-vad`\n\n, experimental).\n\n**Punctuation restoration** (`--punc-model`\n\n): CTC-based backends output lowercase without punctuation. Named shortcuts: `auto`\n\n/`firered`\n\n(Chinese+English), `fullstop`\n\n(EN/DE/FR/IT, XLM-R-large), `punctuate-all`\n\n(12 languages, XLM-R-base), `pcs`\n\n(47 languages, punc + truecasing + sentence boundary detection in one model). Or pass a GGUF path directly. Also available via Python/Rust/Dart wrappers (`crispasr.PuncModel`\n\n).\n\n**Truecasing** (`--truecase-model`\n\n): Restore German noun/name capitalization in lowercase ASR output. Three options in ascending quality: `auto`\n\n(statistical, 1.7 MB), `crf`\n\n(CRF with context, 8.5 MB), `lstm`\n\n(BiLSTM char-level, 3.2 MB, **recommended** — 97.9% F1, handles adjective/noun distinction and formal \"Ihnen\"). All auto-download from [ cstr/truecaser-de](https://huggingface.co/cstr/truecaser-de). Or use\n\n`--punc-model pcs`\n\nfor neural punc + truecasing in one pass (47 languages).## Which backends produce punctuation natively?\n\n| Backend | Punctuation | Capitalization | Notes |\n|---|---|---|---|\n| whisper | ✔ | ✔ | Full punctuation and casing |\n| parakeet | ✔ | ✔ | |\n| canary | ✔ | ✔ | |\n| cohere | ✔ | ✔ | Toggleable via `--no-punctuation` |\n| granite | ✔ | ✔ | LLM output |\n| voxtral | ✔ | ✔ | LLM output |\n| voxtral4b | ✔ | ✔ | LLM output |\n| qwen3 | ✔ | ✔ | LLM output |\n| funasr | ✔ | ✔ | LLM output (Qwen3-0.6B decoder). Chinese chars carry full-width period; mlt-nano variant adds Latin-script casing + punctuation. |\n| sensevoice | ✔ | ✔ | CTC output with native ITN — toggle off via `--no-punctuation` , which controls Arabic-digit vs spelled-out numerals + comma/period emission. |\n| paraformer | no |\nno |\nNAR character-level output — add `--punc-model` |\n| gigaam | ✔ (`e2e_*` ) |\n✔ (`e2e_*` ) |\nThe `e2e_*` revisions carry punctuation + casing + inverse text normalization in the SentencePiece vocabulary. The charwise `ctc` / `rnnt` revisions emit lowercase Cyrillic with no punctuation — but auto-restoration is still suppressed for them, because the auto-enabled FireRedPunc is a Chinese/English model and injects full-width CJK punctuation into Russian. Use an `e2e_*` revision for punctuated output, or pass an explicit `--punc-model` . |\n| glm-asr | ✔ | ✔ | LLM output |\n| kyutai-stt | ✔ | ✔ | LLM output |\n| moonshine | ✔ | ✔ | Encoder-decoder output |\nfastconformer-ctc |\nno |\nno |\nCTC — add `--punc-model` |\nwav2vec2 |\nno |\nno |\nCTC — add `--punc-model` |\nfirered-asr |\nno |\nno |\nCTC — add `--punc-model` |\nomniasr (CTC) |\nno |\nno |\nCTC — add `--punc-model` |\nomniasr (LLM) |\n✔ | ✔ | Autoregressive decoder |\n\nOther freely-licensed alternatives that could be added: [felflare/bert-restore-punctuation](https://huggingface.co/felflare/bert-restore-punctuation) (MIT, English, includes truecasing), [xashru/punctuation-restoration](https://github.com/xashru/punctuation-restoration) (Apache-2.0, 40+ languages, BiLSTM-CRF).\n\n**Progressive subtitle output** (`--flush-after`\n\n): By default, non-whisper backends buffer all segments and print output at the end. For real-time subtitle consumption (PotPlayer, custom media players), use `--flush-after 1`\n\nto print each SRT entry to stdout immediately after its VAD segment is transcribed:\n\n```\ncrispasr --backend parakeet -m parakeet.gguf --vad --flush-after 1 -osrt -f long_audio.wav\n# SRT entries appear progressively as each segment finishes\n```\n\n**JSON output with language detection**: When using `-l auto -oj`\n\n, the JSON output includes detected language info:\n\n```\n{\n  \"crispasr\": {\n    \"backend\": \"cohere\",\n    \"language\": \"en\",\n    \"language_detected\": \"en\",\n    \"language_confidence\": 0.977,\n    \"language_source\": \"ecapa\"\n  },\n  \"transcription\": [...]\n}\n```\n\n| Need | Pick |\n|---|---|\n| Battle-tested, all features exposed | whisper |\n| Lowest English WER | cohere |\nFastest (16x realtime on CPU) |\nmoonshine (tiny), fc-ctc (10x) |\n| Multilingual + word timestamps + fast | parakeet (2.9x RT) |\nMultilingual with explicit language control |\ncanary |\nSpeech translation (X→en or en→X) |\ncanary, voxtral, qwen3 |\n30 languages + Chinese dialects |\nqwen3 |\n1600+ languages |\nomniasr (CTC or LLM) |\nRealtime streaming ASR (native incremental encoder, ~2× RT feed; sub-second-token target deferred to phase 2) |\nvoxtral4b |\n| Highest-quality offline speech-LLM | voxtral |\n| Apache-licensed speech-LLM | granite, voxtral, qwen3, omniasr-llm |\nLightweight CTC-only (fast, no decoder) |\nwav2vec2, fc-ctc, data2vec, omniasr |\nRussian |\ngigaam (`e2e_rnnt` — 8.4 % avg WER, punctuation + ITN), whisper, qwen3 |\nMandarin + Chinese dialects |\nfirered-asr, qwen3, glm-asr, funasr, paraformer, sensevoice |\nMultilingual (31 langs) speech-LLM |\nfun-asr-mlt-nano, qwen3, omniasr-llm, gemma4-e2b |\nMultilingual (50+ langs) + LID + audio-event in one pass |\nsensevoice (encoder-only CTC, non-AR, 15× faster than Whisper-Large) |\n\nAudio-LLM backends (`qwen3`\n\n, `voxtral`\n\n, `granite`\n\n, `glm-asr`\n\n, etc.) run full\ntransformer decoder stacks (28+ layers, 2048-dim) and are **dramatically slower\non CPU** than encoder-only backends. On older dual-core hardware they can drop\nbelow 0.01× realtime. If you're on CPU-only hardware:\n\n- Prefer\n**moonshine**(16× RT),** fc-ctc**(10× RT),** parakeet**(2.9× RT), or** whisper**for usable speeds. - Use\n`--flush-after 1`\n\nto see results as each VAD slice completes instead of waiting for the entire file. - Use\n`-pp`\n\n/`--print-progress`\n\nfor per-slice progress indicators on all backends (unified backends show slice-level progress; whisper shows encoder-level progress). - Quantize models to Q4_K or Q5_K to reduce memory and compute.\n\nCohere, canary, granite, voxtral and voxtral4b need an explicit\nlanguage code up front. If you don't know the language, pass\n`-l auto`\n\nand crispasr runs an optional LID pre-step before the main\ntranscribe() call:\n\n```\n# Downloads ggml-tiny.bin (75 MB, 99 languages) on first use\ncrispasr --backend cohere -m $TC/cohere-transcribe-q5_0.gguf \\\n         -f unknown.wav -l auto\n# crispasr[lid]: detected 'en' (p=0.977) via whisper-tiny\n# crispasr: LID -> language = 'en' (whisper, p=0.977)\n```\n\nThese LID providers are available:\n\n-\n`--lid-backend whisper`\n\n(default) — uses a small multilingual ggml-*.bin model via the crispasr C API. Auto-downloads ~75 MB on first use. 99 languages. -\n`--lid-backend silero`\n\n— native GGUF port of Silero's 95-language classifier. 16 MB F32. Runs as a ggml graph (multi-threaded SIMD on CPU, GPU offload on Metal/CUDA; on Vulkan the graph is routed to CPU pending an upstream kernel fix). Analyzes the first 30 s of audio (`CRISPASR_SILERO_LID_MAX_S`\n\noverrides);`CRISPASR_SILERO_LID_LEGACY=1`\n\nrestores the old scalar path. -\n`--lid-backend ecapa`\n\n—**recommended**: ECAPA-TDNN (Apache-2.0). Purpose-built for language ID. Very high accuracy on TTS benchmark. Two variants via`--lid-model`\n\n:— VoxLingua107, 43 MB F16, 107 languages, ISO codes (en, de, ...).`cstr/ecapa-lid-107-GGUF`\n\n**Default.**— CommonLanguage, 40 MB F16, 45 languages, full names (English, German, ...).`cstr/ecapa-lid-commonlanguage-GGUF`\n\n-\n`--lid-backend firered`\n\n— FireRedLID (Conformer encoder + Transformer decoder). Q4_K (544 MB), 120 languages including Chinese dialects. Slower but covers more languages. -\n`--lid-backend probe`\n\n— no second model at all: ask the**ASR model itself**. Transcribes a 20 s clip once per language the model declares and keeps the best-scoring candidate (length × text-LID agreement × distinct-token ratio², the last term catching the repetitive output a wrong-language prompt produces). Currently implemented by**cohere**. The reason to prefer it is correctness, not just the saved download: an external detector knows 99 languages while Cohere Transcribe accepts 14 — and its Arabic finetune only`en`\n\n/`ar`\n\n— so external LID regularly returns a language the model was never trained on, and Cohere answers a wrong language*fluently*rather than failing. The probe cannot. Cost is one encode + one short decode per candidate, so it runs automatically only for a model with ≤ 4 languages (`CRISPASR_COHERE_PROBE_MAX_LANGS`\n\n);`CRISPASR_COHERE_PROBE_TEXTLID=0`\n\ndrops the text-LID agreement term.**The ceiling is about cost, not accuracy.** Measured on the real models: the two-language Arabic finetune picks`ar`\n\nfor an Arabic clip (p=0.675) and`en`\n\nfor`samples/jfk.wav`\n\n(p=0.647); the 14-language base model, probed across all 14, also gets both right (`en`\n\np=0.169,`ar`\n\np=0.254) — it is simply slower than an external detector. The encoder output is language-independent, so the probe encodes**once** and decodes per candidate (encode is ~87 % of a pass); a 14-candidate probe measured**12 s → 4-5 s** against one-encode-per-candidate, byte-identical output.`CRISPASR_COHERE_PROBE_REUSE_ENC=0`\n\nrestores the naive path.The one soft spot worth knowing: asking the model for a language it was\n\n*not*trained on can yield a clean translation rather than garbage, which a text LID then confirms — \"fluent French out\" is not evidence of French in. That is what makes a mismatched whitelist dangerous, and it is measurable: force a 14-language list onto the two-language Arabic finetune and its`fr`\n\nprobe returns real French and wins. The real base model's`fr`\n\nprobe instead code-switches (\"Et so, my fellow Americans…\", agreement 0.00) and loses, as it should.\n\nThese VAD providers are available:\n\n**Silero VAD**(default) — ~885 KB, auto-downloaded via`--vad`\n\n. Industry-standard, well-tested.**FireRedVAD**— DFSMN-based, 2.4 MB, F1=97.57%. Pass`--vad -vm firered`\n\nto auto-download. Recommended.**MarbleNet**— NVIDIA 1D separable CNN, 439 KB, 6 languages (EN/DE/FR/ES/RU/ZH). Pass`--vad -vm marblenet`\n\nto auto-download. Smallest model. ()`cstr/marblenet-vad-GGUF`\n\n**Whisper-VAD-EncDec***(experimental)*— Whisper-base encoder + TransformerDecoder head, 22 MB Q4_K. Trained on Japanese ASMR; may not generalise well to all domains. Pass`--vad -vm whisper-vad`\n\n. Slower than others (~1s vs ~50ms). ()`cstr/whisper-vad-encdec-asmr-GGUF`\n\nPass `--lid-backend off`\n\nto skip LID entirely.\n\nAudio LID (above) tags **what was spoken**; text LID tags **what was\nwritten**. Text LID runs on a transcript or any UTF-8 string and is\nuseful for routing post-ASR pipelines (translation, punctuation, sub\nselection) without re-running an audio model. Three GGUF families,\none binary — the dispatcher picks by `general.architecture`\n\n:\n\n| Backend | Labels | Size (F16) | License | HF repo |\n|---|---|---|---|---|\nCLD3 (Google compact language detector v3) |\n109 ISO 639-1 | 440 KB |\nApache-2.0 |\n`cstr/cld3-GGUF` |\n\n**GlotLID-V3**(cis-lmu fastText)`cstr/glotlid-GGUF`\n\n**LID-176**(Facebook fastText)`cstr/fasttext-lid176-GGUF`\n\n¹ LID-176 is **CC-BY-NC-4.0** — non-commercial use only. CLD3 +\nGlotLID-V3 are Apache-2.0 with no such constraint. Pick CLD3 for the\nsmallest, fastest path; GlotLID for maximum coverage (low-resource\nlanguages); LID-176 only if you need its specific 176-label space and\naccept its non-commercial terms.\n\n**Standalone CLI** — auto-routes by GGUF arch, with auto-download:\n\n```\ncrispasr-lid -m auto --text \"Bonjour le monde\"        # → cstr/cld3-GGUF (default, ~440 KB)\ncrispasr-lid -m auto:glotlid --text \"Bonjour le monde\" -k 5\ncrispasr-lid -m auto:lid-fasttext176 --text \"Hallo Welt\"\n# Or pass an explicit path / canonical filename (looked up in the registry):\ncrispasr-lid -m cld3-f16.gguf --text \"你好世界\"\n# zh\t0.997816\necho \"Привет мир\" | crispasr-lid -m auto --quiet\n# ru\t0.907322\n```\n\n**Post-ASR pipeline** — `--lid-on-transcript`\n\nruns the same dispatcher\non the assembled transcript (also accepts `auto[:variant]`\n\n):\n\n```\ncrispasr -m ggml-tiny.bin -f speech.wav --lid-on-transcript auto\n# (transcript on stdout)\n# lang=de\tconf=0.997123\tbackend=lid-cld3\n```\n\nThe dispatcher (`src/text_lid_dispatch.{h,cpp}`\n\n) is a thin C ABI\nfaçade — one integer compare per call; per-stage diff harness is\ngreen at cos≥0.999 across 8 multilingual smoke samples.\n\n**Don't want to build?** Prebuilt binaries for Windows, macOS and Linux are on\nthe [releases page](https://github.com/CrispStrobe/CrispASR/releases/latest) —\nsee [Start here](#start-here) for which file to take. The rest of this section\nis for building from source.\n\n```\ngit clone --recursive https://github.com/CrispStrobe/CrispASR\ncd CrispASR\n# already cloned without --recursive? initialize the bundled ggml submodule:\n#   git submodule update --init --recursive\ncmake -B build -DCMAKE_BUILD_TYPE=Release\ncmake --build build -j$(nproc)\n```\n\nThe `ggml/`\n\nsubmodule is required. If you cloned without `--recursive`\n\n, run\n`git submodule update --init --recursive`\n\nfirst — otherwise CMake stops with a\nmessage telling you to do exactly that.\n\nProduces `build/bin/crispasr`\n\n(main CLI), `build/bin/crispasr-quantize`\n\n,\nand `build/bin/crispasr-diff`\n\n. No Python, PyTorch, or pip required at\nruntime — just a C++17 compiler and CMake 3.14+.\n\nFor GPU acceleration, add the matching ggml flag at configure time:\n\n```\ncmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_CUDA=ON     # NVIDIA\ncmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_METAL=ON    # Apple Silicon\ncmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_VULKAN=ON   # cross-vendor\n```\n\n**See ** for the full guide:\nall GPU backends (CUDA / Metal / Vulkan / MUSA / SYCL), Windows\nconvenience scripts, ffmpeg ingestion, optional BLAS, glibc notes,\nand the\n\n`docs/install.md`\n\n`scripts/dev-build.sh`\n\nwrapper.If a build runs but the binary exits with no output, see\n[ docs/troubleshooting.md](/CrispStrobe/CrispASR/blob/main/docs/troubleshooting.md).\n\nDeeper ASR examples below. If this is your first run, use\n[Start here](#start-here) instead. For TTS, the runnable guide is\n[docs/tts.md](/CrispStrobe/CrispASR/blob/main/docs/tts.md) ([Text-to-Speech](#text-to-speech-models) below is\nthe model catalogue).\n\n```\n# Download a whisper model (same as upstream whisper.cpp)\n./models/download-ggml-model.sh base.en\n\n./build/bin/crispasr -m models/ggml-base.en.bin -f samples/jfk.wav\n# [00:00:00.000 --> 00:00:07.940]   And so my fellow Americans ask not what your country can do for you\n# [00:00:07.940 --> 00:00:10.760]   ask what you can do for your country.\n# Grab the quantized model (~467 MB)\ncurl -L -o parakeet.gguf \\\n    https://huggingface.co/cstr/parakeet-tdt-0.6b-v3-GGUF/resolve/main/parakeet-tdt-0.6b-v3-q4_k.gguf\n\n./build/bin/crispasr -m parakeet.gguf -f samples/jfk.wav\n# Auto-detected backend 'parakeet' from GGUF metadata.\n# And so, my fellow Americans, ask not what your country can do for you, ask what you can do for your country.\n\n# Word-level timestamps (one line per word)\n./build/bin/crispasr -m parakeet.gguf -f samples/jfk.wav -ml 1\n# Transcription (source == target)\n./build/bin/crispasr --backend canary -m canary-1b-v2-q5_0.gguf -f audio.de.wav -sl de -tl de\n\n# Translation (German speech → English text)\n./build/bin/crispasr --backend canary -m canary-1b-v2-q5_0.gguf -f audio.de.wav -sl de -tl en\n\n# ...or use the familiar crispasr flag:\n./build/bin/crispasr --backend canary -m canary-1b-v2-q5_0.gguf -f audio.de.wav -l de --translate\n# First run downloads ~2.5 GB to ~/.cache/crispasr/ via curl, then runs\n./build/bin/crispasr --backend voxtral -m auto -f samples/jfk.wav\n\n# Subsequent runs use the cached file\n./build/bin/crispasr --backend voxtral -m auto -f samples/jfk.wav -l en\n# 0.6B (default, ~500 MB)\n./build/bin/crispasr --backend qwen3 -m auto -f audio.zh.wav\n\n# 1.7B (higher quality, ~1.3 GB) — supports both -hf and non-hf source models\n./build/bin/crispasr --backend qwen3 -m qwen3-1.7b --auto-download -f audio.wav\n\n# Japanese anime/galgame fine-tune (~1.3 GB)\n./build/bin/crispasr --backend qwen3 -m qwen3-ja-anime --auto-download -f anime.wav\n```\n\n**Long audio:** the default is safe 30 s chunking. `--chunk-seconds 0`\n\ndecodes\nthe whole file in ONE pass (matches the reference model verbatim on multi-minute\nclips, #218) — but the encoder's full attention is O(N²) in audio length, so\nkeep single-pass clips under ~10 minutes on 16 GB machines. For long-form use\nprefer the plain `-q4_k`\n\n/`-q8_0`\n\nGGUFs over the `-imatrix`\n\nvariants (see the\nmodel card).\n\n```\n./build/bin/crispasr --backend glm-asr -m auto -f audio.wav\n\n# Long audio in one pass (up to 655 s — 30 s encoder windows, one LLM prompt,\n# same layout as the HF/zai reference; matches it verbatim on the #218 clip):\n./build/bin/crispasr --backend glm-asr -m auto --chunk-seconds 0 -f long.wav\n```\n\nNote: in single-pass mode the model (like the reference) skips leading\nnon-speech audio; the default 30 s-chunked mode transcribes more of such\nclips. Custom `--ask`\n\n/ non-English `--language`\n\ninstructions need a GGUF\nwith baked BPE merges (re-published 2026-07; older GGUFs fall back to the\ndefault transcription prompt with a warning).\n\n```\n# Download the LM + audio tokenizer (the tokenizer is a separate model)\nhuggingface-cli download cstr/mimo-asr-GGUF mimo-asr-q4_k.gguf \\\n    --local-dir ~/.cache/crispasr\nhuggingface-cli download cstr/mimo-tokenizer-GGUF mimo-tokenizer-q4_k.gguf \\\n    --local-dir ~/.cache/crispasr\n\n# Transcribe (auto-discovers tokenizer if it sits next to the LM)\n./build/bin/crispasr \\\n    --backend mimo-asr \\\n    -m ~/.cache/crispasr/mimo-asr-q4_k.gguf \\\n    --codec-model ~/.cache/crispasr/mimo-tokenizer-q4_k.gguf \\\n    -f samples/jfk.wav\n# Output: And so, my fellow Americans, ask not what your country can do\n# for you. Ask what you can do for your country.\n```\n\nThe 4.5 GB Q4_K is the recommended quant; F16 (14.9 GB) needs ~16 GB\nRAM during inference. JFK matches the upstream Python\n`MimoAudio.asr_sft`\n\nreference verbatim; performance on M1+Metal is\n~0.3× realtime (Q4_K dequant per step is the bottleneck — F16 +\nKV-reuse follow-ups are queued under PLAN #51a/b/c).\n\n```\n# English (Q4_K quantized, 212 MB — 6x smaller than F16)\ncurl -L -o wav2vec2-en-q4k.gguf \\\n    https://huggingface.co/cstr/wav2vec2-large-xlsr-53-english-GGUF/resolve/main/wav2vec2-xlsr-en-q4_k.gguf\n\n./build/bin/crispasr -m wav2vec2-en-q4k.gguf -f samples/jfk.wav\n# and so my fellow americans ask not what your country can do for you ask what you can do for your country\n\n# German\ncurl -L -o wav2vec2-de-q4k.gguf \\\n    https://huggingface.co/cstr/wav2vec2-large-xlsr-53-german-GGUF/resolve/main/wav2vec2-xlsr-de-q4_k.gguf\n\n./build/bin/crispasr -m wav2vec2-de-q4k.gguf -f audio.de.wav\n\n# Convert any HuggingFace Wav2Vec2ForCTC model:\npython models/convert-wav2vec2-to-gguf.py \\\n    --model-dir jonatasgrosman/wav2vec2-large-xlsr-53-german \\\n    --output wav2vec2-de.gguf --dtype f32\n# Then optionally quantize:\n./build/bin/crispasr-quantize wav2vec2-de.gguf wav2vec2-de-q4k.gguf q4_k\n```\n\nCrispASR has three feature areas that warrant their own docs pages:\n\n—[Streaming & live transcription](/CrispStrobe/CrispASR/blob/main/docs/streaming.md)`--stream`\n\n,`--mic`\n\n,`--live`\n\n, sliding-window chunking, per-token confidence.— Kokoro (multilingual, smallest), Qwen3-TTS (highest fidelity, voice cloning), VibeVoice (lowest-latency streaming), Orpheus (3 B Llama + SNAC), Chatterbox (flow-matching + HiFT vocoder, German via Kartoffelbox), IndexTTS, VoxCPM2, and CosyVoice3 (9 langs + 18 zh dialects; baked-voice bank + arbitrary-WAV cloning). Voice packs, language routing, and qwen3-tts environment switches. All TTS output is watermarked; post-embed verification warns if confidence is low. Use[Text-to-Speech (TTS)](/CrispStrobe/CrispASR/blob/main/docs/tts.md)`--detect-watermark file.wav`\n\nto check any WAV for AI watermarks.— persistent model, OpenAI-compatible[Server mode (HTTP API)](/CrispStrobe/CrispASR/blob/main/docs/server.md)`/v1/audio/transcriptions`\n\n(ASR) and`/v1/audio/speech`\n\n+`/v1/voices`\n\n(TTS, automatic on any loaded CAP_TTS backend), per-request voice + speed + instructions, CORS, long-form sentence chunking, API keys, Docker Compose, prebuilt CUDA images.— one transcription already uses multiple cores; the server accepts requests concurrently but serializes inference on one model by default;[Concurrency, parallelism & scaling](/CrispStrobe/CrispASR/blob/main/docs/concurrency.md)`--server-workers N`\n\nruns N model instances so pure-ASR requests run concurrently; and for bulk/throughput workloads, process-level fan-out (`xargs -P`\n\n/ GNU`parallel`\n\n) or N replicas behind a load balancer. Also covers what is*not*supported (batched multi-stream inference, PagedAttention) and why.\n\nQuickest taste of each:\n\n```\n# Streaming from microphone\ncrispasr --mic -m model.gguf\n\n# TTS via auto-downloaded VibeVoice (~636 MB on first run)\ncrispasr --backend vibevoice-tts -m auto --tts \"Hello world\" --tts-output hello.wav\n\n# CosyVoice3 on GPU; companions auto-download beside the LLM\ncrispasr --backend cosyvoice3-tts -m auto --tts \"Hello world\" --tts-output cosy.wav\n\n# CosyVoice3 fast mode: 5 flow steps instead of the quality-default 10\nCOSYVOICE3_FLOW_STEPS=5 crispasr --backend cosyvoice3-tts -m auto \\\n  --tts \"Hello world\" --tts-output cosy-fast.wav\n\n# Persistent HTTP server, OpenAI-compatible\ncrispasr --server -m model.gguf --port 8080\ncurl -F \"file=@audio.wav\" http://localhost:8080/v1/audio/transcriptions\n\n# TTS over HTTP — load a TTS backend, hit /v1/audio/speech\ncrispasr --server --backend qwen3-tts-customvoice -m auto --voice-dir ./voices --port 8080\ncurl http://localhost:8080/v1/audio/speech \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"input\":\"Hello world\",\"voice\":\"vivian\"}' -o out.wav\n```\n\nCosyVoice3 uses batched classifier-free guidance and request-sized KV\ncaching by default. Baked voices load only the LLM, flow, HiFT, and voice\nbank; the larger S3 tokenizer and CAMPPlus companions load lazily when a\n`.wav`\n\ncloning voice is first requested.\n\nCommon flags:\n\n```\ncrispasr -m auto --backend parakeet -f audio.wav --vad -osrt --split-on-punct\n```\n\n| Flag | Meaning |\n|---|---|\n`-m FNAME` / `--backend NAME` |\nModel path (or `auto` ) and forced backend |\n`-f FNAME` |\nInput audio (repeatable; positional accepted) |\n`--vad` |\nSilero VAD chunking — strongly recommended for multi-minute audio |\n`-osrt` / `-ovtt` / `-otxt` / `-oj` / `-ojf` |\nOutput formats (also `-ocsv` , `-olrc` ) |\n`-am FNAME` |\nCTC aligner GGUF for word-level timestamps on LLM backends |\n`--align-only` |\nStandalone forced alignment: text/`.srt` + audio → timestamped SRT/JSON (no ASR needed); `.srt` input keeps its cues and gets re-timed (`--align-granularity auto|word|segment` ) |\n`-tp F` / `-bs N` |\nSampling temperature / beam search width |\n`-n N` / `--frequency-penalty F` |\nGenerated-token cap / opt-in repeated-token penalty for supported autoregressive ASR backends |\n`-l auto` / `--detect-language` |\nLID pre-step for backends without native lang detect |\n`--hotwords \"A,B,C\"` |\nContextual biasing — boost named terms during CTC/TDT decode or LLM prompt |\n`-ck N` |\nFallback chunk size when VAD is off (default 30 s) |\n`--list-backends` |\nPrint the capability matrix and exit |\n\n**See ** for the full reference: every\nflag, VAD details, CTC alignment workflow, output JSON layout, the\nauto-download registry, and supported audio formats.\n\n`docs/cli.md`\n\n**See** for Python / Rust / Dart / Go / Java / JavaScript / Ruby / mobile.\n\n`docs/bindings.md`\n\nCrispASR is structured as a stable C-ABI in `src/`\n\n(every algorithm:\nVAD, diarize, LID, alignment, cache, registry) consumed by all\nlanguage wrappers, with thin presentation layers in `examples/cli/`\n\n.\nPer-model runtimes live in `src/{whisper,parakeet,canary,...}.cpp`\n\n,\nsharing primitives from `src/core/`\n\n(mel, ffn, attention, GGUF\nloader, FastConformer / Conformer / Granite-LLM blocks, etc.).\n\n— full layered layout, file-by-file tour of`docs/architecture.md`\n\n`src/`\n\nand`examples/cli/`\n\n, per-backend internals table, regression discipline.— adding a new backend in five files, clang-format-18 setup, the`docs/contributing.md`\n\n`crispasr-diff`\n\nPyTorch-ground-truth workflow, and the TTS audio-cosine-vs-reference regression target.—`docs/regression-matrix.md`\n\n`tools/test-all-backends.py`\n\ncapability tiers, cache modes (`keep`\n\n/`ephemeral`\n\n),`--skip-missing`\n\nfor CI.\n\n**Shared libraries** (cross-repo with CrispEmbed):\n\n`crisp_audio/`\n\n— Whisper-shape audio encoder (Conv-stem + Transformer)`crisp_punc/`\n\n— punctuation restoration (FireRedPunc + PCS)`crisp_lid/`\n\n— text-based language identification (fastText + CLD3)`crisp_truecase/`\n\n— truecasing (statistical + CRF + BiLSTM)\n\nBoth are self-contained static libraries with CMakeLists.txt. CrispEmbed\nlinks them via `add_subdirectory(../CrispASR/crisp_*/)`\n\n; CrispASR uses\nthem directly. If the shared dir is absent, both repos fall back to local\ncopies of the source files.\n\nFor benchmarks see [ PERFORMANCE.md](/CrispStrobe/CrispASR/blob/main/PERFORMANCE.md); for the\nsession-by-session port log and the bug-class lessons, see\n\n[.](/CrispStrobe/CrispASR/blob/main/LEARNINGS.md)\n\n`LEARNINGS.md`\n\n`build/bin/crispasr-quantize`\n\nis a single, model-agnostic GGUF\nre-quantization tool that works across all supported model families\n(Whisper, Parakeet, Canary, Cohere, Voxtral, Qwen3, Granite, Wav2Vec2,\nMiMo-ASR, GLM-ASR, Moonshine, VibeVoice, Kokoro, Qwen3-TTS, …):\n\n```\n./build/bin/crispasr-quantize input.gguf output.gguf q4_k\n```\n\n**See ** for the full guide:\nsupported quant types, K-quant alignment fallback, recommended quant\nper backend, and worked examples for each architecture.\n\n`docs/quantize.md`\n\nAll backends use `ggml_backend_init_best()`\n\nwhich automatically picks the highest-priority compiled backend: CUDA > Metal > Vulkan > CPU. To force a specific backend:\n\n```\n# Force Vulkan even when CUDA is available\ncrispasr --gpu-backend vulkan -m model.gguf -f audio.wav\n\n# Pin a specific GPU (useful on Vulkan systems with iGPU + dGPU)\ncrispasr --gpu-backend vulkan -dev 1 -m model.gguf -f audio.wav\n\n# Force CPU (useful for benchmarking)\ncrispasr -ng -m model.gguf -f audio.wav\n\n# CUDA unified memory (swap to RAM when VRAM exhausted)\nGGML_CUDA_ENABLE_UNIFIED_MEMORY=1 crispasr -m model.gguf -f audio.wav\n```\n\nBuild flags: `-DGGML_CUDA=ON`\n\n, `-DGGML_METAL=ON`\n\n, `-DGGML_VULKAN=ON`\n\n.\n\nNotes:\n\n`--gpu-backend vulkan`\n\nselects the Vulkan backend, but it does not choose which physical GPU to use. Use`-dev N`\n\nto select the Vulkan device index.- On some Windows laptops, Vulkan device\n`0`\n\nis the Intel iGPU and the NVIDIA GPU is`1`\n\n. If Vulkan looks unexpectedly slow, rerun with`-dev 1`\n\n. - The Windows convenience script\n`build-vulkan.bat`\n\ncreates a separate Vulkan-capable binary at`build-vulkan\\bin\\crispasr.exe`\n\n.\n\nFor most backends, `-v`\n\n/ `--verbose`\n\nsurfaces per-stage timings and\ndevice picks. For headless / library use (where the CLI flag isn't\nplumbed through), set `CRISPASR_VERBOSE=1`\n\ninstead.\n\n```\n# Per-stage timing breakdown (mel / encoder / prefill / decode):\ncrispasr -v --backend gemma4-e2b -m model.gguf -f audio.wav\n# gemma4_e2b: mel 128x1099 (17.2 ms)\n# gemma4_e2b: encoder done: 1536x275 (719.0 ms)\n# gemma4_e2b: prefill done, first_token=3133 (1464.0 ms)\n# gemma4_e2b: decoded 25 tokens (7748.3 ms total)\n# crispasr: transcribed 11.0s audio in 7.75s (1.4x realtime)\n\n# Hugging Face access for gated models (Voxtral, Gemma4-E2B, …):\nHF_TOKEN=hf_xxx crispasr -m auto --backend gemma4-e2b -f audio.wav\n```\n\nThe server has its own auth env: `CRISPASR_API_KEYS`\n\n(see\n[Server mode](/CrispStrobe/CrispASR/blob/main/docs/server.md)).\n\n**Per-backend debug / bench / dump-dir env vars (developer)**\n\nThese are useful when porting a new backend or chasing a regression.\nThe `*_BENCH=1`\n\ntoggles emit per-stage timings even without `-v`\n\n; the\n`*_DEBUG=1`\n\ntoggles emit per-step diagnostic prints; the `*_DUMP_DIR=`\n\npaths write per-stage F32 tensors for diff-testing against a PyTorch\nreference (see [Debug a new backend against PyTorch ground truth](/CrispStrobe/CrispASR/blob/main/docs/contributing.md#debug-a-new-backend-against-pytorch-ground-truth)).\n\n| Env var | Purpose |\n|---|---|\n`CRISPASR_VERBOSE=1` |\nForces verbose mode for any backend (parallel to the `-v` flag). |\n`CRISPASR_DUMP_DIR=path/` |\nGeneric per-stage F32 tensor dump for the `crispasr-diff` harness. |\n`GEMMA4_E2B_BENCH=1` |\nPer-stage timings for the Gemma-4-E2B backend. |\n`COHERE_BENCH=1` / `COHERE_DEBUG=1` |\nCohere transcribe per-stage timings / per-step diagnostics. |\n`COHERE_PROF=1` |\nCohere graph-level profiling (per-op timings). |\n`COHERE_THREADS=N` |\nOverride thread count for the Cohere backend. |\n`COHERE_DEVICE=cpu|cuda|metal|vulkan` |\nForce the Cohere backend onto a specific device. |\n`COHERE_DUMP_ATTN=path/` |\nDump attention activations for Cohere (used by the diff harness). |\n`FIRERED_BENCH=1` |\nPer-stage timings for the FireRedASR backend. |\n`FIREREDPUNC_DEBUG=1` |\nPer-step diagnostics for the FireRed punctuation post-step. |\n`MOONSHINE_STREAMING_BENCH=1` |\nPer-stage timings for moonshine-streaming. |\n`OMNIASR_BENCH=1` / `OMNIASR_DEBUG=1` / `OMNIASR_DUMP_DIR=` |\nOmniASR per-stage timings, diagnostics, and stage dumps. |\n`PARAKEET_DEBUG=1` |\nParakeet TDT per-step diagnostics (joint network, blank-id sanity). |\n`QWEN3_TTS_BENCH=1` / `QWEN3_TTS_DEBUG=1` / `QWEN3_TTS_DUMP_DIR=` |\nQwen3-TTS per-stage timings, diagnostics, and stage dumps. |\n`VIBEVOICE_BENCH=1` / `VIBEVOICE_DEBUG=1` / `VIBEVOICE_DUMP_DIR=` |\nVibeVoice ASR per-stage timings, diagnostics, and stage dumps. |\n`VIBEVOICE_REF_FEATURES=path` |\nReplace the live encoder with a saved feature tensor (regression harness). |\n`VIBEVOICE_TTS_DUMP=path/` |\nVibeVoice TTS per-stage dumps (token IDs, base/TTS hidden, neg condition, frame-0 noise/v_cfg/latent/acoustic_embed) for the diff harness. |\n`VIBEVOICE_TTS_DUMP_PERFRAME=1` |\nPer-frame VibeVoice TTS dumps written as `perframe_<stage>_f<NNN>.bin` . Pair with `VIBEVOICE_TTS_DUMP=path/` and `VIBEVOICE_TTS_NOISE=path` for stage-by-stage AR diff against `tools/run_official_vibevoice.py` . |\n`VIBEVOICE_TTS_TRACE=1` |\nExtra one-line traces (negative-condition prefill rms, scaling/bias factors loaded). Same effect as library verbosity ≥ 2; there is no CLI flag for it (`-v` caps verbosity at 1). |\n`VIBEVOICE_VOICE_AUDIO=path.wav` |\nReference voice WAV for 1.5B-base TTS without a `.gguf` voice cache. |\n`VIBEVOICE_TTS_NOISE=path` |\nOverride the per-frame Gaussian init noise. Flat little-endian float32 `[N_frames, vae_dim]` — typically the `noise.bin` written by `tools/run_official_vibevoice.py` . |\n`VIBEVOICE_VAE_BACKEND=cpu|metal|cuda|vulkan` |\nPin the VAE decoder onto a specific backend. |\n`WAV2VEC2_BENCH=1` / `WAV2VEC2_VERBOSE=1` / `WAV2VEC2_DUMP_DIR=` |\nwav2vec2 per-stage timings, verbose graph traces, and stage dumps. |\n`CRISPASR_VOXTRAL4B_STREAM_TIMING=1` |\nPer-stage timings for the voxtral4b streaming path (encoder drain / prefill / first-text-token / decode-step p50/p95). |\n`CRISPASR_VOXTRAL4B_STREAM_CHUNK_MS=N` |\nOverride the internal encoder chunk size (default 240 ms). Must be a multiple of 80 ms. Larger = faster feed (kernel-launch amortisation), longer live-caption latency floor. |\n`CRISPASR_VOXTRAL4B_STREAM_BATCH_ENCODER=1` |\nRegression-debug: ignore the streaming encoder's audio_embeds and re-run the whole batch encoder at flush. |\n`CRISPASR_VOXTRAL4B_STREAM_DEBUG=1` / `CRISPASR_VOXTRAL4B_STREAM_DIFF=1` |\nPer-step decode prints / side-by-side encoder cosine vs the batch encoder. |\n`CRISPASR_VOXTRAL4B_STREAM_LIVE=1` |\nLive-captions decode-during-feed (PLAN #7 phase 3). `get_text()` polled during feed returns progressive transcript. Default OFF (PTT semantics). Wrappers: Python `Session.stream_open(live=True)` , Rust `stream_open_ex(.., live: true)` . |\n`CRISPASR_VOXTRAL4B_STREAM_DECODER_THREAD=1` |\nDecoder worker thread (PLAN #7 phase 4, implies live mode). Lets `feed()` return between encoder chunks without waiting for the decode loop — useful for mic-driven workloads. On M1 the Metal queue serializes encoder and decoder so total wall-clock is unchanged; faster GPUs with kernel-level parallelism see real overlap. |\n`CRISPASR_VOXTRAL4B_FUSED_QKV=0` |\nOpt out of the runtime fused-QKV LLM path (default-on, ~7-8 % decode speedup on M1 Q4_K, ~500 MB extra memory). |\n`CRISPASR_QWEN3_ASR_FUSED_QKV=0` |\nOpt out of the runtime fused-QKV LLM path for qwen3-asr (default-on; works on F16/F32/Q4_K/Q8_0/...). |\n`CRISPASR_VOXTRAL_FUSED_QKV=1` |\nOpt in to the runtime fused-QKV LLM path for voxtral 3B. Off by default (no measurable speedup on JFK-shape decodes; useful for long-form workloads where decode dominates). |\n`QWEN3_TTS_FUSED_QKV=1` |\nOpt in to the runtime fused-QKV talker path. |\n`GRANITE_DISABLE_ENCODER_GRAPH=1` |\nForce the granite-speech / -plus / -nar encoder back to the per-layer CPU loop (slower but kept around for debugging). The single ggml-graph encoder with per-layer Shaw RPE is the default and is bit-near-identical to the CPU loop while being ~2× faster end-to-end across all three variants. |\n`CRISPASR_NO_REL_POS=1` |\nAblate the relative-position bias in the Gemma-4 audio encoder (development only). |\n`ECAPA_REF_FBANK=path` |\nReference filterbank tensor for the ECAPA-TDNN LID model (regression harness). |\n`CRISPASR_SHERPA_LID_BIN=path` |\nOverride the auto-detected sherpa-onnx LID binary. |\n`CRISPASR_ARG_DEVICE=N` |\nDefault GPU device index when `-dev` isn't passed. |\n`GGML_CUDA_ENABLE_UNIFIED_MEMORY=1` |\nLet CUDA swap to RAM when VRAM is exhausted. |\n`GGML_VK_VISIBLE_DEVICES` / `CUDA_VISIBLE_DEVICES` |\nStandard ggml/CUDA device-visibility filters. |\n\n`HF_TOKEN`\n\nand `HUGGING_FACE_HUB_TOKEN`\n\nare both honoured for gated-model\ndownloads (in that order).\n\n— the original ggml inference engine and Whisper runtime this fork is built on[whisper.cpp](https://github.com/ggml-org/whisper.cpp)— the tensor library everything runs on[ggml](https://github.com/ggml-org/ggml)**NVIDIA NeMo**— parakeet-tdt-{0.6b-v2,0.6b-v3,1.1b}, parakeet-tdt_ctc-{110m,1.1b,0.6b-ja}, parakeet-ctc-{0.6b,1.1b}, canary-1b-v2, canary-ctc aligner, and the FastConformer-CTC family (stt_en_fastconformer_ctc_{large,xlarge,xxlarge} plus CTC branches of the stt_*_fastconformer_hybrid_large[_pc] fleet: en-pc, de, es, fr, it, nl, pl, ru, ua, hr, be, ar, fa, ka, hy, uz, kk-ru — all usable both as ASR backends and as compact ~82 MB`-am`\n\nforced aligners)**Cohere**— cohere-transcribe-03-2026** Qwen team (Alibaba)**— Qwen3-ASR-0.6B, Qwen3-ASR-1.7B, Qwen3-ForcedAligner-0.6B** Mistral AI**— Voxtral Mini 3B and 4B Realtime** IBM Granite team**— Granite Speech 3.2-8b, 3.3-2b, 3.3-8b, 4.0-1b** Meta / wav2vec2**— wav2vec2 CTC models (XLSR-53 English, German, multilingual via any Wav2Vec2ForCTC checkpoint)— optional diarization via subprocess (ONNX models)[sherpa-onnx](https://github.com/k2-fsa/sherpa-onnx)— VAD (native GGUF) and language identification (native GGUF, 95 languages)[Silero](https://github.com/snakers4/silero-vad)— speaker diarization segmentation (native GGUF port)[pyannote](https://github.com/pyannote/pyannote-audio)+[miniaudio](https://miniaud.io/)+[stb_vorbis](https://github.com/nothings/stb)— embedded/linked audio decoders (WAV/MP3/FLAC/AIFF/OGG/Opus, no ffmpeg; AAC/M4A/ALAC via Apple AudioToolbox)[libopus/opusfile](https://opus-codec.org/)(MIT) — in-tree clean-room codec suite: MP3/AAC-LC/Ogg-Opus output encoders (TTS[glint](https://github.com/CrispStrobe/glint)`.mp3`\n\n/`.aac`\n\n/`.opus`\n\n) and cross-platform ADTS AAC-LC + Ogg Opus input decoders (no libopus needed)(Anthropic) — significant portions of the crispasr integration layer, all model converters, and the FastConformer/attention/mel/FFN/BPE core helpers were co-authored with Claude[Claude Code](https://claude.ai/claude-code)\n\nSame as upstream whisper.cpp: **MIT**.\n\nPer-model weights are covered by their respective HuggingFace model licenses (see [Supported backends](#supported-backends)). The `crispasr`\n\nbinary itself links model runtimes that are mostly permissively licensed (MIT / Apache-2.0 / CC-BY-4.0 for weights).", "url": "https://wpnews.pro/news/crispasr-one-c-binary-for-multilingual-asr-and-tts-models", "canonical_source": "https://github.com/CrispStrobe/CrispASR", "published_at": "2026-08-31 22:22:23+00:00", "updated_at": "2026-08-31 22:52:04.298540+00:00", "lang": "en", "topics": ["artificial-intelligence", "machine-learning", "natural-language-processing", "developer-tools"], "entities": ["CrispASR", "whisper.cpp", "HuggingFace", "NVIDIA", "Mistral"], "alternates": {"html": "https://wpnews.pro/news/crispasr-one-c-binary-for-multilingual-asr-and-tts-models", "markdown": "https://wpnews.pro/news/crispasr-one-c-binary-for-multilingual-asr-and-tts-models.md", "text": "https://wpnews.pro/news/crispasr-one-c-binary-for-multilingual-asr-and-tts-models.txt", "jsonld": "https://wpnews.pro/news/crispasr-one-c-binary-for-multilingual-asr-and-tts-models.jsonld"}}