audio-diag
Standalone Python CLI and library for stereo-master audio diagnostics with explicit reliability tiers. It operates completely offline, requires no external services or telemetry, and classifies measurements into three clear levels of trustworthiness.
- Level 1 (reliable): BS.1770-4 / EBU R128 loudness (integrated, momentary max, short-term max, LRA), sample peak, true peak (4x polyphase Kaiser sinc oversampling), sample-level clipping runs, DC offset, leading and trailing silence, 8-band energy distribution, spectral slope, per-band stereo correlation and mono compatibility.
- Level 2 (heuristic hints): Beat-window energy drops (dropouts vs. sustained breaks), kick-onset deviation from a BPM grid, section energy contrast, crest factor (global and FFT band projections). Always reported with
confidence: "heuristic"and a warning; never treated as an automatic defect. - Level 3 (not determinable from a stereo master): Kick fundamental frequency, kick envelope, kick/rumble ratio, sub masking, musical key. Always reports
{"status": "not_determinable", "reason": ...}. No estimators exist for these from mixed stereo audio.
Requirements
- Python >= 3.12
numpyffmpegandffprobeinstalled and available onPATH
System ffmpeg is used solely to decode audio into float32 PCM; all loudness, true-peak, spectral, and time-domain calculations are performed directly by audio-diag's internal NumPy implementation.
Installation
Install via pip from source:
pip install .
For editable development:
pip install -e .
CLI Usage
The package installs the audio-diag executable and can also be run via python3 -m audio_diag.
# Analyze an audio file
audio-diag analyze track.wav
# Pass tempo and declare intentional arrangement decisions
audio-diag analyze master.wav --bpm 155 --intent "break at bars 33-40" --intent "mono bass"
# Export machine-readable JSON and human-readable Markdown
audio-diag analyze master.wav --json report.json --md report.md
# Inspect the bundled JSON Schema
audio-diag schema
Options
usage: audio_diag analyze [-h] [--bpm BPM] [--json OUT] [--md OUT]
[--intent TEXT] [--target-lufs TARGET_LUFS]
[--tolerance-lu TOLERANCE_LU] [--tp-max TP_MAX]
[--silence-dbfs SILENCE_DBFS] [--drop-db DROP_DB]
file
file: Path to input audio file (opened strictly read-only).--bpm N: Tempo in beats per minute; enables grid-aligned Level 2 onset hints.--json OUT: Write formatted JSON report toOUTinstead of stdout.--md OUT: Write Markdown report toOUTinstead of stderr.--intent TEXT: Declare an intentional artistic choice (repeatable). Echoed inintentional_decisionsand never reported as a defect.--target-lufs N: Integrated loudness target in LUFS (default:-8.0).--tolerance-lu N: Loudness tolerance in LU (default:2.0).--tp-max N: Maximum true peak in dBTP (default:-0.3).--silence-dbfs N: Threshold for digital silence detection (default:-60.0).--drop-db N: Energy drop threshold for dropout/break detection (default:6.0).
Path Safety and Safeguards
- The input file is opened strictly read-only (
O_RDONLY). - The CLI refuses any output path that matches the input file (resolving symlinks and hardlinks).
- The CLI refuses to write output inside protected directories:
- Standard user music directories (
~/Music,~/Música). - Directories configured via the
AUDIO_DIAG_PROTECTED_DIRSenvironment variable (colon-separated).
- Standard user music directories (
- Exit codes:
0on success,2on invalid arguments, decoding failure, or unsafe output paths.
Python API
from audio_diag import analyze, load_schema, to_markdown, DecodeError
# Analyze an audio file
try:
report = analyze("master.wav", bpm=158, intents=["break at bars 33-40"])
except DecodeError as err:
print(f"Decoding failed: {err}")
# Access Level 1 metrics
loudness = report["level1"]["loudness"]
print(f"Integrated LUFS: {loudness['integrated_lufs']}")
print(f"True Peak dBTP: {report['level1']['peaks']['true_peak_dbtp']}")
# Render Markdown report
md_text = to_markdown(report)
# Load the JSON Schema definition
schema = load_schema()
Direct PCM Measurement
Measure in-memory float32 PCM samples without decoding from disk:
import numpy as np
from audio_diag.loudness import measure
# samples: 2D numpy array of shape (num_samples, channels)
stats = measure(samples, sample_rate=48000)
print(stats["integrated_lufs"], stats["true_peak_dbtp"])
Spectral Profiles and Dispersion
Compare relative spectral balance across tracks using gain-normalized power profiles:
from audio_diag.profiles import profile, compare
p1 = profile(analyze("track1.wav"))
p2 = profile(analyze("track2.wav"))
dispersion = compare([p1, p2])
Profiles normalize by total spectral power ($P_{band} / P_{total}$), canceling gain differences. Comparisons produce observed minimum and maximum envelopes per band rather than an artificial average or arbitrary pass/fail gate.
Schema & Report Invariants
- Schema definition is bundled as
report.schema.jsonand accessible viaaudio_diag.load_schema(). - Standard keys:
tool,version,file,thresholds,level1,level2,level3,intentional_decisions,warnings,verdicts. - Finite JSON: values are never
NaNorinf. Missing or invalid numbers are represented asnullwith an accompanying<metric>_reasonexplanation. - Lossy inputs (e.g. MP3, Opus, AAC) set
file.lossy_source: true. True peak, crest factor, and absolute loudness are explicitly marked"not valid for calibration (lossy source)"because lossy codecs alter peaks and levels dynamically.
Metric Summary
- Loudness: ITU-R BS.1770-4 / EBU R128 biquad K-weighting, 400 ms blocks with 75% overlap, -70 LUFS absolute and -10 LU relative gating. Maxima evaluated on a 10 ms grid. LRA uses 3 s windows, -20 LU relative gate, P10-P95 span.
- True Peak: 4x polyphase Kaiser-windowed sinc oversampling filter (32 taps).
- Clipping: Identifies consecutive runs of full-scale samples (
|x| >= 1.0 - 1e-6) per channel. - Bands: Relative energy across 8 sub-bands computed via Hann-windowed periodogram (8192-point FFT, 50% overlap).
- Mono Compatibility: Inter-channel correlation and mono energy ratio $10 \log_{10} \frac{E[((L+R)/2)^2]}{E[(L^2+R^2)/2]}$ per frequency band.
Testing
The test suite runs with Python's standard unittest:
# Run the entire test suite
python3 -m unittest discover
# Run specific test modules
python3 -m unittest tests.test_cli_robustness
python3 -m unittest tests.test_corpus_expected
python3 -m unittest tests.test_ebu_tech3341
test_corpus_expected: Verifies measurements against analytically calculated mathematical ground truths (sine LUFS via K-weighting filter transfer function, pink noise LUFS via Parseval's theorem, exact clipping runs, synthesized click trains).test_ebu_tech3341: Reconstructs EBU Tech 3341 compliance signals and asserts tolerances according to the specification ($\pm 0.1$ LU).test_ffmpeg_crosscheck: Cross-checks loudness and true-peak results against systemffmpeg -af ebur128=peak=true.test_cli_robustness: Verifies CLI exit codes, error handling, path traversal and overwrite protection, memory limits, and schema output.
Test audio signals are generated deterministically in memory or temporary directories and are not committed to source control.
License
MIT License. Copyright (c) 2026 Adrián Cancio / contributors. See LICENSE for details.
Metadata
Release files for audio-diag 0.1.0
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 | Actions |
|---|---|---|---|---|
| audio_diag-0.1.0.tar.gz | 41.7 kB | Without provenance | Details for audio_diag-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| audio_diag-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for audio_diag-0.1.0-py3-none-any.whl |
Total release size: 74.2 kB
Release files / audio_diag-0.1.0.tar.gz
| Download URL | audio_diag-0.1.0.tar.gz |
|---|---|
| Size | 41.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a8c08cc298b077259d68af78231d62a67554ec0f883534f184476682059a74fb
|
|
BLAKE2b-256 checksum How to use checksums |
a261a84b4c1dc65a81909d72e0e29fed9219ac31fa239fd2c341fe015cc06958
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / audio_diag-0.1.0-py3-none-any.whl
| Download URL | audio_diag-0.1.0-py3-none-any.whl |
|---|---|
| Size | 32.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
295ff2257f44fefd3f42e288e6efa7655cfbfb322eb0522d080a698af0e48d7a
|
|
BLAKE2b-256 checksum How to use checksums |
d3c75e28e9ff9494777649b78b23b189fd3224230470203bc7e69270e5bf15b6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Security for audio-diag 0.1.0
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.
To learn more about protecting yourself from malicious actors, visit our package security documentation.