mel_spec
Library Listed
Mel spectrograms aligned to the results from the whisper.cpp, pytorch and librosa reference implementations and suited to streaming audio.
- Downloads
- 26,437
- Dependents
- 6
- Stars
- 91
- Forks
- 13
- Contributors
- 7
- Commits
- 145
- Latest release
- 0.5.0 ·
About
Rust mel spectrogram, filterbank, and VAD components for ASR systems.
Release note: 0.5.0 makes CPU feature extraction faster. The CPU paths
use a real-input FFT, and the batch paths project eight frames at a time.
Results match 0.4.1 within FFT rounding. Details are in
CHANGELOG.md.
| Speedup (11 s JFK sample, one Apple M1 core) | |
|---|---|
| Batch log-mel | 1.9-2.0x |
| Whisper mel | 1.7-2.0x |
| Kaldi fbank | 1.5x |
| VAD | 3.7x |
Read the full README
Main Features
| Feature | API | Use |
|---|---|---|
| Batch log-mel frontend | BatchLogMelSpectrogram | Whole-utterance log-mel features with centered framing, pre-emphasis, padding, and per-feature normalization. The Parakeet/NeMo frontend in asr-api uses it. |
| Whisper-compatible mel | Spectrogram, MelSpectrogram | Streaming and batch log-mel spectrograms that match whisper.cpp, PyTorch, and librosa. |
| Kaldi-compatible fbank | Fbank | Kaldi-style filterbank features with the Povey window, the Kaldi mel scale, and CMN. |
| Mel filterbanks | mel, SparseMelFilterbank | Slaney or HTK filterbank matrices, and the sparse form that the CPU paths execute. |
| Streaming input | RingBuffer | Bounded sample buffer that gives one mel frame for each hop. The rtrb feature uses an rtrb ring buffer. |
| Interleaved PCM | compute_interleaved, downmix_interleaved | Downmix of stereo or multichannel PCM before batch feature extraction. |
| Model-free VAD | VoiceActivityDetector, vad_boundaries | Speech decisions and timestamps from the edge structure of mel frames. |
| TGA mel images | tga_8bit, save_tga_8bit, load_tga_8bit | Quantized 8-bit mel spectrograms in TGA files. |
| WASM worker | SpeechToMel (wasm feature) | Mel frames, quantization, and VAD in a browser worker. Hush uses it for local Whisper transcription. |
| GPU backends | WgpuMelSpectrogram, CudaMelSpectrogram | Experimental batched mel generation with wgpu (Metal, Vulkan, DX12) or cuda (NVIDIA). |
Quick Start
use mel_spec::prelude::*;
let samples = vec![0.0_f32; 16_000];
let mel_frames = Spectrogram::compute_mel_spectrogram_cpu(
&samples,
400,
160,
80,
16_000.0,
);
println!("frames={}", mel_frames.len());
For whole utterances, BatchLogMelSpectrogram gives feature-major output. Keep
the scratch buffers to reuse them across calls:
use mel_spec::prelude::*;
let frontend = BatchLogMelSpectrogram::new(BatchLogMelConfig::default()).unwrap();
let mut scratch = frontend.scratch();
let samples = vec![0.0_f32; 16_000];
let features = frontend.compute_with_scratch(&samples, &mut scratch).unwrap();
assert_eq!(features.shape(), &[80, 101]);
Use BatchLogMelSpectrogram::compute_interleaved for interleaved audio. The
method averages all input channels before feature extraction.
The focused API examples are kept in the example READMEs so the top-level README stays readable:
| Example | Description |
|---|---|
| browser | Stream microphone or WAV audio to a WASM mel worker. |
| mel_tga | Convert raw audio to TGA mel spectrogram images. |
| tga_whisper | Transcribe precomputed TGA mel spectrograms with whisper.cpp. |
| stream_whisper | Stream ffmpeg audio through mel, VAD, and Whisper. |
| vad_ten_eval | Evaluate mel-spec VAD against the vendored TEN-VAD testset. |
Voice Activity Detection
mel-spec includes a lightweight, model-free VAD. It does not load a neural VAD
runtime. It looks for speech-like Sobel edge structure in mel spectrogram frames
and can attach STFT-derived timestamps to each decision.
Current balanced default on the checked-in TEN-VAD testset:
| System | Setting | Macro precision | Macro recall | Macro F1 | Macro FPR | RTFx |
|---|---|---|---|---|---|---|
mel-spec | balanced default | 0.8751 | 0.8785 | 0.8566 | 0.3946 | 819.6 |
mel-spec | high-F1 sweep result | 0.8165 | 0.9635 | 0.8769 | 0.6459 | 828.9 |
| Silero | tuned threshold 0.13 | 0.8897 | 0.9388 | 0.9088 | 0.3602 | 110.3 |
| Silero | default threshold 0.50 | 0.9379 | 0.8630 | 0.8826 | 0.1778 | 110.6 |
The balanced default is not trying to beat learned VADs at strict endpointing. It is a fast built-in option that reuses ASR mel features and avoids another model dependency. Tuned Silero is still more accurate overall. TEN-VAD is the source of the labels and upstream reports stronger precision/recall than Silero and WebRTC on the same testset.
Detailed method, provenance, commands, speed notes, and per-file results are in doc/vad/README.md.
TGA Spectrograms
TGA spectrograms are useful when you want a simple interchange format for mel features. They can be inspected as images, spliced, stored, and passed to the Whisper examples without keeping the original audio around.
This path is live in Hush as local browser ASR. The browser uses the
Whisper-compatible log-mel output from mel-spec. It stores captured speech as
compact 8-bit TGA images. It decodes the images to an 80-mel Float32Array and
passes the tensor to whisper_set_mel in a custom whisper.cpp WASM binding.
The active Hush deployment verifies that local WASM Whisper
can transcribe from the mel tensor without posting microphone audio to a server.
This uses the proposed direct-mel entry point for whisper.cpp,
not the stock browser example that feeds PCM audio into whisper.wasm.
"the quest for peace."
Mel spectrograms are also robust under heavy quantization. Whisper does not need high-precision PCM after projection into mel space. Eight-bit TGA images preserve the information that the model sees. Coarse mel-value rounding can also retain useful transcription quality.
Original: [0.158, 0.266, 0.076, 0.196, 0.167, ...]
Rounded: [0.2, 0.3, 0.1, 0.2, 0.2, ...]
(top: original mel values, bottom: values rounded to 1.0e-1 before image
quantization)
Performance
mel-spec 0.5.0 on the 11-second JFK sample, one Apple M1 core, release build:
| Path | Time | Realtime factor |
|---|---|---|
BatchLogMelSpectrogram, Parakeet configuration | 1.13 ms | 9,700x |
BatchLogMelSpectrogram, default configuration | 0.95 ms | 11,600x |
Spectrogram::compute_mel_spectrogram_cpu (Whisper) | 1.97 ms | 5,600x |
Spectrogram::add and MelSpectrogram::add (Whisper, streaming) | 2.53 ms | 4,300x |
RingBuffer | 2.34 ms | 4,700x |
Fbank::compute | 2.13 ms | 5,200x |
VoiceActivityDetector::add_activity | 0.23 ms | 47,000x |
The Parakeet configuration has 128 mels, pre-emphasis 0.97, and per-feature normalization. The time increases linearly with the audio length: 66 seconds of audio take 6.8 ms in the Parakeet configuration.
mel() and the Kaldi filterbank builder produce dense filterbank matrices for
reference, fixture comparison, and interchange with other toolchains. The CPU
paths execute a sparse form of the same matrices, with one contiguous band of
weights for each mel row. Tests compare the sparse projection with the dense
matrices.
Parakeet/NeMo Frontend Comparison
asr-api uses BatchLogMelSpectrogram for its Parakeet/TDT frontend. The
parakeet_featurizer_bench harness in asr-torch compares this frontend with a
CPU TorchScript trace of the NeMo Parakeet featurizer (featurizer_cpu.pt). The
comparison used the JFK sample on an M1 Mac and mel-spec 0.4.0.
| Featurizer | Shape | Mean | p50 | p95 | RTFx |
|---|---|---|---|---|---|
Rust Parakeet frontend using mel-spec 0.4.0 | 128x1101 | 2.341ms | 2.334ms | 2.406ms | 4699.62 |
| TorchScript CPU trace | 128x1101 | 2.244ms | 2.206ms | 2.813ms | 4902.22 |
Feature comparison across the full tensor:
| Metric | Value |
|---|---|
| MAE | 0.001183 |
| RMSE | 0.023699 |
| Max absolute error | 3.965733 |
| Correlation | 0.999719 |
The mel-spec benchmark gives 2.26 ms for 0.4.1 and 1.13 ms for 0.5.0 in this
configuration. On the first three seconds of the JFK sample, the 0.5.0 features
differ from 0.4.1 by a mean absolute difference of 1.2e-6.
GPU Backends
The CPU path is the default. Experimental native GPU backends are available behind feature flags:
| Feature | Backend |
|---|---|
cuda | NVIDIA-only cuFFT plus CUDA mel projection. |
wgpu | Native Rust GPU backend for Metal, Vulkan, and DX12 systems. |
Build Checks
The top-level library tests do not automatically build every standalone example crate. Use these commands when changing examples:
cargo test --release
MEL_SPEC_FUZZ_SCALE=50 cargo test --release fuzz_
cargo build --release --manifest-path examples/mel_tga/Cargo.toml
cargo build --release --manifest-path examples/stream_whisper/Cargo.toml
cargo build --release --manifest-path examples/tga_whisper/Cargo.toml
cargo run --release --manifest-path examples/vad_ten_eval/Cargo.toml
(cd examples/browser && npm ci && npm test)
MEL_SPEC_FUZZ_SCALE multiplies the number of cases in the seeded random
tests. The Whisper examples compile against the wavey-ai/whisper-rs fork and
require a GGML Whisper model to run inference.
Hush Demo
The Hush live browser demo is active at:
https://wavey.ai/code/hush/?v=20261003-36
The source remains at wavey-ai/hush. With the current tuned settings it works as a live browser VAD, spectrogram debugging view, and local Whisper WASM transcription demo. It exposes mel structure, Sobel edges, ridge tracks, candidate speech regions, and the local transcript in real time. The VAD itself should still be treated as experimental rather than a drop-in replacement for a learned VAD. One strong use case is as a browser-side feature/debugging front end or cheap prefilter before a stronger VAD/ASR model.

Compatibility
- Runs on
- CUDA, WebGPU
What shows it
- CUDA: mel_spec feature cuda
- WebGPU: mel_spec feature wgpu (dependency wgpu)
- Native code
- Optional
- Binds native code: ort-sys (feature ort-tensor)
- Build uses a native toolchain: cc
- 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.
| Project | Downloads | Dependents | Stars | Latest release | Runs on (GPU) | Native code | License |
|---|---|---|---|---|---|---|---|
|
Mel spectrograms aligned to the results from the whisper.cpp, pytorch and librosa reference implementations and suited to streaming audio. |
26,437 downloads over 30 days | 6 | 91 | 0.5.0 | CUDA, WebGPU | Binds native code: ort-sys (feature ort-tensor). Build uses a native toolchain: cc | 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 |
|
nnnoiseless Featured
Audio denoising, derived from Xiph's RNNoise library |
172,829 downloads over 30 days | 27 | 370 | 0.5.2 | GPU support unknown | Binds native code: hdf5-sys (feature train) | BSD-3-Clause |
|
scribble 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 |
|
Voice for the Linux desktop: dictation, read-aloud (TTS), and voice-driven LLM commands, with Groq, OpenAI, Deepgram, and local Whisper backends |
61 binary downloads per release | Not applicable | 149 | 0.2.0 | CUDA, Vulkan | Binds native code: alsa-sys, mac-notification-sys, wayland-sys (feature overlay), whisper-rs-sys (feature local-whisper) | MIT |
|
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 3 active dependents and 2 new dependents in 365 days. Featured needs 11 active dependents or 9 new dependents in 365 days. The repository route reads 91 stars, 13 forks and 7 contributors. It needs 4,539 stars, 434 forks and 79 contributors together.
What else the check found
- The last activity is on 2 Oct 2026, 38 days ago. The rules expect an update within 365 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.0 base 140, raised to the 365-day floor: E = 365 daysdormancy: last activity 2026-10-02, 38 days ago, E = 365: activefeatured: not featured: active_users 3 < 11 and new_adopters 2 < 9 and repository route stars 91 (needs 4539), forks 13 (needs 434), contributors 7 (needs 79)listed: listed: no archive, new or featured rule applies
Crates2 crates
- mel_spec Primary
- mel_spec_pipeline
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
- Description: the crates.io description
- crates.io database dump, fetched
- RustSec advisory database, fetched
- GitHub repository, fetched
- crates.io package, fetched
- GitHub contributors, fetched
Adoption3 active dependents, 2 new dependents in 365 days1 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Active dependents | 3 | crates.io database dump | Yes | |
| New dependents (365 days) | 2 | crates.io database dump | Yes | |
| Peak active dependents | 4 | crates.io database dump | Yes | |
| Active dependents as a share of the peak | 1 | crates.io database dump | Yes | |
| Binary downloads per release | Not measured | Yes |
MaintenanceLatest human commit: 38 days ago3 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Latest human commit | 2026-10-02 | GitHub repository | Yes | |
| Latest release | 2026-10-02 | crates.io database dump | Yes | |
| First release | 2023-07-22 | crates.io database dump | Yes | |
| Latest version | 0.5.0 | crates.io database dump | Yes | |
| Days the oldest outside issue waits for a reply | 0 | GitHub repository | Yes | |
| Maintainer replies over 365 days | 0 | GitHub repository | Yes | |
| Repository archived | false | GitHub repository | Yes | |
| Repository gone | false | GitHub repository | Yes | |
| Release commit or manifest in the repo | true | crates.io package | Yes | |
| Published docs | true | crates.io database dump | Yes | |
| Latest release fails cargo check | Not measured | Yes | ||
| Build check date | Not measured | Yes | ||
| Build check toolchain | Not measured | Yes |
SecurityUnpatched vulnerabilities: none
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Unpatched vulnerabilities past the grace window | none | RustSec advisory database | Yes | |
| RustSec unmaintained advisory | none | RustSec advisory database | Yes | |
| Deprecation notice | none | crates.io database dump | Yes | |
| Deprecated requirement | none | crates.io database dump | Yes |
Distribution17 releases, 26,437 downloads over 30 days5 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Releases | 17 | crates.io database dump | Yes | |
| Downloads over 30 days | 26437 | crates.io database dump | Yes | |
| Binary downloads over the last 3 releases | Not measured | Yes | ||
| Homebrew installs on request over 365 days | Not measured | Yes | ||
| Repology repository families | Not measured | Yes | ||
| Docker pull growth over 90 days | Not measured | Yes | ||
| Docker pulls at the growth baseline | Not measured | Yes | ||
| Every version a prerelease | false | crates.io database dump | Yes | |
| Every version 0.0.x | false | crates.io database dump | Yes | |
| Every version yanked | false | crates.io database dump | Yes | |
| Crate deleted from crates.io | false | crates.io database dump | Yes |
Repository91 stars, 13 forks, 7 contributors, 145 commits. Stars alone never qualify a project.
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| GitHub stars | 91 | GitHub repository | Yes — one part of the repository route | |
| GitHub forks | 13 | GitHub repository | Yes — one part of the repository route | |
| Contributors with a GitHub account | 7 | GitHub contributors | Yes — one part of the repository route | |
| Commits on the default branch | 145 | GitHub repository | No | |
| Repository's main crate left out of the entry | none | crates.io database dump | Yes |
Facts that never count
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| License | MIT | crates.io database dump | No | |
| Runs on, from listed crates and their direct dependencies | CUDA, WebGPU | crates.io database dump | No | |
| What shows each backend | CUDA: mel_spec feature cuda; WebGPU: mel_spec feature wgpu (dependency wgpu) | crates.io database dump | No | |
| Native code, from listed crates and their dependencies | Binds native code: ort-sys (feature ort-tensor). Build uses a native toolchain: cc | crates.io database dump | No | |
| Python bindings, from direct dependencies of listed crates | No Python binding crate found | crates.io database dump | No | |
| Crates that depend on a listed crate directly | 6 | crates.io database dump | No |
Corrections and review history
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.