声道模式就是「一个名字加一组声道位置约定」。 5.1 是 6 个声道不是 5 个——那个 .1 指的是低音声道。
3.11.8 讲视频侧的硬件,这一节转到音频侧的声道。 多声道素材出问题,十有八九是布局名字或者声道顺序弄错了。
一、九个常见布局,名字与声道数
名字拼对了才构造得出来,拼错直接抛异常:
名字 声道数 典型用途
mono 1 单声道,语音最省 stereo 2 立体声,最通用 2.1 3 左右加低音 3.0 3 左中右 quad 4 四声道环绕 5.0 5 环绕无低音 5.1 6 影院标配 6.1 7 多一个后中 7.1 8 蓝光标配
这九个在本机全部可用,名字全部拼对了才构造得出来。 拼错的表现是直接抛异常——这比「静默降级成单声道」好得多。
二、名字里的数字不能靠猜
5.1 是 6 个声道,不是 5 个,这一条最容易记错:
名字 以为几个 实际几个
5.1 5 6 6.1 6 7 7.1 8 8
规律是「小数点前的数加 1」:那个 .1 是一个额外的低音声道,不算在整数里。
7.1 那一行看着对上了,是因为它本来就写了 8——但这个巧合容易让人记错规律。
写脚本时更稳的办法是拿到布局对象读 nb_channels,别自己算。
算错一次就是整条音轨的声道被错位映射,比报错难查得多。
三、降混是自动的,结果不保证好听
声道数变少时系统会自动混,但混法是为「不削波」优化的:
转换 系统怎么处理 注意
5.1 → stereo 按权重混到两个声道 环绕感没了 stereo → mono 两路相加再衰减 可能相位抵消 mono → stereo 两路复制一份 没有真正的立体感
第一行的权重是 libswresample 内置的,可以用 -af pan 自己指定。
默认那套权重不一定是为「好听」优化的,专业场合要自己调。
第二行那个「相位抵消」是个具体现象:两路内容相近但反相时,相加会变小声。 表现是「转成单声道后人声突然变闷」——这不是文件坏了。
四、名字的隐藏用途:查声道顺序
布局名字背后是一张固定的声道顺序表,动多声道素材时必须按它来:
布局 声道顺序
stereo 前左、前右 5.1 前左、前右、中、低音、后左、后右 7.1 前左、前右、中、低音、后左、后右、侧左、侧右
写 -af channelmap 时必须按这个顺序填,填错就是把对白送到低音炮里。
这种错误听起来很荒谬,但它确实是最常见的一类多声道事故。
所以动多声道素材之前,先确认布局名,再确认顺序,两步都不能省。
只确认名字不够——5.1 和 5.1(side) 的声道定义就不一样。
五、动手 Demo:九个布局,逐个读出真实声道数
不靠记忆,直接把每个布局名字构造一遍,读它自己报的声道数。 这样「5.1 到底是几个声道」这种问题就有确定答案了。
import av
LAY = [(u"mono", u"语音"), (u"stereo", u"通用"), (u"2.1", u"加低音"),
(u"3.0", u"左中右"), (u"quad", u"四声道"), (u"5.0", u"环绕"),
(u"5.1", u"影院"), (u"6.1", u"后中"), (u"7.1", u"蓝光")]
for name, use in LAY:
try:
l = av.AudioLayout(name)
print(u"%-8s %d 声道 %s" % (name, l.nb_channels, use))
except Exception as e:
print(u"%-8s 不支持 %s" % (name, use))
# 名字拼错会怎样
try:
av.AudioLayout(u"5.2")
print(u"5.2 竟然也构造出来了")
except Exception:
print(u"5.2 构造失败,说明布局名是白名单")
实跑输出:
--------------------------------------------------------------------
3.11.9 -layouts——声道模式的名字与含义
--------------------------------------------------------------------
**① 声道模式就是一个名字加一组「哪个声道在哪」的约定**
名字 声道数 典型用途
------------------------------------------
mono 1 单声道,语音最省
stereo 2 立体声,最通用
2.1 3 左右+低音
3.0 3 左右中
quad 4 四声道环绕
5.0 5 环绕无低音
5.1 6 影院标配
6.1 7 多一个后中
7.1 8 蓝光标配
**本机这 9 种全部可用,名字全部拼对了才构造得出来。**
**拼错的表现是直接抛异常——这比「静默降级成单声道」好得多。**
**② 数字不能靠猜**
**`5.1` 是 6 个声道,不是 5 个——那个 `.1` 指的是低音声道。**
**`6.1` 是 7 个,`7.1` 是 8 个,规律一样。**
**所以「5.1 转 2.0」这种说法里的数字,跟声道数不是一回事,要查表。**
**写脚本时更稳的办法是:拿到布局对象读 `nb_channels`,别自己算。**
**③ 降混是自动的,但结果不保证好听**
转换 系统怎么处理 注意
-------------------------------------------------------------
5.1 → stereo 按权重混到两个声道 环绕感没了
stereo → mono 两路相加再衰减 可能相位抵消
mono → stereo 两路复制一份 没有真正的立体感
**第一行的权重是 libswresample 内置的,可以用 `-af pan` 自己指定。**
**默认那套权重是为「不削波」优化的,不一定是为「好听」优化的。**
**④ 名字还有一个隐藏用途:查它的声道顺序**
**`5.1` 的六个声道顺序是固定的(前左、前右、中、低音、后左、后右),**
**写 `-af channelmap` 时必须按这个顺序填,填错就是把对白送到低音炮里。**
**所以动多声道素材之前,先确认布局名,再确认顺序,两步都不能省。**
打出来的声道数会逐行验证那条「小数点前加 1」的规律。 这是最省事的记法:不用背表,读一次就记住了。
最后那两行是「拼错会怎样」的对照实验:布局名是白名单,不在名单里直接失败。 这个行为比「猜一个最接近的」安全得多——错了立刻知道,不会静默降级。
注意 quad、mono 这些名字不带数字,所以规律只适用于带点号的那几个。
混着记的时候,还是以读出来的 nb_channels 为准。
30 秒实验
- 列布局:
ffmpeg -layouts,注意它把音频布局和像素格式分两段打在一起。 - 降混:
ffmpeg -i 5.1.wav -ac 2 出.wav,听环绕感丢了多少。 - 指定布局:
ffmpeg -i 片子.mp4 -af aformat=channel_layouts=stereo 出.mp4,强制输出布局。
常见误区
- 以为
5.1是 5 个声道。它是 6 个,那个.1是额外的低音声道。 - 以为降混是免费的。5.1 转 stereo 会按固定权重混,环绕感直接消失。
- 不确认声道顺序就写
channelmap。填错顺序就是把对白送进低音炮。
自测三问(点开对答案)
1. `5.1` 布局是几个声道?为什么? —— 6 个。小数点前是 5 个主声道,那个 `.1` 是一个独立的低音声道。 2. mono 转 stereo 之后听起来有立体感吗? —— 没有。它只是把同一路复制成两份,两个声道内容完全相同。 3. 布局名字拼错了会怎样? —— 直接抛异常。布局名是白名单,不会猜一个最接近的,所以错了立刻能发现。- ☐ (本节完,下一节 3.11.10 -sample_fmts)