Professional audio normalization system for performers, DJ's and sound designers. Normalises audio files to a consistent -12 LUFS loudness for punchy playback on high-quality sound systems with good headroom for effects and layers. Never fiddle with trim again...
- Consistent Loudness: Normalizes all tracks to -12 LUFS using EBU R128 standard
- Five Output Formats: Lossless AIFF (default), FLAC, WAV — or lossy MP3/AAC at 320/256/192 kbps
- Two Modes: Manual batch processing or automatic folder watching
- Preserves Originals: Never modifies source files
- Lossless stays lossless: A lossless source keeps its own sample rate and full 24-bit depth — nothing is re-compressed and nothing is resampled unless the source is above 48 kHz (see Sample rate)
- Zero Quality Loss: No compression on lossless files, just loudness normalization
- Club Friendly: Know exactly what Pioneer/AlphaTheta gear your files will work on
- Format Support: M4A, WAV, FLAC, MP3, AIFF, OGG
Grab the GUI app for your platform from the releases page. Python and ffmpeg are bundled inside.
macOS (VTNormal-macos.zip)
One download, runs natively on both Apple Silicon and Intel.
- Unzip and drag VTNormal.app to your Applications folder.
- Do this BEFORE opening it for the first time. Open Terminal, paste this
whole line, press Return:
codesign --force --deep -s - /Applications/VTNormal.app && xattr -rd com.apple.quarantine /Applications/VTNormal.app - Open App by double-clicking, now and forever after.
Order matters.
If you open it first and get blocked, running the command afterwards does not clear the Mac's annoying Nanny nonsense. If that happens, go to System Settings → Privacy & Security, scroll down, and choose Open Anyway, then Open Anyway again in the pop-up. If you run the Terminal line first, you skip all this.
Why the Terminal step?
Removing that warning permanently means paying Apple $99/year for a Developer ID. This app is free, so it borrows the same approach Radarr, Sonarr and friends use: you sign it yourself, locally and in one command it re-signs the app with your own machine's ad-hoc signature and clears the "scary file downloaded from the internet" quarantine flag. Nothing is sent anywhere and the app source code can be dumped into any LLM to check for hidden threats.
Windows (VTNormal-windows.zip):
- Unzip the whole folder somewhere (keep the files together).
- Double-click
VTNormal.exe. If SmartScreen objects, click More info → Run anyway (needed once only).
- Python 3.7+
- ffmpeg (for audio processing)
- Auto-watch daemon mode: macOS or Linux only (the installer script uses
launchd, so it's macOS; on Linux run
watcher.pyunder systemd or similar)
brew install ffmpeggit clone https://github.com/psi-i-am/audio-normalisation.git
cd audio-normalisationpip3 install -r requirements.txtInteractive mode that prompts for source and destination folders. Perfect for batch processing.
python3 normalize.pyYou'll be prompted for:
- Source path: Single file or folder with audio files
- Destination folder: Where normalized files will be saved
The script will:
- Scan for supported audio files
- Show preview and ask for confirmation
- Display progress bar during processing
- Show summary with success/failure counts
Example:
$ python3 normalize.py
Enter source path (file or folder): ~/Music/DJ/New-Tracks
Enter destination folder: ~/Music/DJ/Normalized
Found 15 audio file(s)
Files to process (showing first 5):
- track01.m4a
- track02.wav
- track03.flac
- track04.mp3
- track05.aiff
... and 10 more
Proceed with normalization? (y/n): y
Processing: 100%|██████████| 15/15 [05:23<00:00]
SUMMARY
Total files: 15
Successful: 15
Failed: 0
Time elapsed: 5.4m
Automatically monitors a folder and normalizes any new audio files that appear.
Any folder works — local, external drive, or a cloud-synced one like Dropbox
(handy for dropping in purchases from your phone). macOS/Linux only — the
install_daemon.sh installer is macOS (launchd); on Linux run watcher.py
as a service yourself (e.g. systemd).
Configuration:
Edit config.json to set your folders:
{
"watch_folder": "/path/to/your/watch/folder",
"destination_folder": "/path/to/your/output/folder",
"target_lufs": -12,
"output_format": "aiff",
"bitrate": 320
}Install daemon:
bash install_daemon.shThe daemon will:
- Start automatically at login
- Watch the configured folder continuously
- Process new files immediately (after a 2-second debounce so files still arriving via cloud sync are complete)
- Log all activity to
~/Library/Logs/audio-normalizer.log - Auto-restart if it crashes
Check daemon status:
launchctl list | grep audiotoolsView logs:
# Live tail
tail -f ~/Library/Logs/audio-normalizer.log
# View errors
cat ~/Library/Logs/audio-normalizer-error.logUninstall daemon:
bash uninstall_daemon.shThe tool uses ffmpeg's loudnorm filter with a two-pass process for accurate loudness normalization:
-
Pass 1 (Analysis): Measures current loudness levels
- Integrated loudness (LUFS)
- Loudness range (LRA)
- True peak (TP)
-
Pass 2 (Normalization): Applies precise gain adjustment
- Uses measurements from pass 1
- Normalizes to -12 LUFS target
- Prevents clipping with -1.5 dB true peak limit
- Outputs lossless AIFF (default) or FLAC with maximum compression
- Matches modern commercial dance music masters
- Hot enough for club systems without distortion
- Provides good headroom for system dynamics
- Consistent with streaming platform standards
Five output formats are available in every mode (CLI menu, GUI FORMAT/BITRATE
buttons, output_format + bitrate in config.json).
Output keeps the source's own sample rate, up to 48 kHz. A 44.1 kHz track stays 44.1 kHz; a 48 kHz master stays 48 kHz. Only sources above 48 kHz (88.2 / 96 kHz) are resampled, and then down to 48 kHz rather than 44.1.
48 kHz is the ceiling because it is the highest rate every Pioneer/AlphaTheta player accepts. Verified per model (Aug 2026): CDJ-350, CDJ-850, CDJ-900, CDJ-2000, CDJ-2000NXS, XDJ-700, XDJ-1000/MK2 and XDJ-XZ all top out at 48 kHz for WAV/AIFF. Only CDJ-3000, CDJ-2000NXS2 and Opus Quad read 88.2/96 kHz — so capping at 48 kHz means every file this tool writes plays on all of them.
| Format | Type | Bitrate | Pioneer support |
|---|---|---|---|
| AIFF (default) | Lossless, uncompressed 24-bit | — | ALL CDJ/XDJ gear |
| WAV | Lossless, uncompressed 16-bit | — | ALL CDJ/XDJ gear |
| FLAC | Lossless, compressed 24-bit (much smaller) | — | Newer gear only |
| MP3 | Lossy (libmp3lame, ID3v2.3) | 320/256/192 kbps | ALL CDJ/XDJ gear |
| AAC (.m4a) | Lossy (better than MP3 at same bitrate) | 320/256/192 kbps | Most modern gear |
AIFF & WAV - Universal & Top Quality
Lossless and universally supported on all Pioneer/Alpha-Theta and most good brands gear (Denon etc) AIFF supports 24 bit and album art. Large files. WAV supports 16 bit and does not support album art. Slightly smaller files.
FLAC — Supported on Newer Gear
Lossless, supports album art and smaller than AIFF & WAV. CDJ-3000, CDJ-2000NXS2, CDJ-TOUR1, XDJ-1000MK2, XDJ-RX2, XDJ-RX3, XDJ-XZ, XDJ-AZ, Opus Quad, Omnis Duo (and newer).
FLAC — NOT supported:
CDJ-2000NXS and older, CDJ-900/900NXS, CDJ-850, CDJ-350, XDJ-700, XDJ-1000 (mk1), XDJ-RX (mk1), XDJ-RR.
AAC — Better Lossy codec. Supported on Post-CD, USB capable Gear
Lossy but better than MP3 at the same bitrates. All modern players (CDJ-350/850/900/2000 onward and every XDJ). Only ancient CD-only decks (CDJ-800/1000 etc.) can't read it.
MP3 - Universal & Lossy
The Universal lossy format. Good at high bitrates, supports album art. Plays everywhere.
Why 16-bit WAV?
ffmpeg writes 24-bit WAV with a WAVE_FORMAT_EXTENSIBLE header (wFormatTag 0xFFFE)
that some CDJ firmware rejects, and offers no way to suppress it. 16-bit WAV plays
everywhere; if you want 24-bit lossless, use AIFF (that's why it's the default).
Note WAV also cannot carry embedded cover art — use AIFF/FLAC to keep artwork.
WAV is therefore the one output format that cannot fully preserve a very high quality lossless source: the sample rate is kept, but bit depth drops to 16. AIFF and FLAC both keep the full 24 bits.
AAC encoder note:
On macOS the bundled/detected ffmpeg uses Apple's AudioToolbox encoder (aac_at),
which genuinely hits 320 kbps. ffmpeg's built-in aac encoder (used on Windows/Linux)
caps out around ~224 kbps for 44.1 kHz stereo even when 320 is requested.
audio-normalisation/
├── normalize.py # Manual mode script
├── normalizer.py # Core normalization engine
├── watcher.py # Auto-watch daemon
├── config.json # Daemon configuration
├── requirements.txt # Python dependencies
├── com.audiotools.normalizer.plist # launchd configuration
├── install_daemon.sh # Daemon installer
├── uninstall_daemon.sh # Daemon uninstaller
└── README.md # This file
Input formats:
- M4A (Apple AAC)
- WAV (Uncompressed)
- FLAC (Lossless)
- MP3 (Lossy)
- AIFF (Apple Uncompressed)
- OGG (Vorbis)
Output formats (CLI menu / GUI buttons / output_format in config.json):
- AIFF (lossless, uncompressed 24-bit — default)
- FLAC (lossless, compressed 24 bit)
- WAV (lossless, uncompressed 16-bit)
- MP3 (lossy, 320/256/192 kbps)
- AAC/.m4a (lossy, 320/256/192 kbps)
Install ffmpeg:
brew install ffmpegCheck error log:
cat ~/Library/Logs/audio-normalizer-error.logVerify paths in config.json exist and are correct
-
Check daemon is running:
launchctl list | grep audiotools -
Check file format is supported (case-sensitive extension)
-
Check logs for errors:
tail -50 ~/Library/Logs/audio-normalizer.log
The tool targets -12 LUFS. You can adjust by editing config.json:
{
"target_lufs": -11 // Louder: -11, -10, etc.
// Quieter: -13, -14, etc.
}Then restart daemon:
bash uninstall_daemon.sh
bash install_daemon.shCheck loudness of normalized file:
ffmpeg -i output.aiff -af loudnorm=print_format=summary -f null - 2>&1 | grep -A 12 "Parsed_loudnorm"Look for "Output Integrated" value - should be close to -12.0 LUFS.
- Batch process before gigs: Use manual mode to normalize your entire library
- Auto-process new purchases: Enable daemon to handle new tracks automatically
- Test on your system: Always audition normalized tracks on your DJ setup
- Keep originals: Never delete source files - normalized output is separate
- USB stick preparation: Copy normalized files to USB for CDJ/standalone gear
- Normalization standard: EBU R128 (ITU-R BS.1770)
- Target loudness: -12 LUFS (Loudness Units relative to Full Scale)
- True peak limit: -1.5 dB (prevents inter-sample peaks)
- Loudness range: 11 LU (preserves dynamics)
- Output formats: AIFF (24-bit PCM, default), FLAC, WAV (16-bit PCM), MP3, AAC
- FLAC compression: Level 8 (maximum, when FLAC selected)
- Lossy bitrates: 320 (default) / 256 / 192 kbps CBR
- Processing: Two-pass for accuracy
MIT License - Free to use for personal and commercial purposes. See LICENSE file for details.
This tool uses FFmpeg. When run from source you must have ffmpeg installed
separately (e.g. brew install ffmpeg). The distributable apps (see
packaging/) bundle a self-contained static GPLv3 build of FFmpeg; the GPL
license text and attribution travel inside each app's zip (a licenses folder).
FFmpeg source: https://ffmpeg.org/releases/ — builds with --enable-nonfree are
deliberately refused by the build scripts, as they are not redistributable.
For issues or questions, check the logs first:
~/Library/Logs/audio-normalizer.log~/Library/Logs/audio-normalizer-error.log
Issues and pull requests are welcome! This tool was created for professional party people. If you are in Johannesburg, look us up, come dance maybe even play. whysoserious.org
Cheers! 🎧🔊