pan

Watch on youtube.com
doc

https://ffmpeg.org/ffmpeg-filters.html#pan-1, (ffmpeg-utils)2.8. Syntax | Channel Layout

see also

channelmap, channelsplit, join, amix, amerge

The description in the official documentation:

Mix channels with specific gain levels. The filter accepts the output channel layout followed by a set of channels definitions.

This filter is also designed to efficiently remap the channels of an audio stream.

The filter accepts parameters of the form:

l|outdef|outdef|...
  • l:

    output channel layout or number of channels

  • outdef:

    output channel specification, of the form:

    out_name=[gain*]in_name[(+-)[gain*]in_name...]
    
    • out_name:

      output channel to define, either a channel name (FL, FR, etc.) or a channel number (c0, c1, etc.)

    • gain:

      multiplicative coefficient for the channel, 1 leaving the volume unchanged

    • in_name:

      input channel to use, see out_name for details;

    Warning

    it is not possible to mix named and numbered input channels

    If the `=’ in a channel specification is replaced by `<’, then the gains for that specification will be renormalized so that the total is 1, thus avoiding clipping noise.

For example:

[me@host: ~]$ # swapping LR
[me@host: ~]$ ffmpeg -y -i 2chstereo.wav -filter_complex "
> [0:a]pan='stereo|FL=FR|FR=FL'" out.wav
[me@host: ~]$ # both the inputs have 2 channels stereo,
[me@host: ~]$ # so the result of "amerge" has 4 channels.
[me@host: ~]$ ffmpeg -y -i audio1.wav -i audio2.wav -filter_complex "
> [0:a][1:a]
> amerge
> ,pan='stereo|
>       c0 < 0.5 * c0 + 0.5 * c2 |
>       c1 < 0.5 * c1 + 0.5 * c3'
> " out.wav

In the uplodaed video, I did:

[me@host: ~]$ # Applying "pan" filter. In this case, it decreases
[me@host: ~]$ # the left and right channel volumes separately.
[me@host: ~]$ ffplay -f lavfi "
> amovie=wolframtones_02.wav
> ,pan='stereo| c0 = 0.1 * c0 | c1 = 0.9 * c1'
> ,asplit=3
> [out1][oa1][oa2];
> [oa1]showfreqs=s=960x270:fscale=log:cmode=separate[v1];
> [oa2]showvolume,scale=960:270[v2];
> [v1][v2]vstack[out0]"
[me@host: ~]$ # After separating LFE components and others,
[me@host: ~]$ # let's "amerge"" them.
[me@host: ~]$ # The resulting channel layout will be 4 channels
[me@host: ~]$ # (FL | FR | FC | BC) (probably not what you want).
[me@host: ~]$ ffplay -f lavfi "
> amovie=wolframtones_02.wav
> ,asplit[a1][a2];
> [a1]bandreject=f=192:w=64,aformat=channel_layouts=stereo[rest];
> [a2]bandpass=f=192:w=64,aformat=channel_layouts=stereo[lfe];
> [rest][lfe]amerge
> ,asplit=3
> [out1][oa1][oa2];
> [oa1]showfreqs=s=960x270:fscale=log:cmode=separate[v1];
> [oa2]showvolume,scale=960:270[v2];
> [v1][v2]vstack[out0]"
[me@host: ~]$ # Using "pan" to make this into "FL | FR | LFE"
[me@host: ~]$ # 2.1 channel.
[me@host: ~]$ ffplay -f lavfi "
> amovie=wolframtones_02.wav
> ,asplit[a1][a2];
> [a1]bandreject=f=192:w=64,aformat=channel_layouts=stereo[rest];
> [a2]bandpass=f=192:w=64,aformat=channel_layouts=stereo[lfe];
> [rest][lfe]amerge
> ,pan='2.1| FL=FL | FR=FR | LFE=FC+BC'
> ,asplit=3
> [out1][oa1][oa2];
> [oa1]showfreqs=s=960x270:fscale=log:cmode=separate[v1];
> [oa2]showvolume,scale=960:270[v2];
> [v1][v2]vstack[out0]"
[me@host: ~]$ # It just outputs the output to a file instead of
[me@host: ~]$ # real-time playback.
[me@host: ~]$ ffmpeg -filter_complex "
> amovie=wolframtones_02.wav
> ,asplit[a1][a2];
> [a1]bandreject=f=192:w=64,aformat=channel_layouts=stereo[rest];
> [a2]bandpass=f=192:w=64,aformat=channel_layouts=stereo[lfe];
> [rest][lfe]amerge
> ,pan='2.1| FL=FL | FR=FR | LFE=FC+BC'
> ,asplit=3
> [out1][oa1][oa2];
> [oa1]showfreqs=s=960x270:fscale=log:cmode=separate[v1];
> [oa2]showvolume,scale=960:270[v2];
> [v1][v2]vstack[out0]" -map '[out0]' -map '[out1]' out_2.1.mp4
[me@host: ~]$ # Probably, there isn't much that you try to
[me@host: ~]$ # convert from 2ch stereo to 2.1ch as in the
[me@host: ~]$ # previous example. Rather, most people want to
[me@host: ~]$ # convert 2.1ch audio received from someone to
[me@host: ~]$ # 2ch stereo to avoid problems in the playback
[me@host: ~]$ # environment.
[me@host: ~]$ ffplay out_2.1.mp4 -af "pan='stereo|FL<FL+LFE|FR<FR+LFE'"
[me@host: ~]$ ffplay -f lavfi "
> amovie=out_2.1.mp4,pan='stereo|FL<FL+LFE|FR<FR+LFE',asplit[out1][a];
> [a]showvolume,scale=800:-1[out0]"

Note

Saying “form specification” may feel flexible, but not at all. For example, the following examples are all illegal and rejected.

[me@host: ~]$ # layout "stereo " is invalid (extra space)
[me@host: ~]$ ffmpeg -y -i 2chstereo.wav -filter_complex "
> [0:a]pan='stereo |FL=FR|FR=FL'" out.wav
[me@host: ~]$ # you cannot use calculation
[me@host: ~]$ ffplay 2chstereo.wav -af "
> pan='stereo|FL=(1/2)*FR|FR=FL'"
[me@host: ~]$ # recall: you cannot use calculation
[me@host: ~]$ ffplay -f lavfi "
> amovie=2chstereo.wav,pan='stereo|c0=0.5*(c0+c1)|c1=c1'"
[me@host: ~]$ # must be "gain*in_name", not "in_name*gain"
[me@host: ~]$ ffmpeg -y -i 2chstereo.wav -filter_complex "
> [0:a]pan='stereo|c0=c0*0.5|c1=c1'" out.wav
[me@host: ~]$ # can not mix named and numbered channels
[me@host: ~]$ ffmpeg -y -i 2chstereo.wav -filter_complex "
> [0:a]pan='stereo|c0=0.5*FR|c1=c1'" out.wav
[me@host: ~]$ # can not mix named and numbered channels
[me@host: ~]$ ffmpeg -y -i 2chstereo.wav -filter_complex "
> [0:a]pan='stereo|FL=0.5*c0|c1=c1'" out.wav

changing the mixing amount for each frequency band

If you want to understand the behavior of filters that are frequency-based and operate on multiple channels, you may want to split the left and right channels by frequency band. The following example is changing the mixing amount for each frequency band:

[me@host: ~]$ # "acrossover" can be used in ffmpeg 4.1+.
[me@host: ~]$ ffmpeg411="/c/Program Files/ffmpeg-4.1.1-win64-shared/bin/ffmpeg"
[me@host: ~]$ "${ffmpeg411}" -y -filter_complex "
> amovie=input.wav
> ,acrossover=split='55|110|220|1500'[ab0_0][ab1_0][ab2_0][ab3_0][ab4_0];
> [ab0_0]aformat=channel_layouts=stereo[ab0];
> [ab1_0]aformat=channel_layouts=stereo[ab1];
> [ab2_0]aformat=channel_layouts=stereo[ab2];
> [ab3_0]aformat=channel_layouts=stereo[ab3];
> [ab4_0]aformat=channel_layouts=stereo[ab4];
> [ab0][ab1][ab2][ab3][ab4]amerge=5[sm];
> [sm]pan='stereo|
> c0 < 0.0 * c0 + 3.0 * c2 + 0.0 * c4 + 3.0 * c6 + 1.0 * c8
> |
> c1 < 4.0 * c1 + 0.0 * c3 + 4.0 * c5 + 0.0 * c7 + 1.0 * c9'
> ,volume=3
> ,asplit=2[out1],channelsplit[a1][a2];
> [a1]showcqt=s=1920x540,setsar=1[v1];
> [a2]showcqt=s=1920x540,setsar=1,vflip[v2];
> [v1][v2]vstack
> [out0]
> " -map '[out0]' -map '[out1]' output.mp4