Repository

loudness_normalizer

loudness normalizer written by spec-driven opencode

README

Loudness Normalizer

A command-line tool to tag FLAC and MP3 audio files with loudness normalization metadata (ReplayGain/R128) for consistent playback volume across songs.

Features

  • Lossless Processing: Only adds metadata tags, preserving original audio quality
  • Accurate LUFS Measurement: Uses industry-standard algorithms (pyloudnorm, FFmpeg ebur128)
  • FLAC Support: Tags with R128_TRACK_GAIN in Q7.8 format
  • MP3 Support: Tags with REPLAYGAIN_TRACK_GAIN and REPLAYGAIN_TRACK_PEAK
  • Configurable Target: Default -20 LUFS, customizable via --target
  • Smart Skipping: Automatically skips already tagged files
  • JSON Reports: Generate detailed processing reports
  • Progress Display: Shows progress bar for batch processing

Installation

Prerequisites

  • Python 3.10 or higher
  • FFmpeg 4.0 or higher (for MP3 processing)

Install from Source

pip install -e .

Usage

Basic Usage

# Process a single file
loudness-normalizer music.flac

# Process a directory (recursive)
loudness-normalizer /path/to/music

# Process multiple paths
loudness-normalizer track1.flac track2.mp3 /music/album

Options

usage: loudness-normalizer [-h] [--version] [--target TARGET] [--force]
                           [--verbose] [--report REPORT]
                           path [path ...]

Tag FLAC and MP3 files with loudness normalization metadata.

positional arguments:
  path             Path to file or directory to process

options:
  -h, --help       Show help message and exit
  --version        Show program version and exit
  --target TARGET  Target LUFS (default: -20)
  --force          Recalculate and overwrite existing tags
  --verbose        Show detailed per-file information
  --report REPORT  Generate JSON report to specified file

Examples

# Use custom target LUFS
loudness-normalizer --target -16 music/

# Force re-tagging of all files
loudness-normalizer --force music/

# Generate a JSON report
loudness-normalizer --report report.json music/

# Verbose output with custom target
loudness-normalizer --verbose --target -18 music.flac

Tag Formats

FLAC (R128_TRACK_GAIN)

  • Storage: Vorbis Comment
  • Format: Q7.8 fixed-point integer (string representation)
  • Unit: 1/256 LU (256 = 1 dB)
  • Example: -1536 corresponds to -6 dB gain

MP3 (ReplayGain)

  • Storage: ID3v2 TXXX frame
  • REPLAYGAIN_TRACK_GAIN: String "-X.XX dB"
  • REPLAYGAIN_TRACK_PEAK: Linear amplitude (0-1)

Player Compatibility

Generated tags are compatible with:

  • VLC
  • Poweramp
  • foobar2000
  • Other players supporting R128/ReplayGain

Development

Running Tests

# Run all tests
pytest tests/

# Run with coverage
pytest tests/ --cov=src/loudness_normalizer --cov-report=term-missing

Project Structure

loudness-normalizer/
├── src/
│   └── loudness_normalizer/
│       ├── __init__.py
│       ├── __main__.py      # Entry point
│       ├── cli.py           # CLI interface
│       ├── lufs.py          # LUFS measurement
│       ├── gain.py          # Gain calculation
│       ├── tagger.py        # Metadata tagging
│       ├── scanner.py       # File scanning
│       ├── processor.py     # Main processing
│       └── report.py        # Report generation
├── tests/
│   ├── conftest.py          # Test fixtures
│   ├── test_gain.py
│   ├── test_lufs.py
│   ├── test_tagger.py
│   ├── test_scanner.py
│   ├── test_processor.py
│   ├── test_cli.py
│   └── test_integration.py
├── specs/
│   └── loudness-normalizer.md
├── pyproject.toml
└── README.md

License

MIT License