Skip to content

Commit

Permalink
Implement --auto-lower-loudness-target
Browse files Browse the repository at this point in the history
  • Loading branch information
ahmetsait committed Dec 15, 2024
1 parent cfbc2bd commit c0923e8
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 1 deletion.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,12 @@ For more information on the options (`[options]`) available, run `ffmpeg-normali
If the measured loudness from the first pass is lower than the target loudness then normalization pass will be skipped for the measured audio source.
- `--auto-lower-loudness-target`: Automatically lower EBU Integrated Loudness Target.
Automatically lower EBU Integrated Loudness Target to prevent falling back to dynamic filtering.
Makes sure target loudness is lower than measured loudness minus peak loudness (input_i - input_tp) by a small amount.
- `--dual-mono`: Treat mono input files as "dual-mono".
If a mono file is intended for playback on a stereo system, its EBU R128 measurement will be perceptually incorrect. If set, this option will compensate for this effect. Multi-channel input files are not affected by this option.
Expand Down
15 changes: 15 additions & 0 deletions ffmpeg_normalize/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,20 @@ def create_parser() -> argparse.ArgumentParser:
),
)

group_ebu.add_argument(
"--auto-lower-loudness-target",
action="store_true",
help=textwrap.dedent(
"""\
Automatically lower EBU Integrated Loudness Target to prevent falling
back to dynamic filtering.
Makes sure target loudness is lower than measured loudness minus peak
loudness (input_i - input_tp) by a small amount.
"""
),
)

group_ebu.add_argument(
"--dual-mono",
action="store_true",
Expand Down Expand Up @@ -527,6 +541,7 @@ def _split_options(opts: str) -> list[str]:
true_peak=cli_args.true_peak,
offset=cli_args.offset,
lower_only=cli_args.lower_only,
auto_lower_loudness_target=cli_args.auto_lower_loudness_target,
dual_mono=cli_args.dual_mono,
dynamic=cli_args.dynamic,
audio_codec=cli_args.audio_codec,
Expand Down
3 changes: 3 additions & 0 deletions ffmpeg_normalize/_ffmpeg_normalize.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class FFmpegNormalize:
true_peak (float, optional): True peak. Defaults to -2.0.
offset (float, optional): Offset. Defaults to 0.0.
lower_only (bool, optional): Whether the audio should not increase in loudness. Defaults to False.
auto_lower_loudness_target (bool, optional): Automatically lower EBU Integrated Loudness Target.
dual_mono (bool, optional): Dual mono. Defaults to False.
dynamic (bool, optional): Dynamic. Defaults to False.
audio_codec (str, optional): Audio codec. Defaults to "pcm_s16le".
Expand Down Expand Up @@ -98,6 +99,7 @@ def __init__(
true_peak: float = -2.0,
offset: float = 0.0,
lower_only: bool = False,
auto_lower_loudness_target: bool = False,
dual_mono: bool = False,
dynamic: bool = False,
audio_codec: str = "pcm_s16le",
Expand Down Expand Up @@ -169,6 +171,7 @@ def __init__(
self.true_peak = check_range(true_peak, -9, 0, name="true_peak")
self.offset = check_range(offset, -99, 99, name="offset")
self.lower_only = lower_only
self.auto_lower_loudness_target = auto_lower_loudness_target

# Ensure library user is passing correct types
assert isinstance(dual_mono, bool), "dual_mono must be bool"
Expand Down
16 changes: 15 additions & 1 deletion ffmpeg_normalize/_streams.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,10 +481,24 @@ def get_second_pass_opts_ebu(self) -> str:
"Specify -ar/--sample-rate to override it."
)

target_level = self.ffmpeg_normalize.target_level
if self.ffmpeg_normalize.auto_lower_loudness_target:
safe_target = (
self.loudness_statistics["ebu_pass1"]["input_i"]
- self.loudness_statistics["ebu_pass1"]["input_tp"]
+ self.ffmpeg_normalize.true_peak
- 0.1
)
if safe_target < self.ffmpeg_normalize.target_level:
target_level = safe_target
_logger.warning(
f"Using loudness target {target_level} because --auto-lower-loudness-target given.",
)

stats = self.loudness_statistics["ebu_pass1"]

opts = {
"i": self.media_file.ffmpeg_normalize.target_level,
"i": target_level,
"lra": self.media_file.ffmpeg_normalize.loudness_range_target,
"tp": self.media_file.ffmpeg_normalize.true_peak,
"offset": self._constrain(
Expand Down

0 comments on commit c0923e8

Please sign in to comment.