scribble

Library Listed

High-level Rust API for audio transcription using Whisper

Checked · Sources

Downloads
457
Dependents
0
Stars
105
Forks
10
Contributors
6
Commits
391
Latest release
0.5.4 ·

About

From the project README ·

Scribble is a fast, lightweight transcription engine written in Rust, with a built-in Whisper backend and a backend trait for custom implementations.

banner

Scribble will demux/decode audio or video containers (MP4, MP3, WAV, FLAC, OGG, WebM, MKV, etc.), downmix to mono, and resample to 16 kHz — no preprocessing required.

Demo

Project goals

  • Provide a clean, idiomatic Rust API for audio transcription
  • Support multiple output formats (JSON, VTT, plain text, etc.)
  • Work equally well as a CLI tool or embedded library
  • Be streaming-first: designed to support incremental, chunk-based transcription pipelines (live audio, long-running streams, and low-latency workflows)
  • Enable composable pipelines: VAD → transcription → encoding, with clear extension points for streaming and real-time use cases
  • Keep the core simple, explicit, and easy to extend

Scribble is built with streaming and real-time transcription in mind, even when operating on static files today.

Installation

Rust toolchain

Scribble targets Rust stable (tracked via rust-toolchain.toml).

Clone the repository and build the binaries:

./scripts/build-all.sh

Or build a single binary to a target directory:

./scripts/build.sh scribble-cli ./dist
Read the full README

This will produce the following binaries:

  • scribble-cli — transcribe audio/video (decodes + normalizes to mono 16 kHz)
  • scribble-server — HTTP server for transcription
  • model-downloader — download Whisper and VAD models

GPU acceleration (feature flags)

Scribble exposes whisper-rs GPU backend features as Cargo features. Enable the backend you want in Cargo.toml or via --features:

[dependencies]
scribble = { version = "0.5", features = ["cuda"] }
cargo run --features "bin-scribble-cli,cuda" --bin scribble-cli -- \
  --model ./models/ggml-large-v3-turbo.bin \
  --input ./input.wav

Available GPU feature flags:

  • cuda (NVIDIA CUDA)
  • metal (Apple Metal)
  • hipblas (AMD ROCm)
  • vulkan (Vulkan)
  • coreml (Apple CoreML)

These are passthrough features; you still need the corresponding system dependencies installed for your platform. See the whisper-rs documentation for backend setup details.

model-downloader

model-downloader is a small helper CLI for downloading known-good Whisper and Whisper-VAD models into a local directory.

List available models
cargo run --features bin-model-downloader --bin model-downloader -- --list

Example output:

Whisper models:
  - tiny
  - base.en
  - large-v3-turbo
  - large-v3-turbo-q8_0
  ...

VAD models:
  - silero-v5.1.2
  - silero-v6.2.0
Download a model
cargo run --features bin-model-downloader --bin model-downloader -- --name large-v3-turbo

By default, models are downloaded into ./models.

Download into a custom directory
cargo run --features bin-model-downloader --bin model-downloader -- \
  --name silero-v6.2.0 \
  --dir /opt/scribble/models

Downloads are performed safely:

  • written to *.part
  • fsynced
  • atomically renamed into place

scribble-cli

scribble-cli is the main transcription CLI.

It accepts audio or video containers and normalizes them to Whisper’s required mono 16 kHz internally. Provide:

  • an input media path (e.g. MP4, MP3, WAV, FLAC, OGG, WebM, MKV) or - to stream from stdin
  • a Whisper model
  • a Whisper-VAD model (used when --enable-vad is set)
Basic transcription (VTT output)
cargo run --features bin-scribble-cli --bin scribble-cli -- \
  --model ./models/ggml-large-v3-turbo.bin \
  --vad-model ./models/ggml-silero-v6.2.0.bin \
  --input ./input.mp4

Output is written to stdout in WebVTT format by default.

Stream a live URL into scribble-cli (via ffmpeg)

If you have a live audio stream URL (MP3/AAC/etc.), you can decode it to Whisper-friendly WAV and pipe it into scribble-cli via stdin:

ffmpeg -re -loglevel error -nostats \
  -i "https://stream.example.com/live.mp3?session-id=REDACTED" \
  -f wav -ac 1 -ar 16000 - \
| scribble-cli \
    --model ./models/ggml-tiny.bin \
    --vad-model ./models/ggml-silero-v6.2.0.bin \
    --enable-vad \
    --input -
Stream a Twitch channel into scribble-cli (via streamlink + ffmpeg)

If you have streamlink installed, you can pull a Twitch stream to stdout and feed it through ffmpeg:

streamlink --stdout https://www.twitch.tv/dougdoug best \
| ffmpeg -hide_banner -loglevel error -i pipe:0 -vn -ac 1 -ar 16000 -f wav pipe:1 \
| scribble-cli \
    --model ./models/ggml-tiny.bin \
    --vad-model ./models/ggml-silero-v6.2.0.bin \
    --enable-vad \
    --input -

scribble-server

scribble-server is a long-running HTTP server that loads models once and accepts transcription requests over HTTP.

Start the server
cargo run --features bin-scribble-server --bin scribble-server -- \
  --model ./models/ggml-large-v3-turbo.bin \
  --vad-model ./models/ggml-silero-v6.2.0.bin \
  --host 127.0.0.1 \
  --port 8080
Transcribe via HTTP (multipart upload)
curl -sS --data-binary @./input.mp4 \
  "http://127.0.0.1:8080/transcribe?output=vtt" \
  > transcript.vtt

For JSON output:

curl -sS --data-binary @./input.wav \
  "http://127.0.0.1:8080/transcribe?output=json" \
  > transcript.json

Example using all query params:

curl -sS --data-binary @./input.mp4 \
  "http://127.0.0.1:8080/transcribe?output=json&output_type=json&model_key=ggml-large-v3-turbo.bin&enable_vad=true&translate_to_english=true&language=en" \
  > transcript.json
Prometheus metrics

scribble-server exposes Prometheus metrics at GET /metrics.

curl -sS "http://127.0.0.1:8080/metrics"

Key metrics:

  • scribble_http_requests_total (labels: status)
  • scribble_http_request_duration_seconds (labels: status)
  • scribble_http_in_flight_requests
Logging

All binaries emit structured JSON logs to stderr.

  • Default level: error
  • Override with SCRIBBLE_LOG (e.g. SCRIBBLE_LOG=info)
JSON output
cargo run --features bin-scribble-cli --bin scribble-cli -- \
  --model ./models/ggml-large-v3-turbo.bin \
  --vad-model ./models/ggml-silero-v6.2.0.bin \
  --input ./input.wav \
  --output-type json
Enable voice activity detection (VAD)
cargo run --features bin-scribble-cli --bin scribble-cli -- \
  --model ./models/ggml-large-v3-turbo.bin \
  --vad-model ./models/ggml-silero-v6.2.0.bin \
  --enable-vad \
  --input ./input.wav

When VAD is enabled:

  • non-speech regions are suppressed
  • if no speech is detected, no output is produced
Specify language explicitly
cargo run --features bin-scribble-cli --bin scribble-cli -- \
  --model ./models/ggml-large-v3-turbo.bin \
  --vad-model ./models/ggml-silero-v6.2.0.bin \
  --input ./input.wav \
  --language en

If --language is omitted, Whisper will auto-detect.

Write output to a file
cargo run --features bin-scribble-cli --bin scribble-cli -- \
  --model ./models/ggml-large-v3-turbo.bin \
  --vad-model ./models/ggml-silero-v6.2.0.bin \
  --input ./input.wav \
  --output-type vtt \
  > transcript.vtt

Library usage

Scribble is also designed to be embedded as a library.

High-level usage looks like:

use scribble::{Opts, OutputType, Scribble};
use std::fs::File;

let mut scribble = Scribble::new(
    ["./models/ggml-large-v3-turbo.bin"],
    "./models/ggml-silero-v6.2.0.bin",
)?;

let mut input = File::open("audio.wav")?;
let mut output = Vec::new();

let opts = Opts {
    model_key: None,
    enable_translate_to_english: false,
    enable_voice_activity_detection: true,
    language: None,
    output_type: OutputType::Json,
    incremental_min_window_seconds: 1,
};

scribble.transcribe(&mut input, &mut output, &opts)?;

let json = String::from_utf8(output)?;
println!("{json}");

Goals

  • [X] Make VAD streaming-capable
  • [X] Support streaming and incremental transcription
  • [X] Select the primary audio track in multi-track video containers
  • [X] Implement a web server
  • [X] Add Prometheus metrics endpoint
  • [X] Add structured logs (tracing)
  • [X] Expand test coverage to 80%+

Coverage

This project uses cargo-llvm-cov for coverage locally and in CI.

One-time setup:

rustup component add llvm-tools-preview
cargo install cargo-llvm-cov

Run coverage locally:

# Print a summary to stdout
cargo llvm-cov --features bin-scribble-cli,bin-model-downloader,bin-scribble-server --all-targets

# Generate an HTML report (writes to ./target/llvm-cov/html)
cargo llvm-cov --features bin-scribble-cli,bin-model-downloader,bin-scribble-server --all-targets --html

Status

Scribble is under active development. The API is not yet stable, but the foundations are in place and evolving quickly.

Release notes live in CHANGELOG.md (and GitHub Releases).

Contributing

See STYLEGUIDE.md for code style, verification conventions, and repo-level checklists.

License

MIT

footer

Runs on
CUDA, Metal, Vulkan
What shows it
  • CUDA: scribble feature cuda
  • Metal: scribble feature metal
  • Vulkan: scribble feature vulkan
Native code
Required
  • Binds native code: whisper-rs-sys
Python bindings
No Python binding crate found
License
MIT

Compare with similar projects

Order: strongest tier first, then most downloads, then name, with unmeasured values last. A library counts downloads over 30 days. An app counts binary downloads per release. An app with none counts its crate downloads over 30 days. ML Rust runs this catalogue, so its closest project always gets a row.

scribble beside the projects that share a topic with it
ProjectDownloadsDependentsStarsLatest releaseRuns on (GPU)Native codeLicense
scribble This page Listed

High-level Rust API for audio transcription using Whisper

457 downloads over 30 days 0 105 0.5.4 CUDA, Metal, Vulkan Binds native code: whisper-rs-sys MIT
whisper-rs Featured

Rust bindings for whisper.cpp

466,717 downloads over 30 days 98 Not measured 0.16.0 CUDA, Metal, Vulkan Binds native code: piper, piper1-rs-sys, whisper, whisper-rs-sys. Build uses a native toolchain: bindgen, cmake Unlicense
sherpa-onnx Featured

Safe Rust wrapper for sherpa-onnx speech recognition toolkit

259,599 downloads over 30 days 28 15,834 2.0.1 GPU support unknown Binds native code: sherpa-onnx, sherpa-onnx-sys Apache-2.0
sonora Listed

Automatic Gain Control 2 (AGC2) with RNN VAD for WebRTC Audio Processing

551,810 downloads over 30 days 3 99 0.3.0 GPU support unknown No native code found BSD-3-Clause

Rust implementation for the CohereLabs/cohere-transcribe-03-2026 speech-to-text model. Includes a CLI and an OpenAI-compatible API server.

0 downloads over 30 days 0 101 0.1.1 CUDA Binds native code: torch-sys (feature tch-backend). Build uses a native toolchain: cmake Apache-2.0
voxr New

Audio and speech on boostr: compressed-audio decode, resampling, DSP and grapheme to phoneme, with speech synthesis (Kokoro, VITS), voice cloning (VoxCPM2), transcription with word timings (Whisper), voice activity (Silero) and audio-text scoring (CLAP), on CPU or CUDA.

642 downloads over 30 days 2 2 0.9.1 CUDA No native code found Apache-2.0
Why ListedNo archive, New or Featured rule places it, so it is Listed.

What it lacks for Featured

  • It has 0 active dependents and 0 new dependents in 365 days. Featured needs 11 active dependents or 9 new dependents in 365 days. The repository route reads 105 stars, 10 forks and 6 contributors. It needs 4,539 stars, 434 forks and 79 contributors together.

What else the check found

  • The last activity is on 22 Jun 2026, 140 days ago. The rules expect an update within 450 days. Dormancy rule

Exact rules: Listed, Featured library. The check on applied thresholds version 9.

Every rule outcome, as the check records it
  • expected-interval: version 0.5.4 base 450: E = 450 days
  • dormancy: last activity 2026-06-22, 140 days ago, E = 450: active
  • featured: not featured: active_users 0 < 11 and new_adopters 0 < 9 and repository route stars 105 (needs 4539), forks 10 (needs 434), contributors 6 (needs 79)
  • listed: listed: no archive, new or featured rule applies

Measurements and sources

Each signal row shows the raw value, its source and the fetch date. The Sources list gathers every distinct source on this page. Movement needs more history.

Sources6 sources
Adoption0 active dependents, 0 new dependents in 365 days1 not measured
Adoption measurements
SignalValueSourceFetchedCounts
Active dependents0crates.io database dumpYes
New dependents (365 days)0crates.io database dumpYes
Peak active dependents0crates.io database dumpYes
Active dependents as a share of the peak1crates.io database dumpYes
Binary downloads per releaseNot measuredYes
MaintenanceLatest human commit: 4 months ago3 not measured
Maintenance measurements
SignalValueSourceFetchedCounts
Latest human commit2026-06-22GitHub repositoryYes
Latest release2026-02-27crates.io database dumpYes
First release2025-12-19crates.io database dumpYes
Latest version0.5.4crates.io database dumpYes
Days the oldest outside issue waits for a reply293GitHub repositoryYes
Maintainer replies over 365 days17GitHub repositoryYes
Repository archivedfalseGitHub repositoryYes
Repository gonefalseGitHub repositoryYes
Release commit or manifest in the repotruecrates.io packageYes
Published docstruecrates.io database dumpYes
Latest release fails cargo checkNot measuredYes
Build check dateNot measuredYes
Build check toolchainNot measuredYes
SecurityUnpatched vulnerabilities: none
Security measurements
SignalValueSourceFetchedCounts
Unpatched vulnerabilities past the grace windownoneRustSec advisory databaseYes
RustSec unmaintained advisorynoneRustSec advisory databaseYes
Deprecation noticenonecrates.io database dumpYes
Deprecated requirementnonecrates.io database dumpYes
Distribution17 releases, 457 downloads over 30 days5 not measured
Distribution measurements
SignalValueSourceFetchedCounts
Releases17crates.io database dumpYes
Downloads over 30 days457crates.io database dumpYes
Binary downloads over the last 3 releasesNot measuredYes
Homebrew installs on request over 365 daysNot measuredYes
Repology repository familiesNot measuredYes
Docker pull growth over 90 daysNot measuredYes
Docker pulls at the growth baselineNot measuredYes
Every version a prereleasefalsecrates.io database dumpYes
Every version 0.0.xfalsecrates.io database dumpYes
Every version yankedfalsecrates.io database dumpYes
Crate deleted from crates.iofalsecrates.io database dumpYes
Repository105 stars, 10 forks, 6 contributors, 391 commits. Stars alone never qualify a project.
Repository measurements
SignalValueSourceFetchedCounts
GitHub stars105GitHub repositoryYes — one part of the repository route
GitHub forks10GitHub repositoryYes — one part of the repository route
Contributors with a GitHub account6GitHub contributorsYes — one part of the repository route
Commits on the default branch391GitHub repositoryNo
Repository's main crate left out of the entrynonecrates.io database dumpYes
Facts that never count
Facts that never count measurements
SignalValueSourceFetchedCounts
LicenseMITcrates.io database dumpNo
Runs on, from listed crates and their direct dependenciesCUDA, Metal, Vulkancrates.io database dumpNo
What shows each backendCUDA: scribble feature cuda; Metal: scribble feature metal; Vulkan: scribble feature vulkancrates.io database dumpNo
Native code, from listed crates and their dependenciesBinds native code: whisper-rs-syscrates.io database dumpNo
Python bindings, from direct dependencies of listed cratesNo Python binding crate foundcrates.io database dumpNo
Crates that depend on a listed crate directly0crates.io database dumpNo

Corrections and review history

Report a correction

No correction applies to this entry.

Judgments

A judgment enters only through an approved issue and a merged pull request.

No judgment applies to this entry.