Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add linear loudnorm option to set lra up to target, then keep input lra #229

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,13 @@ Some containers (like MP4) also cannot handle PCM audio. If you want to use such

- `--keep-loudness-range-target`: Keep the input loudness range target to allow for linear normalization.

- `--keep-lra-above-loudness-range-target`: Keep input loudness range above loudness range target.

- `LOUDNESS_RANGE_TARGET` for input loudness range `<= LOUDNESS_RANGE_TARGET` or
- keep input loudness range target above `LOUDNESS_RANGE_TARGET`.

as alternative to `--keep-loudness-range-target` to allow for linear normalization.

- `-tp TRUE_PEAK, --true-peak TRUE_PEAK`: EBU Maximum True Peak in dBTP (default: -2.0).

Range is -9.0 - +0.0.
Expand Down
14 changes: 14 additions & 0 deletions ffmpeg_normalize/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,19 @@ def create_parser() -> argparse.ArgumentParser:
),
)

group_ebu.add_argument(
"--keep-lra-above-loudness-range-target",
action="store_true",
help=textwrap.dedent(
"""\
Keep input loudness range above loudness range target.
- `LOUDNESS_RANGE_TARGET` for input loudness range `<= LOUDNESS_RANGE_TARGET` or
- keep input loudness range target above `LOUDNESS_RANGE_TARGET`.
as alternative to `--keep-loudness-range-target` to allow for linear normalization.
"""
),
)

group_ebu.add_argument(
"-tp",
"--true-peak",
Expand Down Expand Up @@ -486,6 +499,7 @@ def _split_options(opts: str) -> list[str]:
loudness_range_target=cli_args.loudness_range_target,
# threshold=cli_args.threshold,
keep_loudness_range_target=cli_args.keep_loudness_range_target,
keep_lra_above_loudness_range_target=cli_args.keep_lra_above_loudness_range_target,
true_peak=cli_args.true_peak,
offset=cli_args.offset,
dual_mono=cli_args.dual_mono,
Expand Down
10 changes: 10 additions & 0 deletions ffmpeg_normalize/_ffmpeg_normalize.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class FFmpegNormalize:
print_stats (bool, optional): Print loudnorm stats. Defaults to False.
loudness_range_target (float, optional): Loudness range target. Defaults to 7.0.
keep_loudness_range_target (bool, optional): Keep loudness range target. Defaults to False.
keep_lra_above_loudness_range_target (bool, optional): Keep input loudness range above loudness range target. Defaults to False.
true_peak (float, optional): True peak. Defaults to -2.0.
offset (float, optional): Offset. Defaults to 0.0.
dual_mono (bool, optional): Dual mono. Defaults to False.
Expand Down Expand Up @@ -89,6 +90,7 @@ def __init__(
# threshold=0.5,
loudness_range_target: float = 7.0,
keep_loudness_range_target: bool = False,
keep_lra_above_loudness_range_target: bool = False,
true_peak: float = -2.0,
offset: float = 0.0,
dual_mono: bool = False,
Expand Down Expand Up @@ -147,6 +149,14 @@ def __init__(
"Remove --keep-loudness-range-target or remove the --lrt/--loudness-range-target option."
)

self.keep_lra_above_loudness_range_target = keep_lra_above_loudness_range_target

if self.keep_loudness_range_target and self.keep_lra_above_loudness_range_target:
raise FFmpegNormalizeError(
"Options --keep-loudness-range-target and --keep-lra-above-loudness-range-target are partially contradictory! "
"Please choose just one of the two options"
)

self.true_peak = check_range(true_peak, -9, 0, name="true_peak")
self.offset = check_range(offset, -99, 99, name="offset")

Expand Down
16 changes: 15 additions & 1 deletion ffmpeg_normalize/_streams.py
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,19 @@ def get_second_pass_opts_ebu(self) -> str:
self.loudness_statistics["ebu"]["input_lra"]
)

if self.media_file.ffmpeg_normalize.keep_lra_above_loudness_range_target:
if self.loudness_statistics["ebu"]["input_lra"] <= self.media_file.ffmpeg_normalize.loudness_range_target:
_logger.debug(
"Setting loudness range target in second pass loudnorm filter"
)
else:
self.media_file.ffmpeg_normalize.loudness_range_target = (
self.loudness_statistics["ebu"]["input_lra"]
)
_logger.debug(
"Keeping target loudness range in second pass loudnorm filter"
)

if (
self.media_file.ffmpeg_normalize.loudness_range_target
< self.loudness_statistics["ebu"]["input_lra"]
Expand All @@ -420,7 +433,8 @@ def get_second_pass_opts_ebu(self) -> str:
f"Input file had loudness range of {self.loudness_statistics['ebu']['input_lra']}. "
f"This is larger than the loudness range target ({self.media_file.ffmpeg_normalize.loudness_range_target}). "
"Normalization will revert to dynamic mode. Choose a higher target loudness range if you want linear normalization. "
"Alternatively, use the --keep-loudness-range-target option to keep the target loudness range from the input."
"Alternatively, use the --keep-loudness-range-target or --keep-lra-above-loudness-range-target option to keep the target loudness range from "
"the input."
)
will_use_dynamic_mode = True

Expand Down