AC-3 是恒定码率:每帧 1536 点、字节固定,不够补、多了砍。 它只认 32、44.1、48 kHz 三档采样率,别的不给商量。
上一节转 MP3 还算自由,这一节会撞上硬约束。 目标格式的「死规矩」比参数调优重要得多,这是本节的重点。
一、三档码率,三行都贴着目标走
同一段声音,192/384/448 kbps 各转一遍:
目标码率 字节 实测码率
192 kbps 48482 193 kbps 384 kbps 96966 387 kbps 448 kbps 113128 452 kbps
三行都几乎贴着目标,和 5.1.2 里 AAC「用不完」那次完全不同。 因为 AC-3 是恒定码率:每帧字节固定,简单内容也要填满。
恒定码率的好处是播放器不用缓冲、码流长度可预测;坏处是该省的省不下来。 所以它在网络播放上很浪费,同样的听感 AAC 能省一半。
二、采样率不是想给就能给
AC-3 只认三档采样率:
采样率 结果
48000 成功 44100 成功 32000 成功 24000 被拒(returned 22) 22050 被拒(returned 22)
因为码流里采样率的编码位太少,当年只留了三档。这是标准定死的,不是实现偷懒。 连 24000 这种整数都不行,别指望「取个整就过了」。
遇到这种限制,唯一的路是「先用重采样器改到 48 kHz,再交给 AC-3」。
命令行里 ffmpeg 会帮你补这一步:-ar 48000 加上去就行。
三、什么场合才轮到 AC-3
它是为影院与电视定的,不是为网络定的:
场合 为什么用它
蓝光、家庭影院 老功放都认,兼容性最好 数字电视广播 ATSC 标准音轨就是它 网络播放 不该用,AAC 更省
第三行是结论:选音频格式的顺序永远是「先看播放端认什么,再在里面挑最省的」。 不认 AC-3 的播放器一大把,主动选它只会给自己找麻烦。
顺带一提:真正需要 5.1 声道时,AC-3 的优势才明显—— 它本来就是为多声道设计的,立体声只是它的一种简单情形。
四、动手 Demo:三档码率各转一遍,再试一个不给的采样率
输入是 128 kbps 的 AAC,输出 AC-3,试 192、384、448 三档。 最后故意用 22050 Hz 再转一次,看它怎么拒绝。
import av, os
c0 = av.open(u"aac128.m4a")
fr0 = next(c0.decode(audio=0))
c0.close()
for br in (192000, 384000, 448000):
c0 = av.open(u"aac128.m4a")
c1 = av.open(u"ac3_%d.ac3" % (br // 1000), u"w")
s1 = c1.add_stream(u"ac3", rate=44100)
s1.layout, s1.bit_rate = u"stereo", br
for f in c0.decode(audio=0):
for o in s1.encode(f):
c1.mux(o)
for o in s1.encode(None):
c1.mux(o)
c1.close()
c0.close()
n = os.path.getsize(u"ac3_%d.ac3" % (br // 1000))
print(u"%d kbps -> %d 字节 实测 %d kbps"
% (br // 1000, n, n * 8 / 2.0 / 1000))
c1 = av.open(u"ac3_22.ac3", u"w")
s1 = c1.add_stream(u"ac3", rate=22050)
print(u"建流这一步没报错")
try:
for o in s1.encode(fr0):
c1.mux(o)
print(u"22050 编成功了")
except Exception as e:
print(u"22050 被拒:%s" % str(e)[:60])
c1.close()
实跑输出:
--------------------------------------------------------------------
5.3.3 AAC 转码为 AC-3——影院规格的固定码率
--------------------------------------------------------------------
**① 三档码率各转一遍**
目标码率 字节 实测码率
---------------------------------
192 kbps 48482 193 kbps
384 kbps 96966 387 kbps
448 kbps 113128 452 kbps
**三行几乎都贴着目标走,和 AAC 那次的「用不完」完全不同。**
**因为 AC-3 是恒定码率:每帧 1536 点、固定字节数,不够就补、多了就砍。**
**恒定码率的好处是播放器不用缓冲,坏处是该省的省不下来。**
**② 采样率不是想给就能给**
采样率 结果
-------------------------------
44100 成功
22050 被拒(returned 22)
**22050 直接被拒。AC-3 只认 32 kHz、44.1 kHz、48 kHz 这三档,**
**因为它当初是为影院与电视定的,码流里的采样率只有两位编码,放不下别的值。**
**这就引出转码的第一条常识:目标格式的硬约束要先查,不是所有参数都能商量。**
**③ 什么场合才轮到 AC-3**
场合 为什么用它
------------------------------------------
蓝光、家庭影院 老功放都认,兼容性最好
数字电视广播 ATSC 标准音轨就是它
网络播放 不该用,AAC 更省
**第三行是重点:AC-3 的恒定码率在网络上很浪费,同样的听感 AAC 能省一半。**
**所以选音频格式的顺序应该是:先看播放端认什么,再在里面挑最省的那个。**
注意那个「建流这一步没报错」:add_stream 只是登记参数,
真正的 avcodec_open2 发生在第一次 encode 时。
所以只建流、不喂帧的试探是假成功——必须真编一帧才知道行不行。 这条规律对所有编码器都成立,调试「参数不合法」时尤其有用。
恒定码率下字节可以预估:码率乘时长除 8。 192 kbps 两秒约 48000 字节,实测 48482,多出来的是帧对齐的余量。
写文件用 .ac3 后缀,ffmpeg 能自己认出封装。
如果没有后缀(比如推流),得显式指定格式名。
30 秒实验
- 命令行对照:
ffmpeg -i 出.m4a -c:a ac3 -b:a 384k -ar 48000 出.ac3。 - 故意不给采样率:源是 44100 时也能过,但源是 22050 就必须加
-ar 48000。 - 换成 5.1:
-ac 6试试,字节会明显变大,这就是多声道的代价。
常见误区
- 以为采样率随便填。AC-3 只有三档,别的一律被拒。
- 以为恒定码率更「专业」。网络场景它只会浪费带宽。
- 拿 AC-3 给网页用。浏览器普遍不认,得用 AAC。
自测三问(点开对答案)
1. AC-3 每帧多少采样点?为什么字节这么稳定? —— 1536 点,而且是恒定码率:每帧字节固定,简单内容也要填满。 2. 为什么「只建流、不喂帧」试不出 22050 能不能用? —— add_stream 只登记参数,真正的 avcodec_open2 在第一次 encode 时才跑。 3. 为什么 22050 Hz 会被拒? —— AC-3 规范只允许 32、44.1、48 kHz 三档,码流里没有别的编码位。 4. 要给网页准备音轨,该选什么? —— AAC。AC-3 浏览器普遍不支持,而且恒定码率更费带宽。- ☐ (本节完,下一节 5.4.1 YUV 编码为 H.264)