Normalize the volume of .mkv, .mp4, .mov, or .avi files using ffmpeg's loudnorm filter. Great for watching shows without constantly adjusting the volume.Preserves video quality by copying video streams, speeds up reprocessing with cached loudness metadata, and uses parallelization to speed up processing.
- ๐ Recursively finds all supported media files under a given path
- ๐ Runs a loudness analysis pass on each media file (
input_i) - ๐ Cache analysis results to
.loudnorm.jsonfiles - ๐งฎ Calculates the average integrated loudness (LUFS)
- ๐งโโ๏ธ Only normalizes files that differ by more than 1 LUFS
- โก Runs analysis and normalization in parallel using
--threads - ๐ง Saves per-file JSON metadata to skip re-analysis unless
--reanalyzeis specified - ๐ Supports complex folder structures (e.g., Season folders)
- โ CLI flags for customization and automation
| Tool | Why it's needed | Install with |
|---|---|---|
| ffmpeg | Audio analysis + normalization | sudo apt install ffmpeg |
| bc | Decimal math for averaging and comparisons | sudo apt install bc |
| awk | Text processing and float math (built-in) | Usually preinstalled |
| grep | Extract values from ffmpeg output | Usually preinstalled |
| xargs | Trim whitespace from values | Usually preinstalled |
| find | Recursively locate .mkv files | Usually preinstalled |
Clone the repo and run:
chmod +x norm.sh
./norm.sh
## Usage
```bash
./norm.sh [options]| Flag | Description |
|---|---|
-p <path> |
Path to start scanning (default: .) |
--threads <n> |
Number of files to process in parallel (default: 1) |
--reanalyze |
Re-analyze loudness even if JSON metadata is present |
-y or --yes |
Skip confirmation prompt before normalization |
./norm.sh -p "/mnt/media/SHOW" --threads 4 --reanalyze -yThis will scan the following structure:
SHOW/
โโโ Season 1/
โ โโโ SHOW - S01E01 - EPISODE.mkv
โ โโโ SHOW - S01E02 - EPISODE.mkv
โโโ Season 2/
โ โโโ SHOW - S02E01 - EPISODE.mkv
โ โโโ ...
It recursively scans all subdirectories under the specified path to find valid media files (e.g., inside Season folders).
| File Path | Loudness |
-----------------------------------------------------------------
Average Files
'Season 1/Episode 1.mkv' | -21.00
'Season 1/Episode 2.mkv' | -21.50
Loud Files
'Season 1/Episode 3.mkv' | -15.00
Quiet Files
'Season 1/Episode 4.mkv' | -28.00Prompt:
Do you want to continue and edit the Loud and Quiet Files? [y/N]Each video gets a .loudnorm.json after analysis, for example:
Season 1/Episode 1.mkv.loudnorm.json
Metadata example:
{
"input_i" : "-22.30",
"input_tp" : "-1.10",
"input_lra" : "4.50",
"input_thresh" : "-32.00",
"target_offset" : "-1.70",
"normalized": true
}
- Finds all files matching allowed extensions (excluding
.loudnorm.json) - Uses
ffmpegwithloudnormto analyze volume, outputting JSON - Caches results in
filename.mkv.loudnorm.json - Calculates average LUFS across all files
- Normalizes only those with >1 LUFS deviation
- Writes new
-matched.mkvoutput file next to original - Marks normalized files in metadata
v1.0.0
Licensed under MIT. Contributions welcome!
1 FFmpeg Project
2 Inspiration from struggling to fall asleep to shows without constant remote volume adjustment. ๐บ