Skip to main content

sounddifff

CI PyPI Python License: MIT

Origin and maintenance. sounddifff is the continuation of sounddiff, created by systemBlue and released under the MIT license (original package on PyPI, last version 0.2.1). The original repository is no longer available. This project is maintained by Jaime Fernández González (jaimefgdev): the original idea and the code up to March 2026 are systemBlue's; everything added from October 2026 onward is listed in the CHANGELOG.

sounddifff is a CLI tool for audio producers and developers to compare two audio files (or two folders) and see exactly what changed, and to check a single file against the loudness targets of Spotify, YouTube, Apple Music, podcasts and broadcast. It reports differences in loudness, spectral balance, timing, and flags issues like clipping and silence. Output comes as colored terminal text, structured JSON, or a self-contained HTML report.

sounddifff HTML report comparing two masters: loudness, spectral bands and clipping

Example

$ sounddifff mix-v3.wav mix-v4.wav

sounddifff: mix-v3.wav vs mix-v4.wav

Duration     3:42.108 → 3:42.108  (no change)
Sample Rate  48000 Hz → 48000 Hz  (no change)
Channels     stereo   → stereo    (no change)

Loudness (integrated)
  LUFS       -14.2    → -12.8     (+1.4 dB)
  Peak dBTP  -1.1     → -0.3      (+0.8 dB)
  LRA         8.2     →  6.4      (-1.8 LU)

Spectral
  Low  (20-250 Hz)    +0.8 dB avg
  Mid  (250-4k Hz)    +0.3 dB avg
  High (4k-20k Hz)    +1.9 dB avg

Segments
  0:00-1:12   similar (correlation: 0.97)
  1:12-1:14   ADDED (new content, 2.1s)
  1:14-3:42   similar (correlation: 0.98, shifted +2.1s)

Issues
  ⚠ Clipping detected in mix-v4.wav at 2:31.4 (3 samples)

Installation

pip install sounddifff

The name has three f's: the original sounddiff package on PyPI belongs to systemBlue and stopped at 0.2.1. Package, command and Python module are all called sounddifff.

Requires Python 3.10 or later. Supports WAV, FLAC, OGG, and AIFF natively. For MP3 and AAC support, install ffmpeg.

Usage

Compare two files with colored terminal output:

sounddifff old-mix.wav new-mix.wav

Get structured JSON for scripts and CI pipelines:

sounddifff old.wav new.wav --format json

Generate an HTML report:

sounddifff old.wav new.wav --format html -o report.html

Audio regression checks in CI

--fail-if turns sounddifff into a test: it prints the report as usual and exits with code 3 if any rule is broken (code 1 is reserved for errors such as unreadable files).

sounddifff reference.wav render.wav --fail-if "lufs>1,peak>0.5,band>3,clipping"
Rule Fails when
lufs>N integrated loudness changes by more than N LU
peak>N true peak changes by more than N dB
lra>N loudness range changes by more than N LU
band>N any spectral band changes by more than N dB
duration>N duration changes by more than N seconds
correlation<N overall waveform correlation drops below N
clipping the second file clips
silence the second file has more silent regions than the first
format sample rate or channel count differ

Check one file against a delivery target

sounddifff check episode.wav --preset podcast
sounddifff check: episode.wav against Podcasts (Apple Podcasts, Spotify for Podcasters)

  FAIL  loudness   -11.2 LUFS     target -16.0 +/- 1 LUFS
  PASS  true peak  -10.5 dBTP     target <= -1.0 dBTP
  PASS  clipping   0 event(s)     target none

  Gain to reach the target: -4.8 dB
Preset Integrated loudness True peak
spotify, youtube -14 LUFS ± 1 ≤ -1 dBTP
apple-music, podcast -16 LUFS ± 1 ≤ -1 dBTP
ebu-r128 (European broadcast) -23 LUFS ± 0.5 ≤ -1 dBTP
atsc-a85 (US broadcast) -24 LUFS ± 2 ≤ -2 dBTP

True peak is measured with 4x oversampling (ITU-R BS.1770-4), so inter-sample peaks that would clip after encoding are caught. Override any value with --lufs, --tolerance or --max-peak; add --format json for scripts. Exit code 3 when the file misses the target.

Compare folders

sounddifff renders/v1/ renders/v2/ --fail-if "lufs>1,clipping"

Files are paired by relative path (sub-folders included) and compared one by one; files that exist in only one folder are listed. Useful for game sound banks, voice lines or any batch of renders. --format json is supported.

GitHub Action

permissions:
  contents: read
  pull-requests: write   # only needed for comment: true

steps:
  - uses: actions/checkout@v4

  # Compare a render with its reference (files or folders)
  - uses: jaimefgdev/sounddifff@v0.4.0
    with:
      reference: audio/reference.wav
      candidate: build/render.wav
      fail-if: lufs>1,peak>0.5,clipping
      comment: true

  # Or check one file against a delivery target
  - uses: jaimefgdev/sounddifff@v0.4.0
    with:
      candidate: build/episode.wav
      preset: podcast
      artifact-name: podcast-check

The result goes to the job summary and, with comment: true, to a pull request comment that is updated on every push. File comparisons also upload the HTML report as an artifact. The step fails when a rule or target is missed. Outputs: passed (true/false) and report (path of the HTML file).

--fail-if, sounddifff check, folder comparison and the GitHub Action were added by Jaime Fernández González (jaimefgdev) in October 2026.

What it analyzes

Category Measurements
Loudness Integrated LUFS, true peak (dBTP), loudness range (LRA) per ITU-R BS.1770
Spectral Average energy per frequency band (low, mid, high) with configurable ranges
Temporal Segment-level cross-correlation, added/removed/shifted section detection
Detection Clipping events (timestamp, channel, sample count), silence regions
Metadata Duration, sample rate, channels, bit depth, format

Output formats

Terminal is the default. Colored, grouped by category, designed to be read top to bottom. Uses rich for formatting.

JSON outputs the same data in a structured format. Pipe it to jq, parse it in Python, or use it in CI pipelines for automated regression testing.

HTML generates a self-contained report with inline styles. No external dependencies. Open it in any browser, share it with your team, or archive it alongside your session files.

How it's built

sounddifff is written in Python with a modular architecture. Each analysis type (loudness, spectral, temporal, detection) lives in its own module with no cross-dependencies. The core orchestrator loads two audio files, runs all analyzers, and passes the results to a formatter.

Dependency Purpose
soundfile Audio I/O via libsndfile
numpy Array math, FFT, cross-correlation
scipy Signal processing
pyloudnorm ITU-R BS.1770 loudness measurement
click CLI framework
rich Terminal formatting
jinja2 HTML report templates

See docs/architecture.md for the full module breakdown and data flow.

Documentation

Contributing

Contributions are welcome. See CONTRIBUTING.md for setup instructions and our development workflow.

The issue board has open work organized by milestone. Issues labeled good first issue are scoped for newcomers and have enough context to get started without deep DSP knowledge.

Security

Report vulnerabilities privately through GitHub security advisories. See SECURITY.md for our disclosure policy.

License

MIT

Metadata

Release files for sounddifff 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sounddifff 0.4.0
File Size Uploaded
sounddifff-0.4.0.tar.gz 89.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sounddifff 0.4.0
File Interpreter ABI Platform
sounddifff-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 119.1 kB

Release files / sounddifff-0.4.0.tar.gz

Download URL sounddifff-0.4.0.tar.gz
Size 89.6 kB
Tags Source
SHA-256 checksum
How to use checksums
25e911cbb0735906a66c2859c739fdb62f7e8516bb3f1c3963c15214fdbae0e0
BLAKE2b-256 checksum
How to use checksums
a178c5e2dfc7602c2431efbf21fc2f5cc7d1b470208368039839960e6980f9f3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release files / sounddifff-0.4.0-py3-none-any.whl

Download URL sounddifff-0.4.0-py3-none-any.whl
Size 29.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
af9e0641a56bec4435be3e20d6ce1c9e4a158223d5870636f15a12a70daf1cfe
BLAKE2b-256 checksum
How to use checksums
a51c0a8f71c71d6d3e7a298da6541875853b7f800ed6eb135110236685ee6430
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files

0.3.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page