Real-time audio quality assessment for voice apps
Project description
voicequal
Real-time audio quality assessment for voice apps.
Answers the question every voice app eventually has to answer: "is this recording clean enough to process?"
voicequal analyzes audio using four acoustic metrics and returns a
tier — excellent, good, fair, or poor — plus the numbers
behind the decision.
$ voicequal listen
[15:26:37] EXCELLENT room= 45.5 dBA SNR=18.4dB
[15:26:53] CHANGE GOOD room= 55.0 dBA
[15:26:59] CHANGE FAIR room= 60.4 dBA
[15:27:09] CHANGE POOR room= 71.4 dBA
[15:27:53] CHANGE EXCELLENT room= 45.5 dBA
Install
pip install voicequal # core library
pip install 'voicequal[mic]' # + live-mic support
Quick start
Analyze a file
from voicequal import assess
result = assess("recording.wav")
print(result.quality) # "good"
print(result.background_db) # 52.3
print(result.snr) # 24.1
print(result.reason) # "25<snr<=35 with moderate room: good"
Real-time streaming
from voicequal import LiveDetector
detector = LiveDetector()
detector.on_change(lambda result: print(f"→ {result.quality}"))
while streaming:
chunk = get_audio_chunk() # any float32 numpy array
detector.push(chunk)
Command line
voicequal assess my_recording.wav # one-shot file report
voicequal listen # live mic streaming
voicequal listen --calibrate # first-time mic calibration
voicequal listen --sensitive # stricter thresholds
First listen run auto-calibrates the mic (10 seconds — sit quiet
then make noise). Calibration is saved to ~/.voicequal/.
How it works
voicequal is built around SNR-gated tiered assessment. The intuition: a loud room only matters if your voice isn't dominant. So SNR gates the loudness penalty before it applies.
SNR > 50 dB → excellent (voice dominates completely)
SNR 35-50 → excellent unless room > 72 dBA
SNR 25-35 → depends on room loudness
SNR ≤ 25 → composite score across all four metrics
The four metrics feeding this decision:
| Metric | What it captures |
|---|---|
| SNR | How much louder the peak bin is than the noise floor |
| Spectral flatness | How "noise-like" (chaotic) vs "tonal" (structured) it is |
| Temporal variance | Is noise sustained (fan) or transient (a passing car) |
| Background dBA | Overall room loudness, using minimum statistics tracking |
Streaming is stabilized with a hysteresis buffer — a new tier has to persist for 3 frames before it's announced, so single-frame blips don't cause flicker.
Noise floor is estimated with the 10th percentile of recent RMS values (robust to voice bursts, decays when room quiets). Room loudness is reported as the median of recent RMS (tracks sustained noise, ignores single-frame silences).
Limits — read this before using in production
- voicequal is calibrated for voice / recording quality. Whether a recording is clean enough to process, not whether it sounds subjectively pleasing to a human.
- Not a certified acoustic dB meter. Background dBA is a calibrated proxy using rough dB conversion, not the IEC 61672 A-weighted filter a real SPL meter uses.
- Different mics deliver different signal levels. Run
voicequal listen --calibrateonce per new machine or mic setup. - Assumes reasonable audio input. No echo cancellation or noise suppression built in. If your OS pre-processes mic audio (macOS Voice Isolation, browser noise suppression), your calibration will account for it — but detection accuracy will vary.
API reference
assess(path, target_sample_rate=16000, threshold_offset_db=0.0)
Analyze an audio file. Returns a FileAssessment with:
quality, reason, background_db, snr, spectral_flatness,
temporal_variance, primary_score, secondary_score,
total_score, duration_seconds, sample_rate, num_frames.
LiveDetector(sample_rate=16000, stability_frames=3, threshold_offset_db=0.0, db_offset=94.0)
Streaming detector. Methods:
push(samples)— append audio (any length, float32 numpy array)on_change(callback)— fire when the stable tier changesget_current()— snapshot the latestLiveAssessmentreset()— clear buffers and history
CLI
voicequal --version
voicequal assess <path>
voicequal listen [--calibrate] [--reset-calibration]
[--sensitive] [--stability-frames N]
[--heartbeat SECONDS]
Development
git clone https://github.com/jiya-singhal/voicequal
cd voicequal
poetry install --extras mic
poetry run pytest -v
70 tests, all under tests/. The library has no runtime dependencies
beyond numpy, scipy, soundfile, and rich (CLI). sounddevice is
optional (for live-mic support).
License
MIT. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file voicequal-0.1.0.tar.gz.
File metadata
- Download URL: voicequal-0.1.0.tar.gz
- Upload date:
- Size: 17.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.4.1 CPython/3.14.6 Darwin/25.5.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
090061c6b68ad7e01e3c87c31ec6ed32a97c2bdff10376d62267c373fb14cb26
|
|
| MD5 |
fa095ce27fa235f83724d641492a94a9
|
|
| BLAKE2b-256 |
2a85a511a1b45507fa563abe54aae0578286ea4a0b34db6d75feab914a8d5744
|
File details
Details for the file voicequal-0.1.0-py3-none-any.whl.
File metadata
- Download URL: voicequal-0.1.0-py3-none-any.whl
- Upload date:
- Size: 20.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.4.1 CPython/3.14.6 Darwin/25.5.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8d9977ab274cc02dbb141bf1fd7258fde20db19a0c31aca7a85d385dbaf132f2
|
|
| MD5 |
837fb4d6645dc2237a728761a4baef91
|
|
| BLAKE2b-256 |
a7f0fbdc8fadc2bd8316249900c30c38e7d148443e062aa7066fb9ddf9032ae1
|