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

linear normalization with same configuration for input_LRA <1 and >7 #227

Closed
mjhalwa opened this issue Apr 16, 2023 · 9 comments
Closed
Assignees

Comments

@mjhalwa
Copy link
Contributor

mjhalwa commented Apr 16, 2023

Is your feature request related to a problem? Please describe.

Yes, I am currently using ffmpeg-normalize 1.26.4 in Python 3.10.9 with

from ffmpeg_normalize import FFmpegNormalize
normalizer = FFmpegNormalize(
        normalization_type="ebu",
        target_level=-23,
        print_stats=True,
        keep_loudness_range_target=True,  # needed for linear normalization
        true_peak=-2,
        dynamic=False,
        audio_codec=my_codec,
        audio_bitrate=my_bitrate,
        sample_rate=None,
        debug=True,
        progress=True,
    )
    normalizer.add_media_file(input_file, output_file)
    normalizer.run_normalization()

where 2nd runs with ffmpeg execute with lra={input_lra} which produces a linear normalized audio for any input_lra >= 1. If I try to convert a song with input_lra < 1 (e.g. 0.7 in audio from https://www.youtube.com/watch?v=HTYOa2_1aH4) I get the following error:

Value 0.700000 for parameter 'LRA' out of range [1 - 50]
Error setting option LRA to value 0.7.
Error initializing filter 'loudnorm' with args 'I=-23:TP=-2.0:LRA=0.7:measured_I=-12.7:measured_TP=-2.2:measured_LRA=0.7:measured_thresh=-22.7:offset=+0.1:linear=true:print_format=summary'
Error reinitializing filters!
Failed to inject frame into filter network: Result too large
Error while processing the decoded data for stream #0:0

I am able to resolve this issue by using loudness_range_target=7.0, instead of keep_loudness_range_target=True for any input_lra <= 7.0, but then get the following warning for input_lra > 7 (e.g. 16.10 in audio from https://www.youtube.com/watch?v=GibiNy4d4gc):

Input file had loudness range of 16.1. This is larger than the loudness range target (7.0). 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.
In dynamic mode, the sample rate will automatically be set to 192 kHz by the loudnorm filter. Specify -ar/--sample-rate to override it.

which does perform dynamic normalization instead of linear normalization.

Describe the solution you'd like

In order to solve this and ensure backwards compatibility I'd suggest to a add a flag --keep-lra-above-loudness-range-target (constructor parameter: keep_lra_above_loudness_range_target=True). In combination with loudness_range_target=7.0. This should ensure LRA=7 for input_lra <= 7 and LRA=input_lra for input_lra > 7 and allows to convert any song with the same parameter-set independent of input_lra

Describe alternatives you've considered

An alternative solution would be to set input_lra < 1 to LRA=1 in order to fit into the range of [1 - 50] with something like --force-linear-normalization

Without any change in ffmpeg_normalize I would need to measure input_lra in order to know what parameters to set, but then I can basically use ffmpeg directly without using ffmpeg_normalize at all.

Additional context

I am new to the topic of audio normalization, followed some tutorials and weblinks, played around with ffmpeg in order to achieve linear normalization, as I did not like how dynamic normalization changed the audio. I read that target_LRA should be 7.0 (EBU R128) and therefore used 7.0 when possible (so if input_lra < 7) and used LRA=input_lra for LRA > 7. Using --keep-loudness-range-target in ffmpeg_normalize seems to override --loudness-range-target = 7.0 and therefore only use LRA=7.0, if the input_lra is already 7.0. So I hope --keep-lra-above-loudness-range-target might be an improvement by respecting --loudness-range-target = 7.0 as long as possible.

@mjhalwa mjhalwa changed the title linear normalization with same configuration for <1 LRA and >7 LRA linear normalization with same configuration for input_LRA <1 and >7 Apr 16, 2023
@slhck
Copy link
Owner

slhck commented Apr 18, 2023

Thanks for this detailed description. I have to give it some thought … but wouldn't automatically setting measured_LRA to at least be 1 be simpler? Then users wouldn't have to specify extra flags. (I feel like we have a lot of flags already and they're getting quite confusing, even for me.)

@slhck slhck self-assigned this Apr 18, 2023
@slhck
Copy link
Owner

slhck commented Apr 18, 2023

Then again I do see your point. Would you like to file a PR for your new flag? I think if it's backwards compatible it's a good solution.

@mjhalwa
Copy link
Contributor Author

mjhalwa commented Apr 18, 2023

I can give it a try - probably additional rounding up to 1 is a good solution to allow both flags to work for a broad range of input_LRAs.

Just one question: I am wondering if there is a reason for ffmpeg_normalize currently only supporting linear normalization with unchanged LRA in the second run? I mean, is it sufficient to set LRA=7 in the first run or is it preferrable to set LRA=7 in the 2nd run or is LRA=7 actually not required to fullfill EBU R128

@slhck
Copy link
Owner

slhck commented Apr 19, 2023

I would probably just add a check before setting the opts here:

and output a warning if the loudness_range_target is below 1 (or above 50), saying that it was increased to 1 (or decreased to 50). That ensures we always produce a working command line. But I welcome a PR, since you also have the files to test with!

I believe that if you set LRA, you need to set it for the second run, since that will actually do the processing. The first run is only there to identify the properties of the file.

@mjhalwa
Copy link
Contributor Author

mjhalwa commented Apr 23, 2023

I forked your project's master branch at 7cd65d5 and tried and setup (for me I use a virtual environment with pipenv):

pipenv install
pipenv install --dev -r .\requirements.dev.txt

I just wanted to make sure, I am able to run everything and don't miss anything. So I tried to execute help with with pipenv run python -m ffmpeg_normalize -h - that worked. But runnint pytest with

pipenv run pytest .\test\test.py

seems to fail in 5 out of 25 tests.

➜ pipenv run pytest .\test\test.py
================================================= test session starts =================================================
platform win32 -- Python 3.11.0, pytest-7.3.1, pluggy-1.0.0
rootdir: C:\Daten\Git\ffmpeg-normalize
collected 25 items

test\test.py ......FFF.............FF.                                                                           [100%]

====================================================== FAILURES =======================================================
____________________________________________ TestFFmpegNormalize.test_peak ____________________________________________
# ...
=============================================== short test summary info ===============================================
FAILED test/test.py::TestFFmpegNormalize::test_peak - AssertionError: assert False
FAILED test/test.py::TestFFmpegNormalize::test_rms - AssertionError: assert False
FAILED test/test.py::TestFFmpegNormalize::test_ebu - AssertionError: assert False
FAILED test/test.py::TestFFmpegNormalize::test_pre_filters - AssertionError: assert False
FAILED test/test.py::TestFFmpegNormalize::test_post_filters - AssertionError: assert False
============================================ 5 failed, 20 passed in 22.67s ============================================

Do I miss something or is this currently fine?

@slhck
Copy link
Owner

slhck commented Apr 23, 2023

Could you please try to create a PR against this repository? I have automated tests that should ensure everything is fine.

@mjhalwa
Copy link
Contributor Author

mjhalwa commented Apr 23, 2023

If you like, I could also create a PR to silently set LRA to 1, if it is lower than 1 for --keep-loudness-range-target, in order to fix this flag too. Or would you like me to add it to the same PR?

@slhck
Copy link
Owner

slhck commented Apr 24, 2023

Fixed by c49480c.

@slhck
Copy link
Owner

slhck commented Apr 24, 2023

I added a constraint for the input LRA between 1 and 7 in 3187a02

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants