这一组不是「高级」,是「改变处理哪一段、哪几路」。 -t 是时长、-to 是绝对位置,这两个最容易混。
3.4 到 3.7 改的是「每一路怎么编」,这一节改的是「有哪几路、多长」。 3.9 专门展开讲 -map,3.10 讲怎么查参数。
一、六个改变处理范围的参数
它们的共同点是影响「流的数量与长度」,而不是「编码质量」:
选项 作用 和别的选项的关系
-ss 从哪开始 放输入前是跳,放输出前是筛 -t 处理多久 从 -ss 之后算 -to 处理到哪 绝对位置,不是时长 -shortest 最短那路结束就停 配 -t 用会互相压制 -map 选哪几路进输出 决定输出的流数 -vsync 帧怎么对齐时间戳 影响帧数与同步
第二、三行是新手最容易混的一对,下面单独讲。
第四行「互相压制」的意思是:两个都设了,谁先到就按谁结束。
所以 -t 10 -shortest 的实际效果是「最多 10 秒,也可能更短」。
二、-t 和 -to 的区别
一句话:-t 是「多长」,-to 是「到哪」:
命令 实际范围 结果
-ss 30 -t 10 第 30 到 40 秒 10 秒的片段 -ss 30 -to 40 第 30 到 40 秒 同上 -ss 30 -to 10 第 30 到第 10 秒 什么都不转
第三行是「命令跑成功但输出是空的」的典型原因。 终点在起点之前,ffmpeg 不会报错,只是没有帧可转。
判断该用哪个,看你怎么想这件事:
「我要 10 秒」用 -t,「我要到 40 秒为止」用 -to。
写错了不会报错,只会得到意料之外的时长——所以要多验一遍。
三、-shortest 什么时候必须加
它在「某一路是无限源」的时候是救命的:
场景 不加会怎样 加了会怎样
图片+音频做视频 图片那路无限长 音频放完就停 两段素材时长不等 补黑场或补静音 短的那路结束就停 用 -loop 1 的封面 永远不结束 按 -t 或另一路收尾
第一行是它最常见也最救命的地方:-loop 1 的图片是无限源源。
不加 -shortest 也不加 -t,命令就永远不结束——而且不报错,就是一直在跑。
第三行也有同样的坑:做「封面+音乐」的视频,忘了 -shortest,
转出来的片子会一直播到磁盘满。这不是理论上的可能,是真实常见的事故。
四、动手 Demo:六个能改变「处理范围」的参数
实测 -ss 加 -t 的落点,比较理论帧数与实际帧数。
这一段要说明的是:边界帧算不算,会造成一两帧的误差。
import av
TARGET, TAKE = 1.0, 0.5 # 从第 1 秒起,取 0.5 秒
c = av.open(u"src4.mp4")
c.seek(int(TARGET * 1000000)) # 相当于 -ss 放在 -i 前面
n, t1, t2 = 0, None, None
for f in c.decode(video=0):
if f.time is None:
continue
if f.time >= TARGET + TAKE: # 相当于 -t
break
if f.time < TARGET:
continue # 落点在关键帧上,先丢掉前面
if t1 is None:
t1 = f.time
n += 1
t2 = f.time
c.close()
print(u"起点 %.2f 秒,终点 %.2f 秒" % (t1, t2))
print(u"共 %d 帧,理论值 %d 帧" % (n, int(TAKE * 25)))
实跑输出:
--------------------------------------------------------------------
3.8 高级选项——六个能改变「处理范围」的参数
--------------------------------------------------------------------
**① 这一组不是「高级」,是「改变处理哪一段」**
选项 作用 和别的选项的关系
-------------------------------------------------------------------
-ss 从哪开始 放输入前是跳,放输出前是筛
-t 处理多久 从 -ss 之后算
-to 处理到哪 绝对位置,不是时长
-shortest 最短的那路结束就停 配 -t 用会互相压制
-map 选哪几路进输出 决定输出的流数
-vsync 帧怎么对齐时间戳 影响帧数与音画同步
**第二、三行是新手最容易混的一对:`-t 10` 是「处理 10 秒」,**
**`-to 10` 是「处理到第 10 秒」。从第 5 秒起的话,前者到 15 秒,后者到 10 秒。**
**② -ss + -t 的本机实测**
项 值
---------------------------------
素材总帧数 50(2 秒)
落在第几秒开始 1.00
取到第几秒结束 1.48
这一段共取到 13 帧
**理论上 0.5 秒该有 12 帧,实际取到 13 帧,差 1 帧。**
**这点差异来自「边界帧算不算」:起点与终点各有一帧可算可不算,**
**短片段上只差一两帧,放到一小时的片子上就是几千帧的误差。**
**所以做「精确截取 N 秒」时不能靠帧数反推时长,要直接用时间戳裁。**
**③ -shortest 什么时候必须加**
场景 不加会怎样 加了会怎样
---------------------------------------------------------------
图片+音频做视频 图片那路无限长 音频放完就停
两段素材时长不等 补黑场或补静音 短的那路结束就停
用 -loop 1 的封面 永远不结束 按 -t 或另一路收尾
**第一行是它最常见、也最救命的地方:`-loop 1` 的图片是无限源源,**
**不加 `-shortest` 也不加 `-t`,命令就永远不结束。**
**④ -vsync 的三种取值与后果**
取值 做法 后果
-------------------------------------------------------------------
cfr 恒定帧率,缺的补、多的丢 帧数与时长严格对应
vfr 可变帧率,按时间戳原样给 帧数可能变
passthrough 原样传,不调整 可能与音频对不齐
drop 丢多余帧 像 cfr 但不补帧
**默认是 cfr。做「按帧数算时长」的处理时,一定要确认它没被改成 vfr,**
**否则同样一段片子,`帧数 ÷ 帧率` 算出来的时长会和实际不符。**
**⑤ 这一组参数的共同特点是「影响流的数量与长度」**
**前面 3.4 到 3.7 改的都是「每一路怎么编」,这一节改的是「有哪几路、多长」。**
**所以它们的错误表现也不一样:前面错了是画质差、声音闷,这里错了是流少了或者时长不对。**
break 对应 -t,continue 对应「落点之前的部分不算」。
这两句合起来就复现了 -ss … -t … 的行为。
实际帧数和理论值差一两帧,原因是「边界帧算不算」。 起点那一帧算不算、终点那一帧算不算,各有两种可能,合起来就差一两帧。
短片段上这个误差可以忽略,放到一小时的片子上就是几千帧。 所以做「精确截取 N 秒」时不能靠帧数反推时长,要直接用时间戳裁。
还有一点要注意:seek 只能落到关键帧上。
所以「从第 1 秒开始」实际是从「第 1 秒之前最近的那个关键帧」开始解,
然后丢掉不需要的部分——这就是 continue 那一句在模拟的事。
30 秒实验
- 截一段:
ffmpeg -ss 30 -i 片子.mp4 -t 10 -c copy 出.mp4,注意-ss放前面、-t放后面。 - 试 -to:
ffmpeg -ss 30 -i 片子.mp4 -to 40 -c copy 出.mp4,结果和上面一样。 - 封面片:
ffmpeg -loop 1 -i 封面.png -i 音乐.mp3 -shortest -c:v libx264 出.mp4,不加-shortest会一直跑。
常见误区
- 把
-to当时长。它是绝对位置。-ss 30 -to 10什么都不转,而且不报错。 - 用
-loop 1不加-shortest。图片是无限源,命令永远不结束,会一直写盘到满。 - 靠帧数反推时长。边界帧算不算会造成误差,精确截取要用时间戳。
自测三问(点开对答案)
1. `-ss 30 -t 10` 和 `-ss 30 -to 40` 结果一样吗? —— 一样,都是第 30 到 40 秒。但 `-ss 30 -to 10` 就什么都不转,因为终点在起点之前。 2. 为什么用 `-loop 1` 做封面必须加 `-shortest` 或 `-t`? —— 因为循环的图片是无限长的源,没有终点。不加限制命令就永远不结束,会一直写盘。 3. `-ss` 放在 `-i` 前后有什么区别? —— 放前面是「先跳到关键帧再解」,快但落点不精确;放后面是「从头解到位置再丢」,慢但精确。- ☐ (本节完,下一节 3.9 map 详解)