slhck / ffmpeg-normalize

Audio Normalization for Python/ffmpeg
MIT License
1.25k stars 117 forks source link

4.1 Dolby Surround is louder on the right side. #264

Closed joshinils closed 1 month ago

joshinils commented 3 months ago

The original is fine when played back in my stereo headphones with VLC, the normalized is not – it is louder on my right side.

I have a rare file which is encoded like this: original mediainfo

Audio #1
ID                                       : 2
ID in the original source medium         : 189 (0xBD)128 (0x80)
Format                                   : AC-3
Format/Info                              : Audio Coding 3
Commercial name                          : Dolby Digital
Codec ID                                 : A_AC3
Duration                                 : 1 h 54 min
Bit rate mode                            : Constant
Bit rate                                 : 384 kb/s
Channel(s)                               : 5 channels
Channel layout                           : L R C LFE Cb
Sampling rate                            : 48.0 kHz
Frame rate                               : 31.250 FPS (1536 SPF)
Compression mode                         : Lossy
Stream size                              : 315 MiB (5%)
Title                                    : Surround 4.1
Language                                 : English
Service kind                             : Complete Main
Default                                  : Yes
Forced                                   : No

original ffprobe

  Stream #0:1(eng): Audio: ac3, 48000 Hz, 4.1, fltp, 384 kb/s (default)
    Metadata:
      title           : Surround 4.1
      BPS-eng         : 384000
      DURATION-eng    : 01:54:45.088000000
      NUMBER_OF_FRAMES-eng: 215159
      NUMBER_OF_BYTES-eng: 330484224
      SOURCE_ID-eng   : 0180BD
      _STATISTICS_WRITING_APP-eng: MakeMKV v1.17.7 linux(x64-release)
      _STATISTICS_WRITING_DATE_UTC-eng: 2024-06-30 11:19:27
      _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES SOURCE_ID

normalized mediainfo:

Audio #1
ID                                       : 2
Format                                   : Opus
Codec ID                                 : A_OPUS
Duration                                 : 1 h 54 min
Bit rate                                 : 179 kb/s
Channel(s)                               : 5 channels
Channel layout                           : L R Lb Rb LFE
Sampling rate                            : 48.0 kHz
Frame rate                               : 50.000 FPS (960 SPF)
Bit depth                                : 32 bits
Compression mode                         : Lossy
Stream size                              : 147 MiB (2%)
Title                                    : Surround 4.1
Language                                 : English
Default                                  : No
Forced                                   : No

normalized ffprobe:

  Stream #0:1(eng): Audio: opus, 48000 Hz, 5.0, fltp
    Metadata:
      title           : Surround 4.1
      BPS             : 179146
      DURATION        : 01:54:45.108000000
      NUMBER_OF_FRAMES: 344255
      NUMBER_OF_BYTES : 154180617
      _STATISTICS_WRITING_APP: mkvmerge v84.0 ('Sleeper') 64-bit
      _STATISTICS_WRITING_DATE_UTC: 2024-07-04 23:44:16
      _STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES

this is the command my script used:

['ffmpeg-normalize', '-pr', '-f', '-ar', '48000', '-c:a', 'libopus', '-b:a', '192000', 'input.mkv '-o', 'normalized_temp/input.mkv', '-e', '-ac 5 -dsurex_mode 1']
ffmpeg-normalize -pr -f -ar 48000 -c:a libopus -b:a 192000 "input.mkv" -o "normalized_temp/input.mkv.normalized.mkv -e -ac 5 -dsurex_mode 1"

The problem is that the output is 5.0 instead of 4.1, the input Channel layout is "L R C LFE Cb" the output is "L R Lb Rb LFE" which is the same amount, but the wrong channel layout.

I've tried appending a -af channelmap=channel_layout=4.1 to the above command. But that led to this error message:

Filtergraph 'channelmap=channel_layout=4.1' was specified through the -vf/-af/-filter option for output stream 0:1, which is fed from a complex filtergraph.
-vf/-af/-filter and -filter_complex cannot be used together for the same stream.

I've tried swapping the channels from the above normalized output;

ffmpeg -i input_normalized.kmv -filter_complex "[0:a]channelmap=channel_layout=5.0:map=FL-FL|FR-FR|FC-FC|BL-LFE|BR-BC[out]" -map "[out]" out.mka

that is better, but also wrong.

What can I do to correctly normalize this file?

slhck commented 3 months ago

You can't pass -af through extra options because ffmpeg-normalize internally sets up a complex filtergraph, and any addition to that would have to be made through the --pre-filter and --post-filter options.

Also, didn't we have a discussion about opus not supporting surround sound properly? https://github.com/slhck/ffmpeg-normalize/issues/237#issuecomment-1580288823

I think it would make sense to first try to reproduce the issue with raw ffmpeg commands, just to figure out what is actually going on. In other words, when you manually run your input file through ffmpeg and re-encode, can you get it to output the correct channel map (without normalizing anything)? Once you have that figured out, what happens when you apply the normalization manually, i.e., run it once with the loudnorm filter?

Because the processing pipeline in ffmpeg-normalize is more or less static, it's going to be hard to accommodate all these special cases. Especially when ffmpeg doesn't output properties similar to its input, it's going to be even more effort …

joshinils commented 3 months ago

Also, didn't we have a discussion about opus not supporting surround sound properly? #237 (comment)

Specifically, opus was the problem there, not libopus.

joshinils commented 3 months ago

I think it would make sense to first try to reproduce the issue with raw ffmpeg commands, just to figure out what is actually going on. In other words, when you manually run your input file through ffmpeg and re-encode, can you get it to output the correct channel map (without normalizing anything)?

Yeah, this isn't an issue with ffmpeg-normalize, but the regular ffmpeg. It just doesn't seem to "understand" that the input 4.1 is not the same as what I want it to also output as 4.1, it also re-organizes the channels the same way as above. I don't know how to tell it what I want it to do. ffmpeg -layouts spits out one 4.1 mapping: 4.1 FL+FR+FC+LFE+BC which is what the input is, but ffmpeg only produces Channel layout : L R Lb Rb LFE. No matter what I specify, for example ffmpeg -i input.mkv -map 0:a:0 -c:a libopus -filter_complex "channelmap=channel_layout=4.1:map=FL-FL|FR-FR|FC-FC|LFE-LFE|BC-BC[out]" -map "[out]" -ac 5 out.mka -y, the output has a different mapping, which I do not understand.

joshinils commented 1 month ago

See section 5.1.1.2 in https://www.rfc-editor.org/rfc/rfc7845.html#section-5.1.1.2

5 channels: 5.0 surround (front left, front center, front right, rear left, rear right).

meaning Opus can not produce 4.1 audio.