whisper-guard
English | 繁體中文
whisper-guard is a small Python package that removes common Whisper hallucinations before you ship subtitles or transcripts downstream.
Problem
Whisper output can degrade on silence-heavy or low-confidence clips:
- repeated phrases
- phantom subtitles on silence
- short character loops such as
哈哈哈哈orxyzxyzxyz
This package extracts the anti-hallucination logic from arkiv into a reusable package with a minimal API.
4-Layer Guard
| Layer | What it does | Default |
|---|---|---|
| L1 Silence | Reject all-silence batches | avg no_speech_prob > 0.6 |
| L2 Segment | Filter weak segments | no_speech_prob > 0.8 (unless a ≥5 s window is dense ≥2 chars/s and avg_logprob > -0.5), avg_logprob < -1.5 (short <1.6s: -1.7), compression_ratio > 3.0 |
| L3 Repetition | Reject repetitive text blocks | unique chunk ratio < 0.35 |
| L4 Char loops | Remove looped patterns | 2-4 chars repeated 3+ times |
A/B Test Results
These numbers are from the arkiv guard benchmark set on April 2026.
| Config | Reps | Reduction | Time |
|---|---|---|---|
| Raw Whisper | 16 | baseline | 47.7s |
| Guard only | 2 | -87.5% | 46.5s |
| LLM polish only | 16 | 0% | 106.1s |
| Guard + LLM | 2 | -87.5% | 119.1s |
| VAD + Guard + LLM | 1 | -93.8% | 128.4s |
Accuracy Benchmark
⚠️ This is a curated fixture benchmark, not an independent third-party one. The labels reflect what we already expect the guard to catch, so its value is transparency + regression guard (numbers move if a change starts eating real speech or letting hallucinations through), not a leaderboard score. Reproduce with
python bench/benchmark.py; invariants are pinned intests/test_bench.py.
On a hand-labelled corpus modelling real Chinese Whisper output (genuine speech mixed with each hallucination type):
| Metric | Result | Meaning |
|---|---|---|
| Precision | 100% | Everything flagged really is a hallucination |
| False-positive rate | 0% | Never eats real speech — the property that matters most |
| Recall | 80% | Catches most hallucinations, but misses fluent phantoms (see below) |
| Batch rejection accuracy | 100% | L1 silence / L3 repetition batch verdicts all correct |
Limitations
whisper-guard is metric/pattern-driven — it reasons over no_speech_prob,
avg_logprob, compression_ratio, and character-loop patterns. It therefore
cannot catch a fluent phantom: a single, grammatical hallucinated sentence
with healthy metrics (e.g. 請按讚訂閱開啟小鈴鐺 emitted over silence) is
indistinguishable from real speech by metrics alone.
→ Those are caught by upstream VAD (voice-activity detection). By design, whisper-guard pairs with VAD: VAD removes silence-phantoms, whisper-guard removes repetition / low-confidence / loop hallucinations. The 80% recall above honestly reflects that division of labour.
Install
pip install whisper-guard
For local development:
pip install -e .
Quick Start
from faster_whisper import WhisperModel
from whisper_guard import WhisperGuard
model = WhisperModel("small")
segments, info = model.transcribe("sample.wav")
guard = WhisperGuard()
result = guard.process([segment._asdict() for segment in segments])
if result.passed:
print(result.text)
API
from whisper_guard import WhisperGuard, GuardConfig, filter_hallucinations
WhisperGuard.process() expects segment dictionaries shaped like:
{
"text": "hello world",
"no_speech_prob": 0.12,
"avg_logprob": -0.44,
"compression_ratio": 1.2,
"start": 0.0, # optional — enables dynamic logprob threshold
"end": 2.5, # optional — enables dynamic logprob threshold
}
When start/end are provided, segments shorter than 1.6s use a more lenient logprob threshold (-1.7 vs -1.5) — genuine brief utterances naturally score lower confidence, so loosening the bar avoids wrongly dropping real short speech. Segments without timing info fall back to the normal threshold.
Compatible With
faster-whisperopenai-whispermlx-whisper
Optional Vocab Helpers
from whisper_guard.vocab import build_hotwords_prompt, filter_filler_words
Part Of
Built for the arkiv transcription pipeline and split out as a standalone package for reuse.
License
MIT
Metadata
Release files for whisper-guard 0.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| whisper_guard-0.3.2.tar.gz | 22.6 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| whisper_guard-0.3.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 32.2 kB
Release files / whisper_guard-0.3.2.tar.gz
| Download URL | whisper_guard-0.3.2.tar.gz |
|---|---|
| Size | 22.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4eedd62e294f698836989e0088d4f25bf6fbd28fb1b871715b1cf0477c68bf59
|
|
BLAKE2b-256 checksum How to use checksums |
d3f7ac574b3b0c0cecb7870442fb9d93a4e9fbac8d6d70af7fe21894aa569462
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.11
|
Release files / whisper_guard-0.3.2-py3-none-any.whl
| Download URL | whisper_guard-0.3.2-py3-none-any.whl |
|---|---|
| Size | 9.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1c31c45976ecdca9d664fccacead7057edecd729e3e9d521dbe24f4ea626817a
|
|
BLAKE2b-256 checksum How to use checksums |
52f7678c54831147aeb509f70b8317bc7a7b022adb8e8b2c15ee0be2f9133727
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.11
|
Security for whisper-guard 0.3.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.