Opened 6 years ago

Last modified 7 months ago

#5718 open defect

ffmpeg not remapping channels for libopus automatically

Reported by: agressiv Owned by:
Priority: important Component: avcodec
Version: git-master Keywords: libopus regression
Cc: Michael Niedermayer,,,,, Blocked By:
Blocking: Reproduced by developer: yes
Analyzed by developer: no


[libopus @ 00000000026ad020] Invalid channel layout 5.1(side) for specified mapping family -1.

Summary of the bug:
Encode a 5.1 audio file with 5.1(side) channel map
How to reproduce:

% ffmpeg -i movie-with-51side.mkv -c:a libopus -b:a 256k output.mkv
ffmpeg version N-81025-g25ca74d
built on July 15 2016

ffmpeg version N-80101-gd970f7b automatically remapped these to the rear channels since libopus doesn't seem to allow side channels. I now have to explicitly add:

-af "channelmap=channel_layout=5.1"

Not sure if this is expected behavior or not. Without this channelmap, it aborts. Command-line opusenc automatically remaps as well.

Attachments (1)

0001-libavcodec-libopusenc.c-patch-channel_layouts-back-i.patch (939 bytes ) - added by Peter White 5 years ago.
Reenable channel_layouts

Download all attachments as: .zip

Change History (22)

comment:1 by Hendrik, 6 years ago

Probably a regression since 37941878f193a2316c514bd5ba55bfe9d2dfdfcf. Removing the supported channel_layouts from the codec definition was really not a good idea for on obscure feature.

comment:2 by James, 6 years ago

Component: undeterminedavcodec
Keywords: channelmap removed
Priority: normalimportant
Reproduced by developer: set
Status: newopen
Version: unspecifiedgit-master

Definitely a regression, and indeed started by 37941878f193a2316c514bd5ba55bfe9d2dfdfcf.

New defaults shouldn't make a simple "ffmpeg -i INPUT -c:a libopus OUTPUT" start failing.

Last edited 6 years ago by James (previous) (diff)

comment:3 by Carl Eugen Hoyos, 6 years ago

Keywords: regression added

comment:4 by Michael Niedermayer, 6 years ago

Cc: Michael Niedermayer added

comment:5 by Michael Graczyk, 6 years ago

When I wrote this patch, I did not realize that channel_layouts was used to automatically remix the channel layout from 5.1(side) to 5.1. I did not intend to change default behavior with that patch.

However, my understanding was that the error here is potentially desirable. The ogg audio stream in output.mkv has a different channel layout than the audio in the input file.

I see that in most cases remapping 5.1(side) to 5.1 is the right thing to do. Is there any way to get this automatic remapping only when the mapping_family parameter is not provided?

Also, what do you mean by "Command-line opusenc automatically remaps as well"? How do you process mkv files with opusenc? Are you sure the process used to extract audio from the mkv file didn't do the remapping?

comment:6 by agressiv, 6 years ago

I will pipe it from eac3to. opusenc can take piped input.

eac3to.exe source.mkv stdout.wav | opusenc.exe --bitrate 256k --ignorelength - out.opus
WARNING: WAV file uses side surround instead of rear for 5.1;
remapping side speakers to rear in encoding.
Encoding using libopus 1.1 (audio)

comment:7 by Michael Graczyk, 6 years ago

agressiv, thanks for that. I see that opusenc has a few special cases for moving rear to side and side to rear. I would have liked to preserve the behavior in this case as it was before 37941878f by default. I am hopeful we can restore this behavior without removing the mapping_family argument.

Would it make sense to add these special cases explicitly to libopusenc.c, and log a warning as is done by opusenc?

comment:8 by Hendrik, 6 years ago

I would prefer if opusenc had the channel_layouts setting again so that ffmpeg.c and other user apps know which layouts opus supports and can decide based on that which layout to use and potentially remix to, instead of hoping opusenc supports that internally.

channel_layouts is not only meant to limit the input to an encoder, its also information for the calling code so it can pick the best format on its own and not error out later.

comment:9 by Michael Graczyk, 6 years ago


libopusenc can accept many channel layouts that are not possible to express using the channel_layouts bitfield system. There are channel layouts which are supported by libopus which are not expressible by the channel_layouts member. I removed channel_layouts from the codec definition to prevent ffmpeg.c from halting with an error when one of these unexpressible layouts was passed in.

Is there a way to specify at the command line "no channel layout", or "unknown layout"? With such a flag, I could add channel_layouts back to libopusenc and also add code to handle the "no layout" case. I believe last time I asked about this, it was problematic because the channel count is represented by the popcount of the layout bitfield, and the "no channel layout" layout could have any channel count.

by Peter White, 5 years ago

Reenable channel_layouts

comment:10 by Peter White, 5 years ago

I just added a quick patch to get channel_layouts back. I just got bitten by this as well.

@mgraczyk I don't exactly understand what you are talking about when saying libopusenc can accept many inexpressible layouts. But is it more likely to encounter those than the most prominent ones, like 5.1(side)? I think for the time being, adding channel_layouts back in is the better compromise.

Anyway, the attached patch is there for anyone wanting to workaround this issue. To be honest, though, I did not check any implications, since I wouldn't know how, I am not a developer. But adding this one line back in seems easy enough. Correct me if I am wrong.

comment:11 by Peter White, 5 years ago

A more general workaround, without patching is to use the aformat filter, like i.e.:
ffmpeg -i surround_input -af aformat=channel_layouts="7.1|5.1|stereo" output.opus
This way one does not need to manually set an appropriate channel map with differing input layouts and channel numbers. Put this in a script and select the relevant layouts. The above example is just a quick one.

comment:12 by Federico, 4 years ago

The issue is still present in the latest nightly.
The only thing that seems to have been fixed is that all workarounds no longer work.

It's been almost TWO YEARS. This is a serious limitation!

comment:13 by Brasrok, 3 years ago

Just wanted to push this issue. As dosse91 wrote ealier, none of the workarounds work anymore and this is a serious limitation, guys.

comment:14 by mzso, 3 years ago

Cc: added

So, I guess this was decided to remain broken by design? Then why is it still open?

comment:15 by Jan Klass, 3 years ago

Cc: added

comment:16 by Tom B, 3 years ago

Cc: added

This is still an issue in 4.1.3. Can libobus be used for 5.1 audio? I've been using libvorbis for now but would be preferable to opus.

comment:17 by Soichiro, 2 years ago

Still present in 4.2.1. Could we at least get a response on this? Much thanks to the work by Peter to provide a patch and a workaround, but I would much like to see the patch merged so the workaround isn't needed.

comment:18 by Soichiro, 2 years ago

Cc: added

comment:19 by Christoph, 15 months ago

Cc: added

Still present (after 4 years) in version 4.3.1.

comment:20 by everlanes, 8 months ago

I also ran into this problem and the suggested workaround is not working for me.

I want to convert MKV files with multiple audio channels to opus audio keeping the layout of every single channel. When using the -af channelmap=channel_layout="5.1" option I get an error message for all stereo channels:

[Parsed_channelmap_0 @ 0x55a7dde59300] input channel #2 not available from input layout 'stereo'
[Parsed_channelmap_0 @ 0x55a7dde59300] input channel #3 not available from input layout 'stereo'
[Parsed_channelmap_0 @ 0x55a7dde59300] input channel #4 not available from input layout 'stereo'
[Parsed_channelmap_0 @ 0x55a7dde59300] input channel #5 not available from input layout 'stereo'
[Parsed_channelmap_0 @ 0x55a7dde59300] Failed to configure input pad on Parsed_channelmap_0
Error reinitializing filters!
Failed to inject frame into filter network: Invalid argument
Error while processing the decoded data for stream #0:5

Furthermore I expect all 7.1 channels to be downmixed to 5.1 as well with these settings. I don't want that either.

When removing the filter I get the original error:

[libopus @ 0x563a3830d9c0] Invalid channel layout 5.1(side) for specified mapping family -1.
Error initializing output stream 0:2 -- Error while opening encoder for output stream #0:2 - maybe incorrect parameters such as bit_rate, rate, width or height

This seems to be a trivial problem as all it takes would be changing metadata 5.1(side) to (5.1). No downmixing, no recompressing of data, nothing. But yet, this bug is unresolved since five years now!

Is there a solution (or another workaround ...) for this situation?
Maybe a 3rd party tool or separate ffmpeg run just to change metadata of all 5.1(side) channels to 5.1?

comment:21 by everlanes, 7 months ago

So I hacked together a quite complicated script to circumvent this issue (hopefully), but I am not very proud of it and I think it's strange I have to do it:


read -r -d "" PYTHONCODE << EOD
import sys, json 

data = json.load(sys.stdin)

replace = {
        "5.0(side)": "5.0",
        "5.1(side)": "5.1",
        # you can add more mappings here

filter_string = "[:%d]channelmap=channel_layout='%s'" 
copy_string = "[:%d]anull"

maps = [filter_string % (stream["index"], replace[stream["channel_layout"]])
        if stream.get("channel_layout") in replace.keys() else
        copy_string % (stream["index"])
        for stream in data["streams"]
        if stream["codec_type"] == "audio"]


ffmpeg -i "$FILE" -map 0 \
    -c:v copy \
    -c:a libopus -filter_complex \
        `ffprobe -hide_banner -show_streams -print_format json "$FILE" | \
        python3 -c "$PYTHONCODE"` \
    -c:s copy \

So basically I get all streams of the original file and pipe it into a python script that creates the filter string that remaps all problematic streams. This string is then printed and used as an argument for the ffmpeg call...

Does it work? Hopefully. Is it nice? Definitely not! There should be some kind of an (optionally) fallback mechanism in ffmpeg and/or libopus for unsupported channel layouts.

Note: See TracTickets for help on using tickets.