PAL、NTSC、SECAM 三种模拟制式,行数、场频、帧率都不一样。 这些数字今天还在影响每一个 ffmpeg 参数的默认值。
2.7 讲的是一个「看得懂的格式」,这一节回到历史,讲清那些古怪数字的出处。 2.8.2 和 2.8.3 分别把 PAL 与 NTSC 算到底。
一、三种制式,三套参数
模拟电视时代,各国选的路不一样,留下的参数也不一样:
制式 扫描行 场频 帧率 主要地区
PAL 625 50 25 中国、欧洲、澳洲 NTSC 525 60 29.97 北美、日本 SECAM 625 50 25 法国、俄罗斯、非洲
第一列的行数不是随便定的,它跟当地的交流电频率有关: 50 Hz 的地区用 50 场,60 Hz 的地区用 60 场——早期设备靠电源同步。
所以「用哪种制式」在当年不是技术选择,是地理选择。 这也解释了为什么今天同一个视频在不同国家还要挑不同的版本。
二、场和帧是两倍关系
最容易搞混的一对概念,其实关系很简单:
概念 含义 PAL NTSC
场 一次扫描的半幅画面 50 60 帧 两场拼成一幅完整画面 25 30 关系 帧率 = 场频 ÷ 2 — —
因为当年是隔行扫描:先扫奇数行,再扫偶数行,两次凑成一幅完整画面。 所以「50 场」和「25 帧」说的是同一件事,只是数法不同。
这个换算在看规格时特别有用:看到「1080i50」,就是「1080 隔行、每秒 50 场」, 等价于 25 帧;看到「1080p50」,那是逐行 50 帧,信息量是前者的两倍。
最后一个字母是隔行标志:i 是隔行,p 是逐行。 这两个字母的区别,比分辨率数字更能决定一路流要多少带宽。
三、为什么 NTSC 那个 29.97 这么怪
按上表的规律,NTSC 应该是 60 场、30 帧,整数多干净。 可实际是 29.97,差的那千分之一是后来加的。
原因是彩色电视要兼容黑白电视:彩色信号要在原来的带宽里塞进色度信息, 为了不让色度干扰伴音载波,工程师把行频减慢了千分之一。
这个改动小到肉眼看不出,但它留下了一个永久的麻烦: 帧率不再是整数,时间码和真实时间会慢慢对不上。
差多少、怎么补,2.8.3 会把数算完。这里只要记住一句: 29.97 不是四舍五入的结果,它的精确值是 30000/1001。
四、动手 Demo:PAL 与 NTSC 到底差在哪
把三种制式的参数摆在一起,再把「场」与「帧」的换算算一遍。 最后量一下千分之一的偏差累积一小时会变成多少帧。
# 三种制式的参数表,纯查表,不涉及设备
STD = {
u"PAL": dict(lines=625, field=50, fps=25.0),
u"NTSC": dict(lines=525, field=60, fps=30000.0 / 1001),
u"SECAM": dict(lines=625, field=50, fps=25.0),
}
for name, d in STD.items():
print(u"%-5s 行 %d 场 %d 帧 %.2f"
% (name, d[u"lines"], d[u"field"], d[u"fps"]))
# 场频与帧率的两倍关系
for name, d in STD.items():
half = d[u"field"] / 2.0
print(u"%s 场频÷2 = %.2f,表里写 %.2f,差 %.3f"
% (name, half, d[u"fps"], abs(half - d[u"fps"])))
# 千分之一偏差累积一小时
n30 = 30 * 3600
n2997 = (30000.0 / 1001) * 3600
print(u"按 30 算 %.0f 帧,按 29.97 算 %.0f 帧,差 %.0f 帧"
% (n30, n2997, n30 - n2997))
print(u"折合 %.1f 秒" % ((n30 - n2997) / 30.0))
实跑输出:
--------------------------------------------------------------------
制式——PAL 与 NTSC 到底差在哪
--------------------------------------------------------------------
**① 三种模拟制式,参数完全不一样**
制式 行数 场频 帧率 主要地区
--------------------------------------------------------------
PAL 625 50 25 中国、欧洲、澳洲
NTSC 525 60 29.97 北美、日本、台湾地区
SECAM 625 50 25 法国、俄罗斯、非洲
**② 场频和帧率是两倍关系,因为隔行**
概念 含义 PAL NTSC
--------------------------------------------------
场 一次扫描的半幅画面 50 60
帧 两场拼成一幅完整画面 25 30
关系 帧率 = 场频 ÷ 2 25 30
**所以老录像带上的「50 场」和「25 帧」说的是同一件事,只是数法不同。**
**看到「1080i50」就是「1080 隔行、每秒 50 场」,等价于 25 帧。**
**③ 为什么 NTSC 是 29.97 而不是整数 30**
**因为彩色电视要在原来的黑白信号里塞色度,为了不让色度干扰伴音载波,**
**把行频减慢了千分之一:30 ÷ 1.001 ≈ 29.97。**
项 按 30 算 按 29.97 算 差
------------------------------------------------------
一小时帧数 108000 107892 108 帧
折合秒数 3600.0 3603.6 3.6 秒
**每小时差 3.6 秒,一天差 86 秒,一个月差 43 分钟。**
**这就是「丢帧时间码」这种东西存在的原因——不是丢画面,是丢时间码的编号。**
**④ 现在这些还有用吗**
**有,两种场合:一是老素材的帧率就摆在那儿;**
**二是各国摄像机的默认值仍是 25 或 30 的体系。**
**所以 ffmpeg 的参数里到处是 25、30、29.97、59.94,一个都不能少。**
第二段那个「差」值得看:PAL 和 SECAM 的场频÷2 正好等于帧率,差是 0。 NTSC 就不为 0 了——因为它的帧率根本不是 60÷2,而是 60÷2÷1.001。
这就是分辨「这是个整数制式还是 NTSC 制式」最快的办法: 场频÷2 能不能整除。不能整除的,背后一定有个 1001。
最后两行是那个千分之一累积的结果。一小时的偏差看着不大, 但播出是连续的,一天的偏差就够让字幕和画面错开好几秒。
注意这些都是「查表 + 算术」,不涉及任何设备。 沙箱里没有摄像头也没有采集卡,制式这一层只能这么验证——但结论是硬的,因为它是定义。
30 秒实验
- 查一次:
ffmpeg -h demuxer=rawvideo或看-framerate的说明,找到 PAL/NTSC 的预设值。 - 算一次:用 Python 算
30000/1001,确认和你以为的 29.97 差多少。 - 看一个真文件:
ffprobe -show_streams看r_frame_rate,常见值就是 25/1 和 30000/1001。
常见误区
- 把场频当帧率。50 场不等于 50 帧,隔行扫描下两场才凑一帧。看到 1080i50 要换成 25 帧来算码率。
- 以为 NTSC 是 30 帧。它名义上 30,实际是 30000/1001 ≈ 29.97。差千分之一,累积起来很可观。
- 以为制式只是历史名词。摄像机的默认值、ffmpeg 的预设、DVD 的分辨率,全都是从这儿来的。
自测三问(点开对答案)
1. 为什么 PAL 地区的扫描行数是 625,NTSC 是 525? —— 跟当地交流电频率有关。50 Hz 地区用 50 场配 625 行,60 Hz 地区用 60 场配 525 行,早期设备靠电源同步。 2. 「1080i50」换算成帧是多少? —— 25 帧。i 表示隔行,50 是场频,两场凑一帧,所以是 25 帧。 3. 怎么快速判断一个帧率是不是 NTSC 体系? —— 看场频÷2 能不能整除。不能整除(比如 60÷2=30 但帧率是 29.97)就说明背后有个 1001 的因子。- ☐ (本节完,下一节 2.8.2 PAL 制式)