🎬 第七章 FFmpeg命令行实现音视频特效及复杂滤镜应用
📄 一句话概括

color 四个参数:颜色、分辨率、帧率、时长。 d 不写就是无限长,d=1 在 25 帧率上正好出 25 帧。

📝 本节和前面几节的关系

7.4.6 已经用过 color 造纯黑背景,这一节把它当一个独立主题讲全。 它是「造黑场」「造占位画面」的唯一正解。

一、四个参数

color 的参数很少,但每个都得知道:

参数 写什么 默认


c 颜色名或十六进制 black s 分辨率,如 160x90 320x240 r 帧率 25 d 时长(秒) 不限

d 不写就是无限长——跟 nullsrc、anullsrc 一样。 所以造纯色视频必须给 d 或者在命令行加 -t,否则它会一直造下去。

这一点在 PyAV 里尤其要注意:它是「拉一次造一批」的模型, 不写 d 也不主动停下来,你就得自己数够了帧数再退出循环。

二、四种颜色与帧数

d=1、25 帧率,实测出 25 帧:

c 写什么 左上角像素 d=1 出几帧


black [0, 0, 0] 25 white [255, 255, 255] 25 0x336699 [49, 100, 151] 25 red [253, 0, 0] 25

d=1 出 25 帧、d=2 出 50 帧,正好是「秒 × 帧率」。 这个关系可以用来校验时长算得对不对——差一帧就是帧率写错了。

红色出来是 253 不是 255,还是 YUV 范围压缩那个零头; 十六进制的 0x336699 出来是 [49, 100, 151],也在 255 以内打了个折。 想要精确的 255,得写 color=c=red 之后接 format=rgb24 并指定范围。

三、跟 nullsrc 的区别

三个源滤镜都造画面,但造出来的东西不一样:

滤镜 画出什么 典型用途


color 指定的纯色 黑场、占位、垫片 nullsrc 全 0 的裸帧(看着发绿) 当画布喂给 crop/overlay testsrc 彩条加计时码 测同步、测编码

nullsrc 三平面全是 0,转 RGB 是 [0, 135, 0]——带绿味,不是黑。 要黑就得写 color=c=black,别拿 nullsrc 当黑场用。

testsrc 是测试图:彩条加跳动的数字与计时器。 查「帧是不是在动」「时间戳对不对」用它最快,比找素材省事。

四、黑幕视频的三种用法

纯色视频在实战里主要是这三种用法:

用法 怎么写


做片头黑场 color=c=black:d=0.3 再 concat 给字幕留位置 主画面下面接一条黑场 当编码基准 用同样参数编一遍黑场,看文件多大

第一条在 7.11.3 用过:黑场 0.3 秒垫在片头,接缝处不会突跳。 第二条是「画面在下、字幕区在上」的版式,黑场就是那块留白。

第三条挺实用:黑场是「最省码率」的画面,用它试参数能看出一套编码设置的下限。 如果连黑场都编出很大的文件,说明码率参数给高了,或者 GOP 设得太短。

反过来也成立:拿 testsrc 编一遍,是「最费码率」的一端。 两端各试一次,参数合不合适就有感觉了。

五、动手 Demo:四色、两种时长

下面这段代码先跑四种颜色,各量左上角像素与帧数; 再把 d 换成 2,确认帧数是 50。

import av

print(u"--- 四种颜色、d=1 出几帧")
for c in (u"black", u"white", u"0x336699", u"red"):
    g = av.filter.Graph()
    s = g.add(u"color", u"c=%s:s=160x90:r=25:d=1" % c)
    sk = g.add(u"buffersink")
    s.link_to(sk)
    g.configure()
    n, px = 0, None
    for _ in range(200):
        try:
            fr = sk.pull()
        except Exception:
            break
        if px is None:
            px = [int(v) for v in fr.to_ndarray(format=u"rgb24")[0, 0]]
        n += 1
    print(u"  c=%-10s 左上 %-18s %d 帧" % (c, px, n))

print(u"--- d=2")
g = av.filter.Graph()
s = g.add(u"color", u"c=black:s=160x90:r=25:d=2")
sk = g.add(u"buffersink")
s.link_to(sk)
g.configure()
n = 0
for _ in range(200):
    try:
        sk.pull()
    except Exception:
        break
    n += 1
print(u"  d=2 共 %d 帧" % n)

实跑输出:

--------------------------------------------------------------------
7.16.2 生成纯色视频
--------------------------------------------------------------------

**① color 的四个参数**

**`color` 在 7.4.6 已经用过,这里补全它的参数:**

  参数     写什么                默认
  ------------------------------------------
  c        颜色名或十六进制      black
  s        分辨率,如 160x90     320x240
  r        帧率                  25
  d        时长(秒)            不限

**`d` 不写就是无限长——跟 `nullsrc`、`anullsrc` 一样。**
**所以造纯色视频必须给 `d` 或者在外面加 `-t`,否则它会一直造下去。**

**② 四种颜色与帧数,实测**

  c 写什么     左上角像素          d=1 出几帧
  -----------------------------------------------
  black        [0, 0, 0]           25
  white        [255, 255, 255]     25
  0x336699     [49, 100, 151]      25
  red          [253, 0, 0]         25

**`d=1` 在 25 帧率上出 25 帧,`d=2` 出 50 帧——正好是「秒 × 帧率」。**
**这个数可以用来校验时长算得对不对。**

**红色出来是 253 不是 255,还是 YUV 范围压缩那个零头;**
**十六进制的 `0x336699` 出来是 `[49, 100, 151]`,也在 255 以内打了个折。**

**③ 跟 nullsrc 的区别**

  滤镜        画出什么                    典型用途
  -------------------------------------------------------------------
  color       指定的纯色                  黑场、占位、垫片
  nullsrc     全 0 的裸帧(看着发绿)     当画布喂给 crop/overlay
  testsrc     彩条加计时码                测同步、测编码

**`nullsrc` 三平面全是 0,转 RGB 是 `[0, 135, 0]`——带绿味,不是黑。**
**要黑就得写 `color=c=black`,别拿 `nullsrc` 当黑场用。**

**④ 黑幕视频的三种用法**

  用法             怎么写
  ---------------------------------------------------------
  做片头黑场       color=c=black:d=0.3 再 concat
  给字幕留位置     pad 补黑边,或者主画面下面接黑场
  当编码基准       同样的码率参数编一遍黑场,看文件多大

**第三条挺实用:黑场是「最省码率」的画面,用它试参数能看出一套编码设置的下限。**
**如果连黑场都编出很大的文件,说明码率参数给高了。**

前四行跟本节那张表一一对上,四种颜色都出 25 帧。 red 是 253、0x336699 是 [49, 100, 151],都是 YUV 范围压缩留下的零头。

最后一行 d=2 出 50 帧,说明时长与帧数就是简单的乘法。 这条在算「片头要多长」时很有用:0.3 秒就是 7.5 帧,实际会出 8 帧。

代码里用 for _ in range(200) 兜底,是因为滤镜源可以无限吐帧, 不设上限、万一 d 没生效就会卡死。 写这种「拉源」的代码,永远要有一个帧数上限。

30 秒实验

  1. 换尺寸:把 s=160x90 改成 s=640x360,看编码出来的文件是不是变大。
  2. 试十六进制:把颜色写成 0xFF0000,跟 red 比一比左上角像素。
  3. 去掉 d:把 d=1 删掉,看那个 200 次的上限是怎么兜住它的。

常见误区

  1. 拿 nullsrc 当黑场。它是 YUV 全 0,出来是绿的。
  2. 不写 d 也不加 -t。无限长的源会把命令挂住。
  3. 以为纯红就是 255。YUV 走一趟,出来是 253。
自测三问(点开对答案) 1. `color` 的四个参数是什么? —— `c` 颜色、`s` 分辨率、`r` 帧率、`d` 时长。 2. `d=2` 在 25 帧率上出几帧? —— 50 帧,正好是 2 × 25。 3. `nullsrc` 直接当黑场用会怎样? —— 出来是 `[0, 135, 0]` 那种发绿的画面,不是黑。

相关笔记