From ccfaeff143bba1fa620d77a032e2edf8039c3e22 Mon Sep 17 00:00:00 2001 From: pat-e Date: Mon, 22 Sep 2025 08:16:17 +0200 Subject: [PATCH] Replacement of the audio normalization in mkvopusenc --- MkvOpusEnc.py | 23 +++++++++++++++++++---- README_MkvOpusEnc.md | 3 +-- README_av1_opus_encoder.md | 1 - 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/MkvOpusEnc.py b/MkvOpusEnc.py index 3e2fec1..8b72afe 100644 --- a/MkvOpusEnc.py +++ b/MkvOpusEnc.py @@ -32,7 +32,7 @@ class Tee: def check_tools(): """Checks if all required command-line tools are in the system's PATH.""" - required_tools = ["ffmpeg", "ffprobe", "mkvmerge", "sox_ng", "opusenc", "mediainfo"] + required_tools = ["ffmpeg", "ffprobe", "mkvmerge", "opusenc", "mediainfo"] print("--- Prerequisite Check ---") all_found = True for tool in required_tools: @@ -78,9 +78,24 @@ def convert_audio_track(stream_index, channels, temp_dir, source_file, should_do ffmpeg_args.extend(["-c:a", "flac", str(temp_extracted)]) run_cmd(ffmpeg_args) - # Step 2: Normalize the track with SoX - print(" - Normalizing with SoX...") - run_cmd(["sox_ng", "--show-progress", str(temp_extracted), str(temp_normalized), "--temp", str(temp_dir), "loudness", "-18"]) + # Step 2: Normalize the track with ffmpeg's loudnorm (2-pass) + print(" - Normalizing with ffmpeg (loudnorm 2-pass)...") + # First pass: Analyze the audio to get loudnorm stats + print(" - Pass 1: Analyzing...") + result = subprocess.run( + ["ffmpeg", "-v", "info", "-i", str(temp_extracted), "-af", "loudnorm=I=-14:LRA=7:tp=-1:print_format=json", "-f", "null", "-"], + capture_output=True, text=True, check=True) + stats_lines = result.stderr.strip().split('\n') + stats_json_str = "".join(stats_lines[-12:]) # The JSON block is the last 12 lines + stats = json.loads(stats_json_str) + + # Second pass: Apply the normalization using the stats from the first pass + print(" - Pass 2: Applying normalization...") + run_cmd([ + "ffmpeg", "-v", "quiet", "-stats", "-y", "-i", str(temp_extracted), "-af", + f"loudnorm=I=-14:LRA=7:tp=-1:measured_i={stats['input_i']}:measured_lra={stats['input_lra']}:measured_tp={stats['input_tp']}:measured_thresh={stats['input_thresh']}:offset={stats['target_offset']}", + "-c:a", "flac", str(temp_normalized) + ]) # Step 3: Encode to Opus with the correct bitrate bitrate = "192k" # Fallback diff --git a/README_MkvOpusEnc.md b/README_MkvOpusEnc.md index 9a844d0..d057a62 100644 --- a/README_MkvOpusEnc.md +++ b/README_MkvOpusEnc.md @@ -12,7 +12,7 @@ * Re-encodes all other audio formats (DTS, AC3, TrueHD, FLAC, etc.) to Opus. * **Advanced Downmixing:** Includes an optional `--downmix` flag that converts multi-channel audio (5.1, 7.1) to stereo using a dialogue-boosting formula. * **Audio Normalization:** Uses `SoX` to normalize audio levels for a consistent listening experience. -* **Metadata Preservation:** Carefully preserves audio track metadata such as titles, language tags, and delay/sync information. +* **Audio Normalization:** Uses `ffmpeg`'s two-pass `loudnorm` filter (EBU R 128) to normalize audio levels for a consistent listening experience. * **Detailed Logging:** Creates a separate, detailed log file for each processed MKV in the `conv_logs/` directory, capturing the full terminal output and conversion details for easy review. * **File Organization:** Automatically moves the original source files to an `original/` directory and the newly processed files to a `completed/` directory, keeping your workspace clean. * **Cross-Platform:** As a Python script using common command-line tools, it is designed to work on Windows, macOS, and Linux. @@ -24,7 +24,6 @@ The following command-line tools must be installed and available in your system' * `ffmpeg` * `ffprobe` * `mkvmerge` -* `sox_ng` * `opusenc` * `mediainfo` diff --git a/README_av1_opus_encoder.md b/README_av1_opus_encoder.md index 90b3e86..7c6493c 100644 --- a/README_av1_opus_encoder.md +++ b/README_av1_opus_encoder.md @@ -24,7 +24,6 @@ The following command-line tools must be installed and available in your system' * `ffprobe` * `mkvmerge` * `mkvpropedit` -* `sox_ng` * `opusenc` * `mediainfo` * `av1an`