热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[翻译]FFmpegFiltersDocumentation

注:本文是我在学习FFmpegFiltersDocumentation过程中的中文翻译笔记,为避免英译中过程中一些死板的字面意思引起读者错误理解,有时候我还会加上一些个人注解,若有

注:本文是我在学习FFmpeg Filters Documentation过程中的中文翻译笔记,为避免英译中过程中一些死板的字面意思引起读者错误理解,有时候我还会加上一些个人注解,若有不同见解,请最好参考原文档学习。本翻译仅供参考,转载请注明!





1. 简介

本文档将描述由libavfilter库提供的过滤器(filters)源(sources)接收器(sinks)


关于将Filter翻译为过滤器还是滤波器一直没定论,同时sink也没有比较贴切的中文名词可以放在本语境中。为避免中文翻译之后产生歧义且便于音视频开发者阅读,后续文章中提及上面三个对象以及类似input pad这种不好直接翻译的名词时均用英文表示。



2. Filter

FFmpeg中的Filter相关功能是由库libavfilter提供的。一个Filter可以有N个输入和N个输出(N ≥ 0)。

假设我们现在想将一个视频是上半部分垂直翻转到视频的下半部分镜像显示,我们该怎么做呢?莫慌,我们将以下图作为例子介绍filter处理这个事情的大致流程:

[main]
input --> split ---------------------> overlay --> output
| ^
|[tmp] [flip]|
+-----> crop --> vflip -------+

从上面的filtergraph中可以看出,我们将输入流先分割成两个流并分别被标记为[main][tmp]标签,然后将流[tmp] 经过crop(裁剪)和vflip(垂直翻转)两个过滤器的处理后标记为流[flip],最终将流[flip]这路流overlay(覆盖)到[main]这路流上面去。于是我们可以使用以下命令来实现我们上面的思路:

ffmpeg -i INPUT -vf "split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2" OUTPUT

执行上述命令进行实验之后你会发现,输出的视频是原始视频上半部分垂直翻转镜像的结果,符合预期。

同个链路的Filters使用逗号, 来分隔,每条链路之间用分号; 来分隔。从上面的例子中我们可以看出,cropvflip属于同一条链路,而splitoverlay属于另外独立的两个链路。同时,在每个链路连接点处我们还是用方括号[]的形式来标记链路的输入输出(可以理解为给它们起别名)。

一些过滤器能接受输入参数列表,形式通常是在过滤器名称和等号后面指定,并用冒号彼此隔开,如crop=iw:ih/2:0:0 表示要从原始视频中裁剪出一样宽,一半高的视频。(详见下文的crop过滤器详细介绍)

通常情况下filter都有输入输出,但是在FFmpeg的世界里还存在两种特殊的filter,即:



  • source filters: 没有任何输入

  • sink filters: 没有任何输出


3. graph2dot

不重要,先不翻译


4. Filtergraph

Filtergraph是链接多个Filter的有向图。

它可以包含循环,各个Filter之间也可以有多个链接。每个链接有一个input pad连接到一个Filter并从那里获取输入,有一个output pad连接到另一个Filter提供输出。所有的Filter都是已经注册在程序中的。没有输入的Filter叫source,没有输出的Filter叫sink


4.1 Filtergraph 语法

每个Filtergraph都有对应的结构化的文本表示:



  • 对于命令ffmpeg来说有-filter, -vf, -af-filter_complex这些选项

  • 对于命令ffplay来说有-vf, -af 这些选项


可参考源码libavfilter/avfilter.havfilter_graph_parse_ptr()了解更多细节


从整体看,Filtergraph包含Filterchain,而Filterchain又包含了Filter



  • filtergraph是由一个或多个filterchain组成,filterchain之间使用分号; 来分隔

  • filterchain是由一个或多个filter线性连接而成,filter之间使用逗号, 来分隔

  • filter的语法格式为:[in_link_1]...[in_link_N]filter_name@id=arguments[out_link_1]...[out_link_M]。顾名思义,filter_name就是你所要使用的filter的名称,它必定是已经在libavfilter中有注册的,后面的@id是可选的(基本没用到);紧跟着的=arguments也是可选填的(有些filter并不需要参数),arguments通常有如下格式:

    • : 来分隔一系列值。(这种情况下参数的顺序就是固定的,值的顺序必须按照filter声明的参数顺序来一个个占坑,类似平时写程序时函数调用填实参一样)

    • : 来分隔一系列的key=value的键值对。(这种情况下参数的顺序就不是固定的了,类似Javascript或者Python的指定关键字参数

    • : 来分隔一系列值,之后跟着一系列的key=value的键值对,值必须在键值对前面。(同上,类似Javascript或者Python这类语言的函数调用方式)

    • 有时候value本身就是要填一系列参数值的,那么需要用|来拼接(参考format这个filter)



从上面可以看出,[]=;,这些字符对于参数列表都是特殊字符,所以在参数列表中若要用到特殊字符,可以用单引号''将参数列表包起来,然后用\对特殊字符进行转义。

Filter的名称和参数前后是允许放置一个或多个链接标签link label)的。所谓的链接标签就是一个链接(link)的别名,可以将它们关联到Filter的输入/输出。放在前面的链接标签in_link_1 ... in_link_N 被关联到Filter的input pad,后面的out_link_1 ... out_link_M 被关联到Filter的output pad。当在Filtergraph中匹配到两个同名的链接标签时,Filter将创建其对应的input padoutput pad之间的链接。

如果一个Filter的output pad没被标记链接标签,则它会被默认链接到后续的Filter中第一个未标记链接标签的input pad,如:

nullsrc, split[L1], [L2]overlay, nullsink

上面的split有两个output pad,一个是[L1],另一个是匿名的;而overlay又拥有两个input pad,一个是[L2],另一个是匿名的;因此这两个匿名的pad会被链接起来:split -> overlay

缺省情况下,第一个Filter的输入标签为[in],最后一个Filter的输出标签为[out]。如下面两个Filtergraph是一样的:

ffmpeg -i INPUT -vf "split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2" OUTPUT
ffmpeg -i INPUT -vf "[in] split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2 [out]" OUTPUT

对于一个完整可用的Filterchain来说,所有匿名的链接标签必须有被链接。

对于一个Filtergraph来说,只有所有的Filterchain的input padoutput pad都被连接起来,才是一个有效可用的Filtergraph。

libavfilter在处理Filtergraph过程中当遇到有格式转换的时候会自动插入scale这个Filter,因此你可以在Filtergraph描述中的可能会隐式包含scale的地方前面加上你要指定的缩放参数:sws_flags=flags;

下面是针对Filtergraph语法的一个BNF描述:

NAME ::= sequence of alphanumeric characters and '_'
FILTER_NAME ::= NAME["@"NAME]
LINKLABEL ::= "[" NAME "]"
LINKLABELS ::= LINKLABEL [LINKLABELS]
FILTER_ARGUMENTS ::= sequence of chars (possibly quoted)
FILTER ::= [LINKLABELS] FILTER_NAME ["=" FILTER_ARGUMENTS] [LINKLABELS]
FILTERCHAIN ::= FILTER [,FILTERCHAIN]
FILTERGRAPH ::= [sws_flags=flags;] FILTERCHAIN [;FILTERGRAPH]

4.2 关于Filtergraph的字符转义

详见:(ffmpeg-utils)the "Quoting and escaping" section in the ffmpeg-utils(1) manual。



  1. 优先考虑Filter的参数值本身是否包含:\这些特殊字符

  2. 再考虑整个Filterchain中是否包含\或者[],=;这些特殊字符

  3. 最后如果你是使用命令行,还要从shell命令行的角度去考虑shell语句级别的字符转义

举个例子,假设你要用drawtext这个Filter来给视频加上文字:

this is a 'string': may contain one, or more, special characters

根据第1点提到的,它包含了':两个特殊字符,于是你要这么做:

text=this is a \'string\'\: may contain one, or more, special characters

根据第2点提到的,它包含了\转义字符和', 这些特殊字符,于是你要这么做:

drawtext=text=this is a \\\'string\\\'\\: may contain one\, or more\, special characters

根据第3点提到的,如果你要在shell上使用这个命令,还需要这么做:

-vf "drawtext=text=this is a \\\\\\'string\\\\\\'\\\\: may contain one\\, or more\\, special characters"

5. 时间轴编辑

未完待续




  • https://ffmpeg.org/ffmpeg-filters.html#Filtering-Introduction

  • https://wiki.multimedia.cx/index.php/FFmpeg_filter_HOWTO




推荐阅读
  • 本文详细介绍了Java中org.neo4j.helpers.collection.Iterators.single()方法的功能、使用场景及代码示例,帮助开发者更好地理解和应用该方法。 ... [详细]
  • 本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ... [详细]
  • 解决Element UI中Select组件创建条目为空时报错的问题
    本文介绍如何在Element UI的Select组件中使用allow-create属性创建新条目,并处理创建条目为空时出现的错误。我们将详细说明filterable属性的必要性,以及default-first-option属性的作用。 ... [详细]
  • 本文详细介绍了中央电视台电影频道的节目预告,并通过专业工具分析了其加载方式,确保用户能够获取最准确的电视节目信息。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • 本文介绍了如何使用JQuery实现省市二级联动和表单验证。首先,通过change事件监听用户选择的省份,并动态加载对应的城市列表。其次,详细讲解了使用Validation插件进行表单验证的方法,包括内置规则、自定义规则及实时验证功能。 ... [详细]
  • 本文详细解析了Python中的os和sys模块,介绍了它们的功能、常用方法及其在实际编程中的应用。 ... [详细]
  • Scala 实现 UTF-8 编码属性文件读取与克隆
    本文介绍如何使用 Scala 以 UTF-8 编码方式读取属性文件,并实现属性文件的克隆功能。通过这种方式,可以确保配置文件在多线程环境下的一致性和高效性。 ... [详细]
  • Python实现照片磨皮效果
    本文介绍如何使用Python和OpenCV库来实现照片的磨皮效果,使图片更加平滑并提升整体美感。 ... [详细]
  • 毕业设计:基于机器学习与深度学习的垃圾邮件(短信)分类算法实现
    本文详细介绍了如何使用机器学习和深度学习技术对垃圾邮件和短信进行分类。内容涵盖从数据集介绍、预处理、特征提取到模型训练与评估的完整流程,并提供了具体的代码示例和实验结果。 ... [详细]
  • JavaScript实现表格数据的实时筛选功能
    本文介绍如何使用JavaScript实现对表格数据的实时筛选,帮助开发者提高用户体验。通过简单的代码示例,展示如何根据用户输入的关键字动态过滤表格内容。 ... [详细]
  • 对象自省自省在计算机编程领域里,是指在运行时判断一个对象的类型和能力。dir能够返回一个列表,列举了一个对象所拥有的属性和方法。my_list[ ... [详细]
  • 解读MySQL查询执行计划的详细指南
    本文旨在帮助开发者和数据库管理员深入了解如何解读MySQL查询执行计划。通过详细的解析,您将掌握优化查询性能的关键技巧,了解各种访问类型和额外信息的含义。 ... [详细]
  • 本教程涵盖OpenGL基础操作及直线光栅化技术,包括点的绘制、简单图形绘制、直线绘制以及DDA和中点画线算法。通过逐步实践,帮助读者掌握OpenGL的基本使用方法。 ... [详细]
author-avatar
袁善恩芷恩
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有