🎬 第三章 FFmpeg三大常用工具及应用选项详解
📄 一句话概括

这一组不是「高级」,是「改变处理哪一段、哪几路」。 -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 秒实验

  1. 截一段:ffmpeg -ss 30 -i 片子.mp4 -t 10 -c copy 出.mp4,注意 -ss 放前面、-t 放后面。
  2. 试 -to:ffmpeg -ss 30 -i 片子.mp4 -to 40 -c copy 出.mp4,结果和上面一样。
  3. 封面片:ffmpeg -loop 1 -i 封面.png -i 音乐.mp3 -shortest -c:v libx264 出.mp4,不加 -shortest 会一直跑。

常见误区

  1. 把 -to 当时长。它是绝对位置。-ss 30 -to 10 什么都不转,而且不报错。
  2. 用 -loop 1 不加 -shortest。图片是无限源,命令永远不结束,会一直写盘到满。
  3. 靠帧数反推时长。边界帧算不算会造成误差,精确截取要用时间戳。
自测三问(点开对答案) 1. `-ss 30 -t 10` 和 `-ss 30 -to 40` 结果一样吗? —— 一样,都是第 30 到 40 秒。但 `-ss 30 -to 10` 就什么都不转,因为终点在起点之前。 2. 为什么用 `-loop 1` 做封面必须加 `-shortest` 或 `-t`? —— 因为循环的图片是无限长的源,没有终点。不加限制命令就永远不结束,会一直写盘。 3. `-ss` 放在 `-i` 前后有什么区别? —— 放前面是「先跳到关键帧再解」,快但落点不精确;放后面是「从头解到位置再丢」,慢但精确。

相关笔记