🎬 第六章 FFmpeg命令行实现图片水印及文字跑马灯
📄 一句话概括

查参数的正路是 ffmpeg -h filter=drawtext;没有滤镜时,还能用「故意写错」当探针。 两级探针:先问滤镜在不在,再问参数名认不认。

📝 本节和前面几节的关系

上一节用了 fontsize、fontcolor 这些参数,但没说怎么知道它们存在。 这一节讲「遇到一个陌生滤镜,怎么把它的参数摸清楚」。

一、第一级:滤镜本身在不在

拿四个名字去建图,看它报什么:

试什么 报什么 说明


drawtext no filter drawtext 这滤镜不存在 delogo no filter delogo 这滤镜不存在 subtitles no filter subtitles 这滤镜不存在 drawbox 建成了 这滤镜存在

no filter xxx 这句话很有用:它把「缺滤镜」与「参数写错」分得干干净净。 很多人把这两件事混着查,白折腾很久。

先跑这一级,确认滤镜在,再去纠参数;顺序反了,会一直在错的地方找原因。

二、第二级:参数名认不认

拿还在的 drawbox 演示:故意传一个不存在的参数名。

试着传进去 认不认 这个参数干什么


x=10:y=10:w=40:h=20 认 位置与尺寸 color=red 认 边框颜色 t=fill 认 t 是 thickness 简写 thickness=3 认 线宽,不写就是 3 replace=1 认 不透明覆盖 enable=1 认 时间开关 xx=10 不认 故意写错的名字 box=1 不认 drawtext 的参数

最后两行最有价值:xx 与 box 都被拒,报的是 Option not found。 box 是 drawtext 的参数,drawbox 不认。

这说明参数是「每个滤镜各自一张表」,不能跨滤镜套用。 看到别人的命令里有个参数,先确认那个滤镜到底认不认。

三、drawtext 的参数表

下面这张表来自文档,本机没法实测(没这个滤镜):

参数 作用 典型值


text 要写的文字 'hello' fontfile 字体文件路径 'C\:/…/msyh.ttc' fontsize 字号(像素) 24 fontcolor 颜色,可带 @透明度 [email protected] x / y 位置表达式 w-tw-10 / h-th-10 box、boxcolor 文字底衬与颜色 1、[email protected] borderw 描边宽度 2 shadowx、shadowy 阴影偏移 2、2

这张表里真正天天用到的只有三项:text、fontfile、x 与 y。 其余都可以先不记——参数太多记不住,用探针查比背下来可靠。

真要知道全量参数,ffmpeg -h filter=drawtext 会打出完整清单, 含类型、默认值、取值范围,比任何二手笔记都准。

四、动手 Demo:两级探针

先用四个滤镜名去建图,看「存在」这一级的报错。 再拿 drawbox 试八个参数名,其中两个是故意写错的。

import av
from fractions import Fraction

for name in (u"drawtext", u"delogo", u"subtitles", u"drawbox"):
    try:
        av.filter.Graph().add(name)
        print(u"%-10s 建成" % name)
    except Exception as e:
        print(u"%-10s %s" % (name, str(e)[:26]))

def probe(args):
    try:
        g = av.filter.Graph()
        a = g.add_buffer(width=160, height=90, format=u"yuv420p",
                         time_base=Fraction(1, 25))
        f = g.add(u"drawbox", args)
        s = g.add(u"buffersink")
        a.link_to(f)
        f.link_to(s)
        g.configure()
        return u"认"
    except Exception:
        return u"不认"

for a_ in (u"x=10:y=10:w=40:h=20", u"color=red", u"t=fill",
           u"thickness=3", u"replace=1", u"enable=1",
           u"xx=10", u"box=1"):
    print(u"%-22s %s" % (a_, probe(a_)))

实跑输出:

--------------------------------------------------------------------
6.3.3 查看 drawtext 的参数——用报错当探针
--------------------------------------------------------------------

**正常的办法是 `ffmpeg -h filter=drawtext`。**
**但本机连 drawtext 都没有,这时还有一招更狠的:让它报错。**

**① 第一级探针:滤镜在不在**

  试什么        报什么                  说明
  ------------------------------------------------------------
  drawtext      no filter drawtext      这个滤镜根本不存在
  delogo        no filter delogo        这个滤镜根本不存在
  subtitles     no filter subtitles     这个滤镜根本不存在
  drawbox       建成了                  这个滤镜存在

**报错原文是 `no filter drawtext`,一句话就把「缺滤镜」和「参数写错」分开了。**
**很多人把这两件事混在一起查,白折腾半天——先分清层级,再往下走。**

**② 第二级探针:参数名在不在**

**拿还在的 drawbox 演示:故意写一个不存在的参数名。**

  试着传进去              认不认                       这个参数干什么
  -------------------------------------------------------------------------------------------
  x=10:y=10:w=40:h=20     认                           位置与尺寸
  color=red               认                           边框颜色
  t=fill                  认                           t 是 thickness 简写,fill 表示填满
  thickness=3             认                           线宽,不写就是 3
  replace=1               认                           不透明覆盖,不混合
  enable=1                认                           时间开关,控制哪几帧生效
  xx=10                   不认(Option not found)     故意写错的名字
  box=1                   不认(Option not found)     drawtext 的参数,这里不认

**最后两行最有价值:`xx` 与 `box` 都被拒了,报的是 `Option not found`。**
**`box` 是 drawtext 的参数,drawbox 不认——**
**这说明参数是「每个滤镜各自一张表」,不能跨滤镜套用。**

**③ drawtext 的参数表(来自文档,本机无法实测)**

  参数                  作用                   典型值
  -----------------------------------------------------------------------------
  text                  要写的文字             'hello'
  fontfile              字体文件路径           'C\:/Windows/Fonts/msyh.ttc'
  fontsize              字号(像素)           24
  fontcolor             颜色,可带 @透明度     [email protected]
  x / y                 位置表达式             w-tw-10 / h-th-10
  box / boxcolor        文字底衬与颜色         1 / [email protected]
  shadowx / shadowy     阴影偏移               2 / 2

**这张表里有三项是真正会天天用到的:text、fontfile、x 与 y。**
**其余都可以先不记——参数太多记不住,用探针查比背下来可靠。**

av.filter.Graph().add(name) 不接任何输入,只建一个滤镜对象。 名字不存在就在这一步抛错,是最省事的「存在性检查」。

参数名的检查要到 configure() 才发生,所以 probe 里必须走完整条链。 只 add 不 configure,写错参数名也不会报错——这就是很多人查不出来的原因。

报错原文是 Option not found,不是「参数无效」。 它检查的是「这个名字在不在表里」,还没到「值合不合法」那一步。

30 秒实验

  1. 查全量:ffmpeg -h filter=drawbox,把它打出的参数与上面那张表对一遍。
  2. 试值域:给 thickness=-1,看它是报错还是悄悄改成默认值。
  3. 换滤镜:把 drawbox 换成 crop 或 scale,看哪些参数名通用、哪些不通用。

常见误区

  1. 把「缺滤镜」当成「参数写错」。报 no filter xxx 就是前者。
  2. 只 add 不 configure 就下结论。参数名的检查在配置阶段。
  3. 跨滤镜套参数。box 是 drawtext 的,drawbox 不认。
自测三问(点开对答案) 1. `no filter drawtext` 说明什么? —— 这份构建里根本没有 drawtext 这个滤镜,与参数无关。 2. `Option not found` 说明什么? —— 滤镜在,但你写的参数名不在它的选项表里。 3. 为什么参数名检查要到 configure 才发生? —— 选项是在初始化滤镜上下文时逐个设置的,建对象阶段还没轮到。

相关笔记