乐趣区

关于音视频:音视频编解码流程与如何使用-FFMPEG-命令进行音视频处理

一、前言

FFMPEG 是特地弱小的专门用于解决音视频的开源库。你既能够应用它的 API 对音视频进行解决,也能够应用它提供的工具,如 ffmpeg, ffplay, ffprobe,来编辑你的音视频文件。

本文将简要介绍一下 FFMPEG 库的根本目录构造及其性能,而后具体介绍一下咱们在日常工作中,如何应用 ffmpeg 提供的工具来解决音视频文件。


二、FFMPEG 目录及作用

libavcodec: 提供了一系列编码器的实现。

libavformat: 实现在流协定,容器格局及其本 IO 拜访。

libavutil: 包含了 hash 器,解码器和各利工具函数。

libavfilter: 提供了各种音视频过滤器。

libavdevice: 提供了拜访捕捉设施和回放设施的接口。

libswresample: 实现了混音和重采样。

libswscale: 实现了色调转换和缩放工能。


三、FFMPEG 基本概念

在解说 FFMPEG 命令之前,咱们先要介绍一些音视频格局的基要概念。

(1) 音/视频流

在音视频畛域,咱们把一路音/视频称为一路 。如咱们小时候常常应用 VCD 看港片,在里边能够抉择粤语或国语声音,其实就是 CD 视频文件中寄存了两路音频流,用户能够抉择其中一路进行播放。

(2) 容器

咱们个别把 MP4、 FLV、MOV 等文件格式称之为 容器。也就是在这些罕用格式文件中,能够寄存多路音视频文件。以 MP4 为例,就能够寄存一路视频流,多路音频流,多路字幕流。

(3) channel

channel 是音频中的概念,称之为声道。在一路音频流中,能够有单声道,双声道或立体声。


四、FFMPEG 性能分类

咱们按应用目标能够将 FFMPEG 命令分成以下几类:

  • 根本信息查问命令
  • 录制
  • 合成 / 复用
  • 解决原始数据
  • 滤镜
  • 切割与合并
  • 图/视互转
  • 直播相干

除了 FFMPEG 的根本信息查问命令外,其它命令都按下图所示的流程解决音视频。

而后将编码的数据包传送给解码器(除非为数据流抉择了流拷贝,请参阅进一步形容)。解码器产生未压缩的帧(原始视频 / PCM 音频 / …),能够通过滤波进一步解决(见下一节)。在过滤之后,帧被传递到编码器,编码器并输入编码的数据包。最初,这些传递给复用器,将编码的数据包写入输入文件。

默认状况下,ffmpeg 只蕴含输出文件中每种类型(视频,音频,字幕)的一个流,并将其增加到每个输入文件中。它依据以下规范筛选每一个的“最佳”:对于视频,它是具备最高分辨率的流,对于音频,它是具备最多 channel 的流,对于字幕,是第一个字幕流。在雷同类型的几个流相等的状况下,抉择具备最低索引的流。

您能够通过应用 -vn / -an / -sn / -dn 选项来禁用某些默认设置。要进行全面的手动管制,请应用 -map 选项,该选项禁用刚形容的默认设置。


五、根本信息查问命令

MPEG 能够应用上面的参数进行根本信息查问。例如,想查问一下当初应用的 FFMPEG 都反对哪些 filter,就能够用 ffmpeg -filters 来查问。具体参数阐明如下:

参数 阐明


-version 显示版本。


-formats 显示可用的格局(包含设施)。


-demuxers 显示可用的 demuxers。


-muxers 显示可用的 muxers。


-devices 显示可用的设施。


-codecs 显示 libavcodec 已知的所有编解码器。


-decoders 显示可用的解码器。


-encoders 显示所有可用的编码器。


-bsfs 显示可用的比特流 filter。


-protocols 显示可用的协定。


-filters 显示可用的 libavfilter 过滤器。


-pix_fmts 显示可用的像素格局。


-sample_fmts 显示可用的采样格局。


-layouts 显示 channel 名称和规范 channel 布局。


-colors 显示辨认的色彩名称。


接下来介绍的是 FFMPEG 解决音视频时应用的命令格局与参数

六、命令根本格局及参数

上面是 FFMPEG 的根本命令格局:

ffmpeg [global_options] {[input_file_options] -i input_url} ...

                         {[output_file_options] output_url} ...

ffmpeg 通过 -i 选项读取输任意数量的输出“文件”(能够是惯例文件,管道,网络流,抓取设施等,并写入任意数量的输入“文件”。

原则上,每个输出 / 输入“文件”都能够蕴含任意数量的不同类型的视频流(视频 / 音频 / 字幕 / 附件 / 数据)。流的数量和 / 或类型是由容器格局来限度。抉择从哪个输出进入到哪个输入将主动实现或应用 -map 选项。

要援用选项中的输出文件,您必须应用它们的索引(从 0 开始)。例如。第一个输出文件是 0,第二个输出文件是 1,等等。相似地,文件内的流被它们的索引援用。例如。2:3 是指第三个输出文件中的第四个流。


下面就是 FFMPEG 解决音视频的常用命令,上面是一些罕用参数:

(1) 主要参数

-f fmt(输出 / 输入)

强制输出或输入文件格式。格局通常是自动检测输出文件,并从输入文件的文件扩展名中猜想进去,所以在大多数状况下这个选项是不须要的。

-i url(输出)

输出文件的网址

-y(全局参数)

笼罩输入文件而不询问。

-n(全局参数)

不要笼罩输入文件,如果指定的输入文件曾经存在,请立刻退出。

-c [:stream_specifier] codec(输出 / 输入,每个流)

抉择一个编码器(当在输入文件之前应用)或解码器(当在输出文件之前应用时)用于一个或多个流。codec 是解码器 / 编码器的名称或 copy(仅输入)以批示该流不被从新编码。如:ffmpeg -i INPUT -map 0 -c:v libx264 -c:a copy OUTPUT

-codec [:stream_specifier]编解码器(输出 / 输入,每个流)

同 -c

-t duration(输出 / 输入)

当用作输出选项(在 -i 之前)时,限度从输出文件读取的数据的持续时间。当用作输入选项时(在输入 url 之前),在持续时间达到持续时间之后进行输入。

-ss 地位(输出 / 输入)

当用作输出选项时(在 -i 之前),在这个输出文件中寻找地位。请留神,在大多数格局中,不可能准确搜寻,因而 ffmpeg 将在地位之前寻找最近的搜寻点。当转码和 -accurate_seek 被启用时(默认),搜寻点和地位之间的这个额定的分段将被解码和抛弃。当进行流式复制或应用 -noaccurate_seek 时,它将被保留。当用作输入选项(在输入 url 之前)时,解码但抛弃输出,直到工夫戳达到地位。

-frames [:stream_specifier] framecount(output,per-stream)

进行在帧计数帧之后写入流。

-filter [:stream_specifier] filtergraph(output,per-stream)

创立由 filtergraph 指定的过滤器图,并应用它来过滤流。filtergraph 是利用于流的 filtergraph 的形容,并且必须具备雷同类型的流的单个输出和单个输入。在过滤器图形中,输出与标签中的标签相关联,标签中的输入与标签相关联。无关 filtergraph 语法的更多信息,请参阅 ffmpeg-filters 手册。


(2) 视频参数

-vframes num(输入)

设置要输入的视频帧的数量。对于 -frames:v,这是一个过期的别名,您应该应用它。

-r [:stream_specifier] fps(输出 / 输入,每个流)

设置帧率(Hz 值,分数或缩写)。作为输出选项,疏忽存储在文件中的任何工夫戳,依据速率生成新的工夫戳。这与用于 -framerate 选项不同(它在 FFmpeg 的旧版本中应用的是雷同的)。如果有疑难,请应用 -framerate 而不是输出选项 -r。作为输入选项,复制或抛弃输出帧以实现恒定输入帧频 fps。

-s [:stream_specifier]大小(输出 / 输入,每个流)

设置窗口大小。作为输出选项,这是 video_size 专用选项的快捷方式,由某些分帧器辨认,其帧尺寸未被存储在文件中。作为输入选项,这会将缩放视频过滤器插入到相应过滤器图形的开端。请间接应用比例过滤器将其插入到结尾或其余中央。格局是 ’wxh’(默认 – 与源雷同)。

-aspect [:stream_specifier] 宽高比(输入,每个流)

设置方面指定的视频显示宽高比。aspect 能够是浮点数字符串,也能够是 num:den 模式的字符串,其中 num 和 den 是宽高比的分子和分母。例如“4:3”,“16:9”,“1.3333”和“1.7777”是无效的参数值。如果与 -vcodec 正本一起应用,则会影响存储在容器级别的宽高比,但不会影响存储在编码帧中的宽高比(如果存在)。

-vn(输入)

禁用视频录制。

-vcodec 编解码器(输入)

设置视频编解码器。这是 -codec:v 的别名。

-vf filtergraph(输入)

创立由 filtergraph 指定的过滤器图,并应用它来过滤流。


(3) 音频参数

-aframes(输入)

设置要输入的音频帧的数量。这是 -frames:a 的一个过期的别名。

-ar [:stream_specifier] freq(输出 / 输入,每个流)

设置音频采样频率。对于输入流,它默认设置为相应输出流的频率。对于输出流,此选项仅实用于音频捕捉设施和原始分路器,并映射到相应的分路器选件。

-ac [:stream_specifier]通道(输出 / 输入,每个流)

设置音频通道的数量。对于输入流,它默认设置为输出音频通道的数量。对于输出流,此选项仅实用于音频捕捉设施和原始分路器,并映射到相应的分路器选件。

-an(输入)

禁用录音。

-acodec 编解码器(输出 / 输入)

设置音频编解码器。这是 -codec 的别名:a。

-sample_fmt [:stream_specifier] sample_fmt(输入,每个流)

设置音频采样格局。应用 -sample_fmts 获取反对的样本格局列表。

-af filtergraph(输入)

创立由 filtergraph 指定的过滤器图,并应用它来过滤流。


七、性能阐明

(1) 录制
ffmpeg -f avfoundation -list_devices true -i ""
(2) 录屏
ffmpeg -f avfoundation -i 1 -r 30 out.yuv
  • -f 指定应用 avfoundation 采集数据。
  • -i 指定从哪儿采集数据,它是一个文件索引号。在我的电脑上,1 代表桌面(能够通过下面的命令查问设施索引号)。
  • -r 指定帧率。按 ffmpeg 官网文档说 -r 与 -framerate 作用雷同,但理论测试时发现不同。-framerate 用于限度输出,而 -r 用于限度输入。

留神,桌面的输出对帧率没有要求,所以不必限度桌面的帧率。其实限度了也没用。

(3) 录屏 + 声音
ffmpeg  -f avfoundation -i 1:0  -r 29.97 -c:v libx264 -crf 0 -c:a libfdk_aac -profile:a aac_he_v2 -b:a 32k  out.flv
  • -i 1:0 冒号后面的 “1” 代表的屏幕索引号。冒号前面的 ”0″ 代表的声音索相号。
  • -c:v 与参数 -vcodec 一样,示意视频编码器。c 是 codec 的缩写,v 是 video 的缩写。
  • -crf 是 x264 的参数。0 表式无损压缩。
  • -c:a 与参数 -acodec 一样,示意音频编码器。
  • -profile 是 fdk_aac 的参数。aac_he_v2 表式应用 AAC_HE v2 压缩数据。
  • -b:a 指定音频码率。b 是 bitrate 的缩写, a 是 audio 的缩与。
(4) 录视频
ffmpeg -framerate 30 -f avfoundation -i 0 out.mp4
  • -framerate 限度视频的采集帧率。这个必须要依据提醒要求进行设置,如果不设置就会报错。
  • -f 指定应用 avfoundation 采集数据。
  • -i 指定视频设施的索引号。
(5) 视频 + 音频
ffmpeg -framerate 30 -f avfoundation -i 0:0 out.mp4
(6) 录音
ffmpeg -f avfoundation -i :0 out.wav
(7) 录制音频裸数据
ffmpeg  -f avfoundation -i :0 -ar 44100 -f s16le out.pcm
(8) 合成与复用

流拷贝是通过将 copy 参数提供给 -codec 选项来抉择流的模式。它使得 ffmpeg 省略了指定流的解码和编码步骤,所以它只能进行多路合成和多路复用。这对于更改容器格局或批改容器级元数据很有用。在这种状况下,上图将简化为:

因为没有解码或编码,速度十分快,没有品质损失。然而,因为许多因素,在某些状况下可能无奈失常工作。利用过滤器显然也是不可能的,因为过滤器解决未压缩的数据。

(9) 抽取音频流
ffmpeg -i input.mp4 -acodec copy -vn out.aac
  • acodec: 指定音频编码器,copy 指明只拷贝,不做编解码。
  • vn: v 代表视频,n 代表 no 也就是无视频的意思。
(10) 转换为 MP3 格局
ffmpeg -i input.mp4 -acodec libmp3lame  out.mp3
(11) 抽取视频流
ffmpeg -i input.mp4 -vcodec copy -an out.h264
  • vcodec: 指定视频编码器,copy 指明只拷贝,不做编解码。
  • an: a 代表视频,n 代表 no 也就是无音频的意思。
(12) 转格局
ffmpeg -i out.mp4 -vcodec copy -acodec copy out.flv

下面的命令表式的音频、视频都间接 copy,只是将 mp4 的封装格局转成了 flv。

(13) 音视频合并
ffmpeg -i out.h264 -i out.aac -vcodec copy -acodec copy out.mp4
(14) 提取 YUV 数据
ffmpeg -i input.mp4 -an -c:v rawvideo -pixel_format yuv420p out.yuv
# 播放
ffplay -s wxh out.yuv
  • -c:v rawvideo 指定将视频转成原始数据
  • -pixel_format yuv420p 指定转换格局为 yuv420p
(15) YUV 转 H264
ffmpeg -f rawvideo -pix_fmt yuv420p -s 320x240 -r 30 -i out.yuv -c:v libx264 -f rawvideo out.h264
(16) 提取 PCM 数据
ffmpeg -i out.mp4 -vn -ar 44100 -ac 2 -f s16le out.pcm
# 播放
ffplay -ar 44100 -ac 2 -f s16le -i out.pcm
(17) PCM 转 WAV
ffmpeg -f s16be -ar 8000 -ac 2 -acodec pcm_s16be -i input.raw output.wav
(18) 简略滤镜

在编码之前,ffmpeg 能够应用 libavfilter 库中的过滤器解决原始音频和视频帧。几个链式过滤器造成一个过滤器图形。ffmpeg 辨别两种类型的过滤器图形:简略和简单。

简略的过滤器图是那些只有一个输出和输入,都是雷同的类型。在下面的图中,它们能够通过在解码和编码之间插入一个额定的步骤来示意:

简略的 filtergraphs 配置了 per-stream-filter 选项(别离为视频和音频应用 -vf 和 -af 别名)。一个简略的视频 filtergraph 能够看起来像这样的例子:

请留神,某些滤镜会更改帧属性,但不会扭转帧内容。例如。上例中的 fps 过滤器会扭转帧数,但不会涉及帧内容。另一个例子是 setpts 过滤器,它只设置工夫戳,否则不扭转帧。

(19) 简单滤镜

简单的过滤器图是那些不能简略形容为利用于一个流的线性解决链的过滤器图。例如,当图形有多个输出和 / 或输入,或者当输入流类型与输出不同时,就是这种状况。他们能够用下图来示意:

简单的过滤器图应用 -filter_complex 选项进行配置。请留神,此选项是全局性的,因为简单的过滤器图形实质上不能与单个流或文件明确关联。

-lavfi 选项等同于 -filter_complex。

一个简单的过滤器图的一个简略的例子是笼罩过滤器,它有两个视频输出和一个视频输入,蕴含一个视频叠加在另一个下面。它的音频对应是 amix 滤波器。

(20) 增加水印
ffmpeg -i out.mp4  -vf "movie=logo.png,scale=64:48[watermask];[in][watermask] overlay=30:10 [out]" water.mp4
  • -vf 中的 movie 指定 logo 地位。scale 指定 logo 大小。overlay 指定 logo 摆放的地位。
(21) 删除水印

先通过 ffplay 找到要删除 LOGO 的地位

ffplay -i test.flv -vf delogo=x=806:y=20:w=70:h=80:show=1

应用 delogo 滤镜删除 LOGO

ffmpeg -i test.flv -vf delogo=x=806:y=20:w=70:h=80 output.flv
(22) 视频放大一倍
fmpeg -i out.mp4 -vf scale=iw/2:-1 scale.mp4
  • -vf scale 指定应用简略过滤器 scale,iw/2:-1 中的 iw 指定按整型取视频的宽度。-1 示意高度随宽度一起变动。
(23) 视频裁剪
ffmpeg -i VR.mov  -vf crop=in_w-200:in_h-200 -c:v libx264 -c:a copy -video_size 1280x720 vr_new.mp4

crop 格局:crop=out_w:out_h:x:y

  • out_w: 输入的宽度。能够应用 in_w 表式输出视频的宽度。
  • out_h: 输入的高度。能够应用 in_h 表式输出视频的高度。
  • x : X 坐标
  • y : Y 坐标

如果 x 和 y 设置为 0, 阐明从左上角开始裁剪。如果不写是从中心点裁剪。

(24) 倍速播放
ffmpeg -i out.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" speed2.0.mp4

-filter_complex 简单滤镜,[0:v]示意第一个(文件索引号是 0)文件的视频作为输出。setpts=0.5*PTS 示意每帧视频的 pts 工夫戳都乘 0.5,也就是差少一半。[v]示意输入的别名。音频同理就不详述了。

map 可用于解决简单输入,如能够将指定的多路流输入到一个输入文件,也能够指定输入到多个文件。”[v]” 简单滤镜输入的别名作为输入文件的一路流。下面 map 的用法是将简单滤镜输入的视频和音频输入到指定文件中。

(25) 对称视频
ffmpeg  -i out.mp4 -filter_complex "[0:v]pad=w=2*iw[a];[0:v]hflip[b];[a][b]overlay=x=w" duicheng.mp4
  • hflip 程度翻转

如果要批改为垂直翻转能够用 vflip。

(25) 画中画
ffmpeg -i out.mp4 -i out1.mp4 -filter_complex "[1:v]scale=w=176:h=144:force_original_aspect_ratio=decrease[ckout];[0:v][ckout]overlay=x=W-w-10:y=0[out]" -map "[out]" -movflags faststart new.mp4
(26) 录制画中画
ffmpeg  -f avfoundation -i "1" -framerate 30 -f avfoundation -i "0:0"

-r 30 -c:v libx264 -preset ultrafast

-c:a libfdk_aac -profile:a aac_he_v2 -ar 44100 -ac 2

-filter_complex "[1:v]scale=w=176:h=144:force_original_aspect_ratio=decrease[a];[0:v][a]overlay=x=W-w-10:y=0[out]"

-map "[out]" -movflags faststart -map 1:a b.mp4
(27) 多路视频拼接
ffmpeg  -f avfoundation -i "1" -framerate 30 -f avfoundation   -i "0:0" -r 30 -c:v libx264 -preset ultrafast -c:a libfdk_aac -profile:a aac_he_v2 -ar 44100 -ac 2 -filter_complex "[0:v]scale=320:240[a];[a]pad=640:240[b];[b][1:v]overlay=320:0[out]" -map "[out]" -movflags faststart  -map 1:a  c.mp4
(28) 裁剪
ffmpeg -i out.mp4 -ss 00:00:00 -t 10 out1.mp4
  • -ss 指定裁剪的开始工夫,准确到秒
  • -t 被裁剪后的时长。
(29) 合并

首先创立一个 inputs.txt 文件,文件内容如下:

file ‘1.flv’

file ‘2.flv’

file ‘3.flv’

而后执行上面的命令:

ffmpeg -f concat -i inputs.txt -c copy output.flv

(30) hls 切片
ffmpeg -i out.mp4 -c:v libx264 -c:a libfdk_aac -strict -2 -f hls  out.m3u8
  • -strict -2 指明音频使有 AAC。
  • -f hls 转成 m3u8 格局。
(31) 视频转 JPEG
ffmpeg -i test.flv -r 1 -f image2 image-%3d.jpeg
(32) 视频转 gif
ffmpeg -i test.flv -r 1 -f image2 image-%3d.jpeg
(33) 图片转视频
ffmpeg  -f image2 -i image-%3d.jpeg images.mp4
(34) 推流
ffmpeg -re -i out.mp4 -c copy -f flv rtmp://server/live/streamName
(35) 拉流保留
ffmpeg -i rtmp://server/live/streamName -c copy dump.flv
(36) 转流
ffmpeg -i rtmp://server/live/originalStream -c:a copy -c:v copy -f flv rtmp://server/live/h264Stream
(37) 实时推流
ffmpeg -framerate 15 -f avfoundation -i "1" -s 1280x720 -c:v libx264  -f  flv rtmp://localhost:1935/live/room
(38) 播放 YUV 数据
ffplay -pix_fmt nv12 -s 192x144 1.yuv
(39) 播放 YUV 中的 Y 立体
ffplay -pix_fmt nv21 -s 640x480 -vf extractplanes='y' 1.yuv
退出移动版