ffmpeg-normalize

repository·master·Indexed 23 days ago

https://github.com/slhck/ffmpeg-normalize

A utility for batch-normalizing audio using ffmpeg, available via CLI or Python API. It supports EBU R128 loudness normalization (automating the two-pass linear process), RMS-based normalization, and peak normalization. Features include predefined presets (podcast, music, streaming-video), batch/album processing to preserve relative loudness, ReplayGain tag writing, and support for preserving input bit depth and modification times.

Tokens
15.9K
Snippets
53
Records
109
Agent score
80%

What's inside ffmpeg-normalize

  1. Skip files already at target level

    master

    To avoid unnecessary re-encoding, you can use the --threshold option. If a file's loudness is already within the specified threshold of the target level, it will be copied through unchanged instead of being re-encoded.

    When using --print-stats, the output will include a status field for each file: normalized, skipped, or error.

  2. How output audio codecs are chosen

    master

    The program automatically selects an audio codec based on the output container:

    • Uncompressed containers (e.g., WAV, MKV, MOV): Uses PCM audio, matching the input bit depth. This is lossless but results in larger files.
    • Compressed containers (e.g., MP3, MP4/M4A, FLAC, Ogg, Opus, WebM): Uses the same default codec that ffmpeg itself would pick for that container. You do not need to specify a codec manually for these containers.
  3. How the output audio codec is chosen

    master

    If you do not explicitly set the audio codec using -c:a / --audio-codec, ffmpeg-normalize selects a codec based on the output container:

    • PCM-capable containers (e.g., WAV, MKV, MOV): Uses PCM audio, matching the input bit depth (lossless).
    • Non-PCM containers (e.g., MP3, MP4/M4A, FLAC, Ogg, Opus, WebM): Uses the default codec that your specific ffmpeg build would pick for that container.

    Common defaults:

    • .mp3 $\rightarrow$ libmp3lame (MP3)
    • .m4a / .mp4 $\rightarrow$ AAC
    • .flac $\rightarrow$ FLAC
    • .opus $\rightarrow$ libopus (Opus)

    To avoid generation loss, use a PCM-capable container or a lossless codec like FLAC. You can override the default by explicitly setting -c:a (e.g., -c:a libvorbis).

  4. Understand EBU R128 Linear vs Dynamic mode

    master

    EBU R128 is a loudness normalization method based on Integrated Loudness (I), Loudness Range (LRA), and True Peak (TP).

    • Linear mode: Applies a constant gain adjustment across the entire file. It is recommended for most cases because it preserves the original dynamic range and avoids artifacts like pumping.
    • Dynamic mode: Changes volume dynamically throughout the file. This can achieve more consistent loudness but may alter the artistic intent.

    When does dynamic mode occur? ffmpeg-normalize (via ffmpeg's loudnorm filter) may automatically switch to dynamic mode if:

    1. The input LRA is larger than the target LRA.
    2. The required gain to reach the target loudness would cause the True Peak to exceed the specified limit.

    To maximize the chance of staying in linear mode, use these mitigation flags:

    • --keep-loudness-range-target: Sets the target LRA to the input file's measured LRA.
    • --keep-lra-above-loudness-range-target: Only adjusts the target LRA if the input LRA is above the target.
    • --auto-lower-loudness-target: Automatically lowers the integrated loudness target to prevent True Peak violations.
    • --lower-only: Skips normalization if the measured loudness is already lower than the target.
  5. Apply audio filters with ffmpeg-normalize

    master

    You can modify the audio signal before or after the normalization process using FFmpeg audio filters. This is controlled via two CLI options:

    • -prf or --pre-audio-filter: Applies the filter(s) before normalization.
    • -pof or --post-audio-filter: Applies the filter(s) after normalization.

    The syntax for these options must follow the standard FFmpeg filter string format. You can chain multiple filters together using commas (e.g., filter1,filter2). For a complete list of available filters, refer to the FFmpeg audio filters documentation.

  6. How ffmpeg-normalize automates EBU R128 linear normalization

    master

    While you can run loudnorm directly in ffmpeg, a single-pass loudnorm uses dynamic mode by default, which applies compression and alters audio dynamics.

    To achieve linear normalization (constant gain adjustment that preserves dynamics) using raw ffmpeg, you must perform two passes:

    1. A first pass to measure loudness, range, true peak, and threshold.
    2. A second pass feeding those values back with linear=true.

    ffmpeg-normalize automates this entire two-pass process and handles edge cases like adjusting target LRA and loudness to prevent silent fallback to dynamic mode.

  7. Understand normalization algorithms: EBU R128, Peak, and RMS

    master

    The tool supports several normalization methods:

    • EBU R128: An industry standard for broadcasting. It uses a psychoacoustic model to target a subjective loudness level measured in LUFS. It is more subjectively accurate than peak or RMS methods.
    • Peak Normalization: Analyzes the peak signal level in dBFS and increases volume so the maximum output is 0 dB (or a specified threshold). This can result in files that feel quieter if the signal has significant spikes.
    • RMS-based Normalization: Analyzes the Root Mean Square (RMS) power of the signal and adjusts volume to reach a target RMS level. It functions similarly to peak normalization but targets average power.
  8. Use Batch Mode for Albums

    master

    When processing a group of files that belong together (like an album), use --batch to preserve their relative loudness. Instead of making every track hit the same absolute target, it calculates a single adjustment based on the average loudness of the group and applies relative adjustments to each file.

    Note: For music albums, rms or peak normalization is generally recommended over ebu when using batch mode.

    ffmpeg-normalize album/*.flac --batch -nt rms -t -20
  9. Install ffmpeg on Linux

    master

    While distribution packages (like apt install ffmpeg) are available, they are often outdated and not recommended. It is better to use a static build.

    To install using a static build from johnvansickle.com:

    wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz
    mkdir -p ffmpeg
    tar -xf ffmpeg-release-amd64-static.tar.xz -C ffmpeg --strip-components=1
    sudo cp ffmpeg/ffmpeg /usr/local/bin
    sudo cp ffmpeg/ffprobe /usr/local/bin
    sudo chmod +x /usr/local/bin/ffmpeg /usr/local/bin/ffprobe
  10. Install and Quick Start ffmpeg-normalize

    master

    To use ffmpeg-normalize, you must have a recent version of ffmpeg and Python 3.10 or higher installed on your system.

    You can install the package via pip or run it directly using uvx.

    By default, the normalized file will be saved in a normalized/ directory relative to your input file.

    # Using pip
    pip3 install ffmpeg-normalize
    ffmpeg-normalize /path/to/your/file.mp4
    
    # Using uv
    uvx ffmpeg-normalize /path/to/your/file.mp4
  11. Install Zsh shell completions

    master

    To install completions for Zsh, download the script into your $FPATH directory (the default is /usr/local/share/zsh/site-functions/).

    Note: Ensure your .zshrc file contains autoload -Uz compinit && compinit for completions to function.

    curl -L https://raw.githubusercontent.com/slhck/ffmpeg-normalize/master/completions/ffmpeg-normalize.zsh \
      -o /usr/local/share/zsh/site-functions/