
Agent-first Rust ASR stack with a real in-process pure-Rust Whisper engine (no FFI, no Python, no subprocess — and on CPU it beats whisper.cpp 2.33× on tiny.en, at parity on large-v3-turbo), adaptive Bayesian backend routing, real-time NDJSON streaming, DTW word timestamps, and SQLite-backed run history.
curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/franken_whisper/main/install.sh?$(date +%s)" | bash
SHA-256-verified prebuilt binaries for Linux (x86_64 / aarch64), macOS (Intel / Apple Silicon), and WSL — proxy-aware, airgap-capable (--offline), reversible (--uninstall). Windows users: grab windows_amd64.zip from the latest release. All flags: Installation.
v0.2.0 — the native engine is real, and it is fast. The in-process pure-Rust Whisper engine (built on FrankenTorch kernels,
#![forbid(unsafe_code)]in-crate) now transcribes 2.33× faster than whisper.cpp on tiny.en and at parity on large-v3-turbo — CPU vs CPU, same machine (Apple M4 Pro, interleaved runs), while using about 18% less user CPU on the large model (53.8 s vs 65.4 s). Native-vs-whisper.cpp conformance on the reference fixture: WER 0.0000.
Model franken_whisper native (CPU) whisper.cpp (CPU) tiny.en (11 s clip) 475 ms 1,105 ms 2.33× faster large-v3-turbo (11 s clip) 9.73 s 9.59 s parity
Speech-to-text pipelines are fragmented. To get production-quality transcription you need whisper.cpp for speed, insanely-fast-whisper for GPU batching, and whisper-diarization for speaker identification. Each has its own CLI, output format, error handling, and deployment story. Orchestrating them from scripts means parsing inconsistent stdout, handling timeouts manually, killing zombie subprocesses, and losing all run history when something crashes.
Agent workflows make the problem worse. Modern LLM agents need structured, streaming, machine-readable output, not human-oriented terminal decorations that break the moment they touch jq, pipes, or SSH.
franken_whisper is a single Rust binary that wraps every major Whisper backend behind a unified, agent-first interface — and ships its own engine:
auto request runs a formal decision contract with an explicit loss matrix, per-backend Beta posteriors, Brier-scored calibration, and deterministic fallback when the model is mis-calibrated.v1.0.0. No fragile regex; agents parse JSON.symphonia. ffmpeg is a fallback for video and exotic codecs, and is auto-provisioned on Linux x86_64 if missing.whisper.cpp's word-timestamp pipeline, with the cancellation token threaded into the inner extraction loop.| Feature | whisper.cpp | insanely-fast-whisper | whisper-diarization | franken_whisper |
|---|---|---|---|---|
| Streaming output | partial | — | — | sequenced NDJSON stage events |
| Machine-readable errors | exit code only | exceptions | exceptions | 12 structured FW-* error codes |
| Adaptive backend selection | — | — | — | Bayesian decision contract |
| Run persistence | — | — | — | SQLite + JSONL replay packs |
| Diarization | — | yes (HF token) | yes | yes (any backend) |
| GPU acceleration | CUDA / Metal | CUDA / MPS | CUDA | frankentorch / frankenjax |
| Cancellation | SIGKILL |
KeyboardInterrupt |
SIGKILL |
cooperative CancellationToken |
| TTY audio relay | — | — | — | mulaw + zlib + base64 NDJSON |
| Native audio decode | WAV only | needs ffmpeg | needs ffmpeg | MP3 / AAC / FLAC / WAV / OGG / ALAC |
| Memory safety | C++ | Python | Python | #![forbid(unsafe_code)] |
# Transcribe an audio file. MP3 / FLAC / OGG / AAC decoded natively, no ffmpeg needed.
franken_whisper transcribe --input meeting.mp3 --json
# Transcribe a video file. Audio extracted automatically via ffmpeg fallback.
franken_whisper transcribe --input presentation.mp4 --json
# Stream real-time pipeline events for agents
franken_whisper robot run --input meeting.mp3 --backend auto
# Speculative streaming: fast partial transcripts with quality-model corrections
franken_whisper robot run --input meeting.mp3 --speculative \
--fast-model tiny.en --quality-model large-v3
# Speaker diarization with pyannote
franken_whisper transcribe --input meeting.mp3 --diarize --hf-token "$HF_TOKEN" --json
# TinyDiarize: whisper.cpp's built-in speaker-turn detection (no HF token needed)
franken_whisper transcribe --input meeting.mp3 --tiny-diarize --json
# Discover available backends and their capabilities
franken_whisper robot backends
# System health check (backends, ffmpeg, database, resources)
franken_whisper robot health
# Query run history
franken_whisper runs --limit 10 --format json
# Export run history to a portable JSONL snapshot (full or incremental)
franken_whisper sync export-jsonl --output ./snapshot
# Compressed audio over a text-only channel (PTY, SSH, serial)
franken_whisper tty-audio encode --input audio.wav > frames.ndjson
cat frames.ndjson | franken_whisper tty-audio decode --output restored.wav
The primary interface is robot. Every command in robot mode emits sequenced, timestamped NDJSON on stdout with schema version 1.0.0. Human-friendly output (transcribe without --json) is the exception. Robot mode never mixes decorative stderr into the data stream; structured run_error envelopes replace human prose even for argument-parsing failures.
Given identical inputs and parameters, franken_whisper produces identical outputs. The TTY retransmit loop, replay envelopes, replay packs, and conformance harness all enforce determinism. Random elements (UUIDs, wall-clock timestamps) are quarantined to metadata fields; they never enter computational output.
Every error has a structured code (FW-IO, FW-CMD-TIMEOUT, FW-BACKEND-UNAVAILABLE, FW-STAGE-TIMEOUT, …) and propagates through the NDJSON event stream. Cancellation tokens let in-flight work checkpoint and clean up instead of dying mid-write. In-progress SQLite transactions roll back via savepoints; subprocesses get SIGKILL; temp directories are removed by registered finalizers under a bounded budget.
The pipeline is composed dynamically per request. The 10 canonical stages (Ingest, Normalize, VAD, Source Separate, Backend, Accelerate, Align, Punctuate, Diarize, Persist) are skipped when unnecessary, budgeted independently, and profiled automatically. The PipelineBuilder validates ordering at build time; runtime never hits "stage X requires stage Y" errors.
The entire crate uses #![forbid(unsafe_code)]. forbid is stricter than deny: it cannot be overridden per item. Memory safety is enforced by the compiler, not by code review.
franken_whisper decodes MP3, AAC, FLAC, WAV, OGG (Vorbis), and ALAC entirely in-process via symphonia; no ffmpeg, no Python, no PATH lookup. ffmpeg is only invoked as a fallback for video files, exotic codecs (AC3, DTS, Opus-in-MKV), and live microphone capture. When ffmpeg is needed and missing on Linux x86_64, it is downloaded once into the per-user state directory.
Every adaptive controller in the system (the backend router, the speculative window controller, the budget tuner, the TTY adaptive bitrate controller, the correction tracker) ships with an explicit alien-artifact engineering contract: state space, action space, loss matrix, posterior, calibration metric, deterministic fallback, and an evidence ledger. When models drift, the system falls back to a deterministic policy rather than confidently making bad decisions.
+--------------------------------------------------------------+
| INFERENCE ENGINES (run the model) |
| |
| whisper.cpp (C++, CPU/Metal/CUDA, ~47k stars) |
| faster-whisper (Python/CTranslate2, ~14k stars) |
| OpenAI Whisper (Python/PyTorch, ~95k stars) |
+--------------------------------------------------------------+
|
+------------------------------v-------------------------------+
| ENHANCED PIPELINES (add features on top) |
| |
| WhisperX (faster-whisper + wav2vec2 + pyannote)|
| whisper-diarization (Whisper + Demucs + NeMo TitaNet) |
| insanely-fast-whisper (HuggingFace Transformers, max GPU) |
| whisper-timestamped (DTW word timestamps) |
+--------------------------------------------------------------+
|
+------------------------------v-------------------------------+
| ORCHESTRATION (manage engines/pipelines) |
| |
| > franken_whisper < (Rust, Bayesian routing, |
| 10-stage pipeline, conformance |
| gating, native engine rollout, |
| evidence-based decisions) |
+--------------------------------------------------------------+
Most tools occupy one level. franken_whisper is the orchestration layer: it wraps inference engines and enhanced pipelines behind a unified interface, then adds capabilities none of them provide individually.
| Capability | whisper.cpp | faster-whisper | WhisperX | WhisperLive | WhisperS2T | franken_whisper |
|---|---|---|---|---|---|---|
| Language | C++ | Python | Python | Python | Python | Rust |
| Multi-backend | — | — | — | 3 | 4 | 3 backends + paired native pilots |
| Backend selection | — | — | — | manual | manual | Bayesian decision contract |
| Pipeline stages | monolithic | monolithic | 3 | monolithic | monolithic | 10 composable stages |
| Per-stage budgets | — | — | — | — | — | independent timeouts + auto profiling |
| Speculative streaming | — | — | — | single-model | — | dual-model fast+quality with retraction |
| Conformance validation | — | — | — | — | — | cross-engine, 50 ms tolerance, drift detection |
| Native rollout governance | — | — | — | — | — | 5-stage Shadow → Sole with conformance gates |
| Memory safety | C++ | Python GC | Python GC | Python GC | Python GC | #![forbid(unsafe_code)] |
| Capability | whisper.cpp | faster-whisper | WhisperX | WhisperLive | **franken_whisper
$ claude mcp add franken_whisper \
-- python -m otcore.mcp_server <graph>