FFmpeg从入门到精通-云享读书会

2022-10-06 08:24:59 浏览数 (1)

前言

FFmpeg是一款开源软件,用于生成处理多媒体数据的各类库和程序。FFmpeg可以转码、处理视频和图片(调整视频、图片大小,去噪等)、打包、传输及播放视频。作为最受欢迎的视频和图像处理软件,它被来自各行各业的不同公司所广泛使用。

FFmpeg被称作是音视频领域的瑞士军刀,是音视频及相关领域是无人不晓,无人不知的项目, 只要了解多媒体音视频处理的人,都会感叹这个项目的强大。

FFmpeg项目由 Fabrice Bellard在2000年创立,到目前为止,经历了21年的演化。FFmpeg社区和其他多媒体项目互动频繁,这也是它成功的原因之一。在创立之初,有很多开发者同时活跃在Mplayer项目,到目前为止,FFmpeg项目的开发者仍然与VLC、MPV、dav1d、x264等多媒体开源项目有着广泛的重叠。2004年以后,FFmpeg社区基本由Michael Niedermayer领导。

在这近22年的风风雨雨中,FFmpeg一路走来也是经历过不少挫折,在2011年 FFmpeg 就因为核心成员意见不一导致分裂,差点最终导致整个项目消亡殆尽。最终的结果就是,项目创始人法布里斯贝拉选择了离开FFmpeg,但是随后他与其他一起出走的开发者创建另一知名开源编解码库项目Libav。 FFmpeg和 Libav ,就像南慕容和北乔峰一样,是当下所有主流播放器必备的编解码库,并且这些编解码库全部开源可免费使用无需额外付费。不过,虽然说是免费使用,但FFmpeg是基于LGPL/GPL开源的,这意味着如果某软件使用了FFmpeg的代码,那么这个软件涉及这些代码的部分,也必须开源,并且需要在使用其项目源代码和编解码库时注明来源。目前,FFmpeg不仅被大量免费软件使用,同时使用的,还有很多大型公司,例如:YouTube、iTunes、腾讯旗下产品、字节跳动旗下产品等。

当前文章内容来至 华为云 · 云享读书会 第13期 《FFmpeg从入门到精通》读书会直播视频的资料整理,《FFmpeg从入门到精通》的作者是一位典型的音视频技术爱好者,前后就职于广电巨头和音视频互联网公司,具有丰富的音视频直播和点播相关经验,对 WebRTC、FFmpeg 和 Electron 有非常深入的了解。

接下来会陆续按照几个章节由浅入深地介绍FFmpeg处理音视频的常用方法, 对音视频技术感兴趣的小伙伴能从中学到很多干货。

当前文章能学习的知识点:

(1)了解多媒体处理工具FFmpeg工具集

(2)了解音频文件的封装格式、编码格式

(3)了解视频文件的封装格式、编码格式

(4)掌握FFmpeg查看音视频媒体信息的方法

(5)掌握FFmpeg处理音视频文件的常用方法

一、多媒体处理工具 FFmpeg 工具集

(1)FFmpeg的发展

FFmpeg 是一个多媒体开源项目,项目地址:https://github.com/FFmpeg/FFmpeg

FFmpeg 最早是由法国天才程序员法布里斯·贝拉在 2000年时开发的,后来一直快速发展至今,当前最新的版本是 5.0。

目前,FFmpeg 已经被很多开源项目所采用,比如 ijkplayer、VLC、MPlayer、Blender、Google Chrome等。

(2)FFmpeg的组成

FFmpeg 工程内部根据功能划分了不同的模块,包括 AVFormat、AVCodec、AVFilter、AVDevice、AVUtil、swresample、swscale。

(3)FFmpeg的模块介绍

【1】AVFormat 是 FFmpeg 的封装模块,其中实现了目前多媒体领域中的绝大多数媒体 封装格式,包括封装和解封装,比如 MP4、FLV、MKV、TS 等文件封装格式,RTMP、 RTSP、HLS 等网络协议封装格式。另外,也支持自定义封装格式。

【2】AVCodec 是 FFmpeg 的编解码模块,其中实现了目前多媒体领域中的绝大多数媒体 编解码格式,包括编码和解码两大部分,比如 MPEG4、H264、H265 等视频格式,AAC、 MP3 等音频格式。另外,也支持自定义编解码格式。

【3】AVFilter 是 FFmpeg 的滤镜模块,其中实现了目前通用的音频、视频、字幕等滤 镜处理框架。

【4】AVDevice 是 FFmpeg 的设备管理模块,包括音频设备和视频设备。

【5】AVUtil 是 FFmpeg 的工具模块。

【6】swresample 是 FFmpeg 的音频转换模块,包括音频重采样、声道数调整等。

【7】swscale 是 FFmpeg 的视频图像转换模块,包括图像缩放、像素格式转换等。

FFmpeg开发库:

代码语言:javascript复制
(1)、libavutil是一个包含简化程序功能的库,其中包括随机数生成器,数据结构,数学例程,核心多媒体实用程序等。
(2)、libavcodec是一个库,其中包含音频/视频编解码器的解码器和编码器。
(3)、libavformat是一个包含用于多媒体容器格式的解复用器和复用器的库。
(4)、libavdevice是一个包含输入和输出设备的库,用于从许多常见的多媒体输入/输出软件框架(包Video4Linux,Video4Linux2,VfW和ALSA)中获取和呈现。
(5)、libavfilter是一个包含媒体过滤器的库。
(6)、libswscale是一个执行高度优化的图像缩放和颜色空间/像素格式转换操作的库。
(7)、libswresample是一个执行高度优化的音频重采样,重矩阵化和样本格式转换操作的库。

(4)FFmpeg的工具集

【1】ffmpeg 是 FFmpeg 工具集中的编解码工具。

【2】ffplay 是 FFmpeg 工具集中的播放器。

【3】ffprobe 是 FFmpeg 工具集中的多媒体分析工具。

(5)FFmpeg编译安装(linux)

【1】下载地址

代码语言:javascript复制
https://ffmpeg.org/download.html

【2】配置FFMPEG

代码语言:javascript复制
[root@wbyq ffmpeg-3.0.2]#./configure --enable-shared --enable-static --prefix=$PWD/_install --enable-gpl --extra-cflags=-I/home/wbyq/pc_work/x264-snapshot-20160527-2245/_install/include --extra-ldflags=-L/home/wbyq/pc_work/x264-snapshot-20160527-2245/_install/lib --enable-ffserver --enable-ffmpeg --enable-libx264
编译安装:
[root@wbyq ffmpeg-3.0.2]# make
[root@wbyq ffmpeg-3.0.2]# make install

FFMPEG最新版本4.2.2编译配置:
截止编写文档时,FFMPEG最新版本是4.2.2。
 
编译配置方法如下:
[root@wbyq ffmpeg-4.2.2]# ./configure --enable-static --enable-shared --prefix=$PWD/_install --extra-cflags=-I/home/wbyq/pc_work/x264-snapshot-20160527-2245/_install/include --extra-ldflags=-L/home/wbyq/pc_work/x264-snapshot-20160527-2245/_install/lib --enable-ffmpeg --enable-libx264 --enable-gpl
[root@wbyq ffmpeg-4.2.2]#make
[root@wbyq ffmpeg-4.2.2]#make install

二、视频文件的封装格式

FFmpeg 支持很多封装格式,包括 MP4、FLV、MKV、TS 等视频封装格式、MP3、AAC 等音频封装格式以及 RTMP、RTSP、HLS 等网络协议封装格式。 接下来,重点介绍 MP4 视频封装格式。

(1)MP4 封装格式

MP4 封装格式基本上可以认为是日常生活和工作中最常见的视频文件格式,主要是由于其广泛的适用性,不仅在PC端(windows、mac、linux)支持的非常好,而且在移动端(Android、iOS)也能流畅播放。

(2)MP4 格式标准

MP4 格式标准为 ISO-14496 Part 12 和 ISO-14496 Part 14,具体特征如下:

【1】MP4 文件由许多 Box 和 FullBox。

【2】FullBox 是 Box 的扩展,在 Header 中增加了8位version信息和24位的flags信息。

【3】每个 Box 由 Header 和 Data 两部分组成。

【4】Header 中包含了整个 Box 的长度大小(size)和类型(type)。

【5】Data 中包含了实际的数据,可以是纯数据,也可以是子 Box。当 Box 中的 Data 是一系列子Box 时,这个 Box 又被称为 Container(容器)。

(3)MP4 ftyp Box

ftyp Box,一般位于文件开始位置,其中包含了 MP4 视频文件的类型、版本、兼容协议等信息。

(4)MP4 moov容器

moov 容器中包含了 MP4 视频文件的媒体数据信息,内部又包含两个子容器:mvhd和trak,前者定义了文件头信息,后者定义了媒体文件中的track信息。

moov 容器一般默认会生成在 MP4 文件结尾,在线播放时需要加载完整个文件才能正常打开,为了能够快速打开视频,需要把 moov 容器放在 MP4 文件的前面。

(5)MP4 mdat Box

mdat Box,用来存放媒体文件的实际数据内容。

三、视频文件的编码格式

FFmpeg 支持很多视频编码格式,比如:MPEG4、H263、H264、H265、VP8、VP9 等。

接下来,重点介绍 H264 视频编码格式。

(1)H264的码率控制

【1】VBR:Variable BitRate,动态码率模式,其码率可以随着图像的复杂程度的不同 而变化,因此其编码效率比较高。

【2】CBR:Constant BitRate,恒定码率模式,由于码率恒定,有画面剧烈变化时,QP 参数会增大,图像质量会变差,当场景静止时,又浪费带宽。该模式的整体图像质量 不稳定。

【3】ABR:Average BitRate,平均码率模式,是 VBR 的一种衍生形式,在指定的文件 大小内,静态或者接近静态的画面部分使用相对较低的流量,复杂画面部分使用较高 的流量,可以视为是 VBR 和 CBR 的一种折衷方案。

(2)H264 的I帧类型

【1】一个GOP序列的第一个图像叫做 IDR 图像(立即刷新图像),IDR 图像都是 I 帧图像,但I帧不一定都是IDR帧,只有GOP序列的第1个I帧是IDR帧。

【2】I帧,又叫帧内参考帧 ,保留一帧完整的画面。

【3】解码时仅用I帧的数据就可重构出完整的图像。

【4】I帧不需要参考其他画面而生成。

【5】I帧是P帧和B帧的参考帧。

【6】I帧不需要考虑运动矢量。

【7】I帧所占数据的信息量最大。

(3)H264 的B帧类型

【1】B帧,又叫双向参考帧,也就是B帧记录的是本帧与前后帧的差别,要解码B帧,不 仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加 取得最终的画面。

【2】B帧的压缩率最高,但是解码时CPU使用率会比较高。

【3】B帧是由前面的I或P帧和后面的P帧来进行预测的。

【4】B帧传送的是它与前面的I或P帧和后面的P帧之间的预测误差及运动矢量。

【5】B帧不是参考帧,不会造成解码错误的扩散。

(4)H264 的P帧类型

【1】P帧,又叫前向参考帧,表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解 码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面,P帧没有完整画面 数据,只有与前一帧的画面差异的数据。

【2】P帧是I帧后面相隔1~2帧的编码帧。

【3】P帧采用运动补偿的方法传送它与前面的I或P帧的差值及运动矢量(预测误差)。

【4】P帧属于前向预测的帧间编码。它只参考前面最靠近它的I帧或P帧。

【5】P帧可以是其后面P帧的参考帧,也可以是其前后的B帧的参考帧。

【6】P帧是参考帧,可能会造成解码错误的扩散。

【7】P帧的压缩比介于I帧和B帧之间。

(5)H264 帧参考关系

四、音频文件的封装格式和编码格式

(1)FFmpeg的音频封装格式

MP3 是我们在日常生活中最常见的音频格式之一,也是一种音频封装格式。

日常生活中,我们经常可以看到 *.mp3 的音频文件,就像 mp4、flv 的视频封装格式一样。

MP3 封装格式

使用如下命令查看 ffmpeg 支持的封装格式列表: ffmpeg -formats | grep mp3

使用如下命令播放一个 mp3 音乐文件:

普通模式: ffplay 少年.mp3

波形图模式:ffplay -showmode 1 少年.mp3

频谱图模式:ffplay -showmode 2 少年.mp3

(2)FFmpeg的音频编码格式

FFmpeg 支持很多编码格式,包括 MP3、AAC、AC3 等。

接下来,重点介绍 MP3 音频编码格式。

MP3 编码格式

MP3 也是一种音频编码格式。

和视频不同,视频编码格式,比如 H264,一般会封装 MP4 或者 FLV 这种封装格式中被使用。音频编码格MP3,则是封装在同名的 MP3 的封装格式中。二者容易混淆,注意区分。

MP3 编码格式

使用如下命令查看ffmpeg支持的编码格式列表:

MP3 文件结构

MP3 文件结构

五、FFmpeg 查看媒体信息和处理音视频文件的常用方法

(1)FFmpeg的工程化方案

音频文件和视频文件的转码处理一般称为多媒体处理,华为云也有相应的媒体处理服务——Media Processing Center,简称 MPC,是一种多媒体数据处理服务,基于华为云云计算服务构建,解决客户自建音视频处理能力不可避免的投入成本高昂、技术门槛高等问题,帮助客户专注于业务能力构建,快速交付上线。

【1】视频处理

【2】音频处理

(2)FFmpeg视频转码

采用 FFmpeg 对音视频处理,主要是转码、视频参数、音频参数三部分内容。

传统的转码程序工作原理如下图所示:

【1】音视频转码示例:

代码语言:javascript复制
1. 音频转码
ffmpeg -i 少年.mp3 -acodec aac -ab 3000 -ac 1 -ar 8000 output.aac

2. 视频转码
ffmpeg -i big_buck_bunny.mp4 -vcodec h263 -b:v 256000 -r 15 -s 352x288 -acodec copy
output.ts

【2】最简单的方式转码

代码语言:javascript复制
ffmpeg -i 123.mp4 out.flv

【3】任意格式转为MP4

代码语言:javascript复制
转码视频格式并设置音频采样率和输出视频尺寸: mpg-->mp4
C:FFMPEGffmpeg_x86_4.2.2binffmpeg.exe -i 1.mpg -y -qscale 0 -vcodec libx264 -acodec aac -ac 1 -ar 22050 -s 300*300  1_1.mp4
 
 
转码视频格式并设置音频采样率和输出视频尺寸(软解可以播放-硬解无法播放): wmv-->wmv
C:FFMPEGffmpeg_x86_4.2.2binffmpeg.exe -i 2.wmv -y -qscale 0 -vcodec libx264 -acodec aac -ac 1 -ar 48000 -s 300*300  2_1.wmv
 
 
转码视频格式并设置音频采样率和输出视频尺寸: wmv-->mp4
C:FFMPEGffmpeg_x86_4.2.2binffmpeg.exe -i 2.wmv -y -qscale 0 -vcodec libx264 -acodec aac -ac 1 -ar 48000 -s 300*300  2_1.mp4
 
 
转码视频格式并设置音频采样率: wmv-->mp4
C:FFMPEGffmpeg_x86_4.2.2binffmpeg.exe -i 2.wmv -y -qscale 0 -vcodec libx264 -acodec aac -ac 1 -ar 48000 2_1.mp4
 
 
转码视频格式并设置音频采样率: wmv-->mp4
C:FFMPEGffmpeg_x86_4.2.2binffmpeg.exe -i Video_2020-10-11_2.wmv -y -qscale 0 -vcodec libx264 -acodec aac -ac 1 -ar 22050 Video_2020-10-11_2_1.mp4
 
 
转码视频格式并设置音频采样率和输出视频尺寸、修改码率: mpg-->mp4
C:FFMPEGffmpeg_x86_4.2.2binffmpeg.exe -i 1.mpg -y -qscale 0 -vcodec libx264 -acodec aac -ac 1 -ar 22050 -b:v 400k -s 300*300  1_1.mp4

(3)音视频合并

【1】视频拼接

这种方式需要保证所有的视频的格式、音频码率一样,不然无法正常合并。

代码语言:javascript复制
C:FFMPEGffmpeg_x86_4.2.2binffmpeg.exe  -f concat -safe 0 -i filelist.txt -c copy demo.mp4
 
filelist.txt文件内容---里面的视频路径使用相对路径:
file 'd8381671f616468c9193defcd55eeb3b.mp4'
file 'ad6beef4b9e14bcf8f4c07d802cae360.mp4'
file '1d15bf4c221c4e429413568d5c2e58e4.mp4'
 
转码视频格式并设置音频采样率和输出视频尺寸、设置输出帧率: 
C:FFMPEGffmpeg_x86_4.2.2binffmpeg.exe -i 1.mp4 -y -qscale 0 -vcodec libx264 -acodec aac -ac 1 -ar 22050 -s 300*300 -r 30 -aspect 1_1.mp4

【2】不同分辨率的源视频合成一个视频,设置画面的中心位置

代码语言:javascript复制
C:FFMPEGffmpeg_x86_4.2.2binffmpeg.exe -i 1.mp4 -i 1.mpg -i 123.mp4 -f lavfi -i color=black -filter_complex "[0:v]format=pix_fmts=yuva420p,rotate=PI*0/180:c=none:ow=rotw(PI*0/180):oh=roth(PI*0/180),pad=1920:1080:(ow-iw)/2:(oh-ih)/2:black,setpts=PTS-STARTPTS 0/TB[va0];[1:v]format=pix_fmts=yuva420p,rotate=PI*0/180:c=none:ow=rotw(PI*0/180):oh=roth(PI*0/180),pad=1920:1080:(ow-iw)/2:(oh-ih)/2:black,setpts=PTS-STARTPTS 3/TB[va1];[2:v]format=pix_fmts=yuva420p,rotate=PI*0/180:c=none:ow=rotw(PI*0/180):oh=roth(PI*0/180),pad=1920:1080:(ow-iw)/2:(oh-ih)/2:black,setpts=PTS-STARTPTS 7/TB[va2];[3:v]scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:black,trim=duration=12[over0];[over0][va0]overlay[over1];[over1][va1]overlay[over2];[over2][va2]overlay=format=yuv420[outv];[0:a][1:a][2:a] concat=n=3:v=0:a=1[outa]" -aspect 1920:1080 -vcodec libx264 -map "[outv]" -map "[outa]" -y out.mp4

【3】音频混合合成

代码语言:javascript复制
ffmpeg -i 1.mp3 -i 2.mp3 -filter_complex amix=inputs=2:duration=first:dropout_transition=2 -f mp3 remix.mp3
    
参数说明:
-i 文件 1.mp3 和 2.mp3 为待合成的两个源文件;
-filter_complex 过滤器参数;
amix=inputs 配置输入的整体样本数;
duration,first:长度取决于第一个文件,longest:长度取决于时间最长文件,shortest:长度取决于时间最短文件;
dropout_transition:输入流结束时用于体积重新规范化的过渡时间;
-f mp3 设置导出文件格式;

【4】音频连接合成

代码语言:javascript复制
ffmpeg -i "concat:headerNew.mp3|006.mp3" -acodec copy demo6.mp3
    
参数说明:
concat 合并文件指令;

【5】音频淡出效果

代码语言:javascript复制
ffmpeg -i bgm3.mp3  -filter_complex afade=t=out:st=16:d=4 bgm31.mp3

参数说明:
afade 淡入淡出指令;
从 st 秒开始,经过 d 秒钟的淡出效果;

【6】使用 FFmpeg concat 过滤器重新编码(有损)

语法有点复杂,但是其实不难。这个方法可以合并不同编码器的视频片段,也可以作为其他方法失效的后备措施。

代码语言:javascript复制
ffmpeg -i input1.mp4 -i input2.webm -i input3.avi -filter_complex '[0:0] [0:1] [1:0] [1:1] [2:0] [2:1] concat=n=3:v=1:a=1 [v] [a]' -map '[v]' -map '[a]' <编码器选项> output.mkv

上面的命令合并了三种不同格式的文件,FFmpeg concat 过滤器会重新编码它们。注意这是有损压缩。

[0:0] [0:1] [1:0] [1:1] [2:0] [2:1] 分别表示第一个输入文件的视频、音频、第二个输入文件的视频、音频、第三个输入文件的视频、音频。concat=n=3:v=1:a=1 表示有三个输入文件,输出一条视频流和一条音频流。[v] [a] 就是得到的视频流和音频流的名字,注意在 bash 等 shell 中需要用引号,防止通配符扩展。

【7】使用amix合并两种声音

代码语言:javascript复制
ffmpeg -i g001_2.wav -i tx.wav -filter_complex amix=inputs=2:duration=longest:dropout_transition=2 tx_new.wav

(4)视频倒放

代码语言:javascript复制
//视频倒放,无音频
C:FFMPEGffmpeg_x86_4.2.2binffmpeg.exe -i 123.mp4 -filter_complex [0:v]reverse[v] -map [v] -preset superfast out.mp4
//视频倒放,音频不变
C:FFMPEGffmpeg_x86_4.2.2binffmpeg.exe -i 123.mp4 -vf reverse out.mp4
//音频倒放,视频不变
C:FFMPEGffmpeg_x86_4.2.2binffmpeg.exe -i 123.mp4 -map 0 -c:v copy -af "areverse" out.mp4
//音视频同时倒放
C:FFMPEGffmpeg_x86_4.2.2binffmpeg.exe -i 123.mp4 -vf reverse -af areverse -preset superfast out.mp4

(5)视频转GIF

代码语言:javascript复制
1. 最简单的方式
ffmpeg -i 123.mp4 out.gif
    
2.将视频 MP4 转化为 GIF
ffmpeg -i OUTPUT_VIDEO.mp4 OUTPUT_VIDEO.gif

3.将视频中的一部分转换为GIF
// 从视频中第二秒开始,截取时长为3秒的片段转化为 gif
ffmpeg -t 3 -ss 00:00:02 -i small.mp4 small-clip.gif


4.转化高质量 GIF
ffmpeg -i  OUTPUT_VIDEO.mp4 -b 2048k OUTPUT_VIDEO.gif

5.将 GIF 转化为 MP4

ffmpeg -f gif -i animation.gif animation.mp4
ffmpeg -f gif -i animation.gif animation.mpeg
ffmpeg -f gif -i animation.gif animation.webm

6. 设置时间
通常我们只需要转换视频的某一个时间片段,所以不能像上图中的命令那样直接转换,需要使用-ss(设置起始时间),-t(设置持续时间)。

ffmpeg -ss 起始时间 -t 持续时间 -i 输入文件 输出文件

比如:ffmpeg -ss 9 -t 5 -i 1.mp4 1.gif,将会从视频的9秒开始截取5秒片段转换为gif图片。-ss也可以设置为00:00:00.000的形式,为小时、分钟、秒、毫秒,例如00:00:09.000。

7. 设置循环次数

-loop 循环次数,比如设置-loop 1,生成的gif图片将只会播放一次,0为无限次(默认)。

ffmpeg -ss 起始时间 -t 持续时间 -i 输入文件 -loop 循环次数 输出文件

比如ffmpeg -ss 9 -t 5 -i 1.mp4 -loop 0 1.gif。

8. 设置缩放

如果是高分辨率视频,可能需要将画面缩放,不然gif图片就太大了,可以使用scale控制。比如scale=iw/2:-1:flags=lanczos(lanczos为缩放算法),将会设置gif图片的宽度为源视频一半,高度为比例缩放,也可以强制设置宽高像素。

ffmpeg -ss 起始时间 -t 持续时间 -i 输入文件 -loop 循环次数 -vf scale=宽:高:flags=lanczos 输出文件

例如ffmpeg -ss 9 -t 5 -i 1.mp4 -loop 0 -vf scale=iw/2:-1:flags=lanczos 1.gif。

9. 设置fps(每秒帧数)
设置低一些的fps可以压缩gif的体积,使用fps=指定的fps数值,保持流畅即可。
ffmpeg -ss 起始时间 -t 持续时间 -i 输入文件 -loop 循环次数 -vf "scale=宽:高:flags=lanczos,fps=数值" 输出文件

例如ffmpeg -ss 9 -t 5 -i 1.mp4 -loop 0 -vf "scale=iw/2:-1:flags=lanczos,fps=15" 1.gif

10. 裁剪画面

可能我们只需要将视频画面的一部分转成gif图片,可以使用crop,具体为crop=宽度:高度:宽度起始:高度起始,比如crop=200:200:0:0,将会从横向0像素,纵向0像素开始,从画面裁剪200x200的区域。

ffmpeg -ss 起始时间 -t 持续时间 -i 输入文件 -loop 循环次数 -vf "scale=宽:高:flags=lanczos,fps=数值,crop=宽度:高度:宽度起始:高度起始" 输出文件

例如: ffmpeg -ss 9 -t 5 -i 1.mp4 -loop 0 -vf "scale=iw/2:-1:flags=lanczos,fps=15,crop=iw/2:ih:0:0" 1.gif,将裁剪视频的左半边画面。

11. 提高gif画面质量

你可能发现通过上面的方法直接生成的gif图片质量不怎么好,可以使用split和palette过滤器进行改善。

ffmpeg -ss 起始时间 -t 持续时间 -i 输入文件 -loop 循环次数 -vf "scale=宽:高:flags=lanczos,fps=数值,crop=宽度:高度:宽度起始:高度起始,split[s1][s2];[s1]palettegen[p];[s2][p]paletteuse" 输出文件

如ffmpeg -ss 9 -t 5 -i 1.mp4 -loop 0 -vf "scale=iw/2:-1:flags=lanczos,fps=15,crop=iw/2:ih:0:0,split[s1][s2];[s1]palettegen[p];[s2][p]paletteuse" 1.gif。

上面的参数和过滤器可根据自己的需要自由选择及设置。

(6)给视频添加图片水印

【1】添加图片水印

代码语言:javascript复制
//添加图片水印
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -i D:/666.mp4 -vf "movie=image/123.png[wm];[in][wm]overlay=30:10[out]" D:/linux-share-dir/video_file/test/output.mp4
 
参数解析:
1. D:/666.mp4 输入的视频
2. image/123.png 要添加进去的图片水印
3. D:/linux-share-dir/video_file/test/output.mp4 合成水印之后输出的视频

【2】在视频左下角添加GIF动态水印

代码语言:javascript复制
ffmpeg -y -i test2.mp4 -i gnore_loop 0 -i test.gif  -filter_complex overlay=0:H-h test_out2.mp4

【3】水印显示时间变化

代码语言:javascript复制
1. 设置水印显示时长
ffmpeg -hide_banner -i big_buck_bunny.mp4 -i doggie2.png -filter_complex "overlay=enable='lte(t,5)'" out.mp4 -y
上面命令作用是:让水印只显示5秒,5秒后消失。

2. 设置水印显示时间段
ffmpeg -hide_banner -i big_buck_bunny.mp4 -i doggie2.png -filter_complex "overlay=enable='between(t,5,10)'" out.mp4 -y
上面的命令作用是:让水印在视频的5~10秒时间段内显示

3. 设置两个水印轮番出现
ffmpeg -i big_buck_bunny.mp4 -i doggie1.png -i doggie2.png -filter_complex "overlay=enable='lte(mod(t,10),4)',overlay=enable='gt(mod(t,10),6)'" out.mp4 -y
上面的命令作用是:第一个水印显示4秒后消失,2秒后第二个水印显示4秒后消失。
这里布置个作业?huaji 请让两个水印一个在左上角,一个在右上角

【4】水印位置变化

代码语言:javascript复制
设置水印随时间向右移动
ffmpeg -i big_buck_bunny.mp4 -ignore_loop 0 -i doggie3.gif -lavfi "overlay=x=t*20" -shortest out.mp4 -y
上面命令的作用是:让水印每秒向右移动20像素,直到消失。

设置水印每隔10秒钟从左移动右直至消失
 ffmpeg -i big_buck_bunny.mp4 -ignore_loop 0 -i doggie3.gif -lavfi "overlay=enable='mod(t,10)':x='100*mod(t,10)-w'" -shortest out.mp4 -y

【5】GIF水印循环播放方式

代码语言:javascript复制
第一种:设置gif的-ignore_loop为0,让gif保持循环播放即可,命令如下:
ffmpeg -hide_banner -i big_buck_bunny.mp4 -ignore_loop 0 -i doggie3.gif -filter_complex  overlay -shortest out.mp4 -y
但是这种方式,只适用于gif格式的图像,如果滤镜是一小段视频就无能为力了。

第二种:使用movie滤镜,同样是让gif循环播放,虽然这种方式复杂点,不过这种解决方案支持视频水印,命令如下:
ffmpeg -hide_banner -i big_buck_bunny.mp4 -vf "movie=doggie3.gif:loop=0,setpts=N/FRAME_RATE/TB[out];[0:v][out]overlay=x=main_w-overlay_w:y=0" -shortest out.mp4 -y
上面的命令有两个地方比较关键:

loop=0,setpts=N/FRAME_RATE/TB :设置水印gif无限循环
-shortest :将输出文件的时长设置为第一个视频文件的时长,如果不设置,你会发现命令会一直执行根本不会停下来,因为gif图的循环是无限的
这样gif图/短视频就会一直不停的播放了。


希望水印播放一次就不播放了,那就设置上面的eof_action为pass就可以了,如下:
ffmpeg -hide_banner -i big_buck_bunny.mp4 -i doggie3.gif -filter_complex "overlay=x=0:y=0:eof_action=pass" out.mp4 -y

如果视频一开始就播放且只播放一次,假如水印比较短可能根本就没被注意就过去了,这时可以设置水印出现的延迟时间,使用-itsoffset选项,如下:
ffmpeg -hide_banner -i big_buck_bunny.mp4 -itsoffset 3 -i doggie3.gif -filter_complex "overlay=x=0:y=0:eof_action=pass" out.mp4 -y
这样,视频播放3秒后,水印才会出现。

【6】水印旋转

代码语言:javascript复制
如果想实现旋转的功能,需要使用ffmpeg过滤器的链式功能,即:先把作为水印的图片旋转,再覆盖到视频上。

1. 水印旋转一次
ffmpeg -i buck.mp4 -i s1.jpg -lavfi "[1:v]format=rgba,rotate='PI/6:c=0x00000000:ow=hypot(iw,ih):oh=ow'[out];[0:v][out]overlay=10:10" out.mp4 -y

思路是:
调整水印宽高,根据勾股定律计算图片对角长度(hypot),将这个值设置为水印的宽高,这样,图片无论如何旋转,都不会超过设定的宽高,也就不会出现图片部分丢失的情况了
将图片显示的像素格式转换为rgba格式,如果做过前端的小伙伴会很熟悉的,最后的a表示透明度,如此一来,c=0x00000000的作用就是将图片旋转后的背景变为白色且完全透明,这样就不会遮挡视频了

2. 让旋转停不下,具体命令如下:
ffmpeg -i buck.mp4 -loop 1 -i s1.jpg -lavfi "[1:v]format=rgba,rotate='PI/2*t:c=0x00000000:ow=hypot(iw,ih):oh=ow'[out];[0:v][out]overlay=10:10" -shortest out.mp4 -y
这次水印图片前面添加了-loop 1,正常情况下水印图片默认在播放一次后就停下来,保留最后一帧,所以要让水印图片保持循环才行。

(7)使用ffprobe获取媒体信息

【1】输出媒体信息

代码语言:javascript复制
PS D:> ffprobe -i .jiyi.mp4
ffprobe version 4.2.2 Copyright (c) 2007-2019 the FFmpeg developers
  built with gcc 9.2.1 (GCC) 20200122
  configuration: --disable-static --enable-shared --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt
  libavutil      56. 31.100 / 56. 31.100
  libavcodec     58. 54.100 / 58. 54.100
  libavformat    58. 29.100 / 58. 29.100
  libavdevice    58.  8.100 / 58.  8.100
  libavfilter     7. 57.100 /  7. 57.100
  libswscale      5.  5.100 /  5.  5.100
  libswresample   3.  5.100 /  3.  5.100
  libpostproc    55.  5.100 / 55.  5.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '.jiyi.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.29.100
  Duration: 00:00:54.15, start: 0.000000, bitrate: 574 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 960x544, 518 kb/s, 29.97 fps, 29.97 tbr, 19200 tbn, 38400 tbc (default)
    Metadata:
      handler_name    : Core Media Video
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 47 kb/s (default)
    Metadata:
      handler_name    : Core Media Audio
PS D:>

【2】输出媒体信息

代码语言:javascript复制
PS D:> ffprobe -v quiet -of json -i .jiyi.mp4  -show_streams

{
    "streams": [
        {
            "index": 0,
            "codec_name": "h264",
            "codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
            "profile": "High",
            "codec_type": "video",
            "codec_time_base": "8123/486900",
            "codec_tag_string": "avc1",
            "codec_tag": "0x31637661",
            "width": 960,
            "height": 544,
            "coded_width": 960,
            "coded_height": 544,
            "has_b_frames": 1,
            "pix_fmt": "yuv420p",
            "level": 31,
            "color_range": "tv",
            "color_space": "bt709",
            "color_transfer": "bt709",
            "color_primaries": "bt709",
            "chroma_location": "left",
            "refs": 1,
            "is_avc": "true",
            "nal_length_size": "4",
            "r_frame_rate": "30000/1001",
            "avg_frame_rate": "243450/8123",
            "time_base": "1/19200",
            "start_pts": 0,
            "start_time": "0.000000",
            "duration_ts": 1039744,
            "duration": "54.153333",
            "bit_rate": "518796",
            "bits_per_raw_sample": "8",
            "nb_frames": "1623",
            "disposition": {
                "default": 1,
                "dub": 0,
                "original": 0,
                "comment": 0,
                "lyrics": 0,
                "karaoke": 0,
                "forced": 0,
                "hearing_impaired": 0,
                "visual_impaired": 0,
                "clean_effects": 0,
                "attached_pic": 0,
                "timed_thumbnails": 0
            },
            "tags": {
                "language": "und",
                "handler_name": "Core Media Video"
            }
        },
        {
            "index": 1,
            "codec_name": "aac",
            "codec_long_name": "AAC (Advanced Audio Coding)",
            "profile": "LC",
            "codec_type": "audio",
            "codec_time_base": "1/44100",
            "codec_tag_string": "mp4a",
            "codec_tag": "0x6134706d",
            "sample_fmt": "fltp",
            "sample_rate": "44100",
            "channels": 1,
            "channel_layout": "mono",
            "bits_per_sample": 0,
            "r_frame_rate": "0/0",
            "avg_frame_rate": "0/0",
            "time_base": "1/44100",
            "start_pts": 0,
            "start_time": "0.000000",
            "duration_ts": 2387471,
            "duration": "54.137664",
            "bit_rate": "47025",
            "max_bit_rate": "47025",
            "nb_frames": "2332",
            "disposition": {
                "default": 1,
                "dub": 0,
                "original": 0,
                "comment": 0,
                "lyrics": 0,
                "karaoke": 0,
                "forced": 0,
                "hearing_impaired": 0,
                "visual_impaired": 0,
                "clean_effects": 0,
                "attached_pic": 0,
                "timed_thumbnails": 0
            },
            "tags": {
                "language": "und",
                "handler_name": "Core Media Audio"
            }
        }
    ]
}

(8)采集桌面屏幕、摄像头保存为视频

【1】 列出当前电脑上音频设备、摄像头设备列表

代码语言:javascript复制
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -list_devices true -f dshow -i dummy

【2】录制桌面全屏图像 音频

代码语言:javascript复制
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -f gdigrab -i desktop -f dshow -i audio="@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}wave_{6E399CBA-5F7D-443F-9071-1657DE0F5483}" -vcodec libx264 -acodec libmp3lame -s 1280x720 -r 15 D:/linux-share-dir/video_file/6666.mp4
 
其中: 
audio= "" 这里填麦克风设备. 第一条指令就是查询电脑上音频设备。把名字复制过来即可。

【3】录制摄像头 音频

代码语言:javascript复制
示例1:
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -f dshow -i video="@device_pnp_\?usb#vid_5986&pid_2113&mi_00#6&3326332&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}global" -f dshow -i audio="@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}wave_{6E399CBA-5F7D-443F-9071-1657DE0F5483}" -vcodec libx264 -acodec libmp3lame -s 1280x720 -r 15 D:/linux-share-dir/video_file/6666.mp4
 
 
其中:
video="" 视频摄像头设备名称
audio="" 视频音频设备名称
 
 
示例2:
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -f dshow -i video="@device_pnp_\?usb#vid_5986&pid_2113&mi_00#6&3326332&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}global" -f dshow -i audio="@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}wave_{6E399CBA-5F7D-443F-9071-1657DE0F5483}" D:/linux-share-dir/video_file/test/202108161456.mp4

【4】 采集桌面指定区域(无音频)

代码语言:javascript复制
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -f gdigrab -framerate 6 -offset_x 50 -offset_y 50 -video_size 400x400 -i desktop D:/linux-share-dir/video_file/test/202108161448.mp4

【5】采集桌面指定区域 音频

代码语言:javascript复制
//录制指定范围--采集图像 音频
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -f gdigrab -framerate 6 -offset_x 50 -offset_y 50 -video_size 400x400 -i desktop -f dshow -i audio="@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}wave_{6E399CBA-5F7D-443F-9071-1657DE0F5483}" D:/linux-share-dir/video_file/test/202108161514.mp4

【6】案例

代码语言:javascript复制
列出设备列表
ffmpeg -list_devices true -f dshow -i dummy

全屏录像 ( dshow录屏, H264编码 )
ffmpeg -f dshow -i video="screen-capture-recorder" -f dshow -i audio="virtual-audio-capturer" -vcodec libx264 -acodec libmp3lame -s 1280x720 -r 15 e:/temp/temp.mkv

全屏录像 ( gdigrab录屏, H264编码 )
ffmpeg -f gdigrab -i desktop -f dshow -i audio="virtual-audio-capturer" -vcodec libx264 -acodec libmp3lame -s 1280x720 -r 15 e:/temp/temp.mkv

全屏录像 ( gdigrab录屏, vp9编码 )( 注 : dshow不支持vp9 )
ffmpeg -f gdigrab -i desktop -f dshow -i audio="virtual-audio-capturer" -vcodec libvpx-vp9 -acodec libmp3lame -s 1280x720 -r 15 e:/temp/temp.mkv

区域录像 ( 起点:100,60 width:600 width:480 )
ffmpeg -f gdigrab -i desktop -f dshow -i audio="virtual-audio-capturer" -vcodec libx264 -acodec libmp3lame -video_size 600x480 -offset_x 100 -offset_y 60 -r 15 e:/temp/temp.mkvC:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -f dshow  -i video="screen-capture-recorder"  screen-capture.mp4




window (安装dshow)
ffmpeg -rtbufsize 100M -f dshow -i video="screen-capture-recorder":audio="virtual-audio-capturer" -vcodec libx264  -preset veryfast -crf 22 -tune:v zerolatency  -pix_fmt yuv420p  -s  ' size r'  -acodec libmp3lame  -t  '   str(times)   '  '   filename



列出当前电脑上音频设备、摄像头设备列表
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -list_devices true -f dshow -i dummy

//录制全屏
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -f gdigrab -i desktop -f dshow -i audio="@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}wave_{6E399CBA-5F7D-443F-9071-1657DE0F5483}" -vcodec libx264 -acodec libmp3lame -s 1280x720 -r 15 D:/linux-share-dir/video_file/6666.mp4
    
    
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -f dshow  -i video="screen-capture-recorder"  screen-capture.mp4




window (安装dshow)
ffmpeg -rtbufsize 100M -f dshow -i video="screen-capture-recorder":audio="virtual-audio-capturer" -vcodec libx264  -preset veryfast -crf 22 -tune:v zerolatency  -pix_fmt yuv420p  -s  ' size r'  -acodec libmp3lame  -t  '   str(times)   '  '   filename



列出当前电脑上音频设备、摄像头设备列表
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -list_devices true -f dshow -i dummy

//录制全屏
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -f gdigrab -i desktop -f dshow -i audio="@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}wave_{6E399CBA-5F7D-443F-9071-1657DE0F5483}" -vcodec libx264 -acodec libmp3lame -s 1280x720 -r 15 D:/linux-share-dir/video_file/6666.mp4
    
    
这是OK的--录制全屏无音频
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -f gdigrab -framerate 10 -i desktop D:/linux-share-dir/video_file/test/666.mp4


这是OK的---但是捕获的位置有问题
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -f dshow  -i video="screen-capture-recorder" -crf 22 -r 10 D:/linux-share-dir/video_file/test/666.mp4



C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -f gdigrab -i desktop -f dshow -i audio="@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}wave_{6E399CBA-5F7D-443F-9071-1657DE0F5483}" -vcodec libx264 -acodec aac -s 1280x720 -r 10 D:/linux-share-dir/video_file/6666.mp4
 
其中: 
audio= "" 这里填麦克风设备. 第一条指令就是查询电脑上音频设备。把名字复制过来即可。


C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -f gdigrab -i desktop -f dshow -i audio="麦克风阵列 (Conexant SmartAudio HD)" -vcodec libx264 -acodec aac -s 1280x720 -r 10 D:/linux-share-dir/video_file/test/6666.mp4


C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -f gdigrab -i desktop -f dshow -i audio="麦克风阵列 (Conexant SmartAudio HD)" -vcodec libx264 -acodec aac -video_size 100x100 -offset_x 500 -offset_y 500 -r 10 D:/linux-share-dir/video_file/6666.mp4
    
    
    //采集摄像头 
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -f dshow -i video="Integrated Camera" -f dshow -i audio="virtual-audio-capturer" D:/linux-share-dir/video_file/test/202108161421.mp4


//采集摄像头和电脑音频. 这是OK的
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -f dshow -i video="Integrated Camera" -f dshow -i audio="@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}wave_{6E399CBA-5F7D-443F-9071-1657DE0F5483}" D:/linux-share-dir/video_file/test/202108161443.mp4



//录制指定范围--采集图像--这是OK的
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -f gdigrab -framerate 6 -offset_x 50 -offset_y 50 -video_size 400x400 -i desktop D:/linux-share-dir/video_file/test/202108161448.mp4


//采集摄像头和电脑音频. 这是OK的
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -f dshow -i video="@device_pnp_\?usb#vid_5986&pid_2113&mi_00#6&3326332&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}global" -f dshow -i audio="@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}wave_{6E399CBA-5F7D-443F-9071-1657DE0F5483}" D:/linux-share-dir/video_file/test/202108161456.mp4


//录制指定范围--采集图像 音频
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -f gdigrab -framerate 6 -offset_x 50 -offset_y 50 -video_size 400x400 -i desktop -f dshow -i audio="@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}wave_{6E399CBA-5F7D-443F-9071-1657DE0F5483}" D:/linux-share-dir/video_file/test/202108161514.mp4


fmpeg.exe -f dshow -i video="@device:pnp:\\?\usb#vid_5986&pid_2113&mi_00#6&3326332&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global" -f dshow -i audio="麦克风阵列 (Conexant SmartAudio HD)" C:/Users/11266/Videos/2021-8-16-16-35-44-426.mp4n"

(9)视频音频替换

【1】去掉视频原声再添加新的音频

代码语言:javascript复制
(1)去掉视频原声:
C:FFMPEGffmpeg_x86_4.2.2bin>ffmpeg.exe -i 123.mp4 -c:v copy -an out1.mp4
 
(2)合并音频到视频:
C:FFMPEGffmpeg_x86_4.2.2bin>ffmpeg.exe -i out1.mp4 -i 花僮-笑纳.mp3 out2.mp4
 
可以指定合成时间:
C:FFMPEGffmpeg_x86_4.2.2bin>ffmpeg.exe -i out1.mp4 -i 花僮-笑纳.mp3 -t 30 out3.mp4
其中-t参数是指定时间.单位是秒.

【2】保留视频原生添加新的音频

代码语言:javascript复制
ffmpeg -i 花僮-笑纳.mp3 -i 123.mp4 -filter_complex amix=inputs=2 output.mp4

【3】替换原来影片的音讯

代码语言:javascript复制
ffmpeg -i tx_new.wav -i r001_2.flv -shortest -c copy n001_2.flv

(10)给视频添加文字水印

【1】在图片的左上角(横坐标10.纵坐标100)添加水印:

代码语言:javascript复制
wbyq@wbyq:/mnt/hgfs/linux-share-dir$ ffmpeg -i 123.mp4 -vf "drawtext=fontfile=simhei.ttf: text=‘DS小龙哥’:x=100:y=10:fontsize=24:fontcolor=white:shadowy=2" output.mp4
 
参数说明
fontfile:字体类型  --simhei.ttf如果没有找到,可以在windows下的Fonts目录下拷贝过来,放到程序执行目录下-
text:要添加的文字内容
fontsize:字体大小
fontcolor:字体颜色

【2】常见案例

代码语言:javascript复制
水印位置:(x,y)=(10,10)<=(left,top)距离左侧、顶部各10像素;
										 
贴图水印时间显示
ffmpeg -i C:UsersheshipingDesktopvideoDown2.mp4 -i C:UsersheshipingDesktopvideoDown4.jpg -filter_complex  overlay=x='if(between(t,15,30),150,NAN)':0 -threads 5  -preset ultrafast  C:UsersheshipingDesktopvideoDown15-30s.mp4
 
 
透明度
ffmpeg -i C:UsersheshipingDesktopvideoDown2.mp4 -i C:UsersheshipingDesktopvideoDown4.jpg -filter_complex  "[1:v]colorkey=0x000000:0.6:1.0[ckout];[0:v][ckout]overlay=10:10[out]" -map "[out]"   -threads 5  -preset ultrafast C:UsersheshipingDesktopvideoDownxuanzhuans.mp4
 
ffmpeg -i C:UsersheshipingDesktopvideoDown2.mp4 -i C:UsersheshipingDesktopvideoDown4.jpg -filter_complex  "[1:v]scale=100:100[wm];[0:v][wm]overlay=x='if(between(t,15,30),150,NAN)':50[HSP];[HSP]colorkey=0x000000:0.6:1.0[ckouts];[0:v][ckouts]overlay=150:50[out]" -map "[out]"  -threads 5  -preset ultrafast C:UsersheshipingDesktopvideoDown缩放透明度时间显示位置.mp4
 
合成
ffmpeg -i C:UsersheshipingDesktopvideoDown2.mp4 -i C:UsersheshipingDesktopvideoDown4.jpg -filter_complex  "[1:v]scale=500:500[sf];[0:v][sf]overlay=x='if(between(t,10,30),300,NAN)':150[cc];[cc]colorkey=0x000000:0.6:1.0[tmd];[0:v][tmd]overlay=300:150[out]" -map "[out]" -threads 5  -preset ultrafast  -max_muxing_queue_size 1024 C:UsersheshipingDesktopvideoDown111.mp4
 
ffmpeg 
-i C:UsersheshipingDesktopvideoDown2.mp4 
-i C:UsersheshipingDesktopvideoDown4.jpg 
-filter_complex  "[1:v]scale=500:500[sf];[0:v][sf]overlay=x='if(between(t,10,30),300,NAN)':150[cc];[cc]colorkey=0x000000:0.6:1.0[tmd];[0:v][tmd]overlay=300:150[out]"
-map "[out]"   
-threads 5  -preset ultrafast 
C:UsersheshipingDesktopvideoDownfinal.mp4
 
ffmpeg -i C:UsersheshipingDesktopvideoDown2.mp4 -i C:UsersheshipingDesktopvideoDown4.jpg -filter_complex  "[1:v]scale=500:500[sf];[0:v][sf]overlay=x='if(between(t,10,30),300,NAN)':150[cc];[cc]colorkey=0x000000:0.6:1.0[tmd];[0:v][tmd]overlay=300:150[out]" -map "[out]" -threads 5  -preset ultrafast  -max_muxing_queue_size 1024 C:UsersheshipingDesktopvideoDown111.mp4
 
 
//垂直翻转
ffmpeg -i C:\Users\heshiping\Desktop\videoDown\1.jpg -vf vflip -y C:\Users\heshiping\Desktop\videoDown\1s.jpg
//水平翻转
ffmpeg -i C:\Users\heshiping\Desktop\videoDown\66.webm -vf hflip -y C:\Users\heshiping\Desktop\videoDown\66.webm
ffmpeg -i C:UsersheshipingDesktopvideoDown4.jpg -vf vflip -y C:UsersheshipingDesktopvideoDownvflip.jpg
 
delogo 去除视频某处的logo。其实实现原理就是将给出区域进行高斯模糊处理。
delogo=x=0:y=0:w=100:h=77:band=10
x,y,w,h 构成一个Rect,band是模糊强度。  
removelogo ,消除logo水印,和delogo 类似。
 
 
视频水印 透明度
ffmpeg -i C:UsersheshipingDesktopvideoDown21.mp4 -itsoffset 5 -i C:UsersheshipingDesktopvideoDownc.webm -filter_complex [1:v]scale=900:500[sf];[sf]format=yuva444p,colorchannelmixer=aa=0.5[sf];[0:v][sf]overlay=x='if(between(t,5,13),0,NAN)':0 -y C:UsersheshipingDesktopvideoDowneric1.mp4
 
视频水印旋转透明
ffmpeg -i  C:UsersheshipingDesktopvideoDown21.mp4 -itsoffset 10 -i C:UsersheshipingDesktopvideoDownc.webm  -filter_complex [1:v]scale=300:200[sf];[sf]format=yuva444p,colorchannelmixer=aa=0.6[sf];[sf]rotate='45*PI/180:ow=hypot(iw,ih):oh=ow:c=none'[sf];[0:v][sf]overlay=x='if(between(t,10,18),100,NAN)':100 C:UsersheshipingDesktopvideoDownccccc.mp4 -y
 
 
 
转场滤镜
ffmpeg -i /data/video/tencent/动漫/a8dukd400400_泽塔奥特曼_普通话版_18_mp4/a8dukd400400_泽塔奥特曼_普通话版_18_001121_001142.mp4 -i /data/video/tencent/动漫/a8dukd400400_泽塔奥特曼_普通话版_18_mp4/a8dukd400400_泽塔奥特曼_普通话版_18_001100_001121.mp4 -filter_complex "[0:v]split[v0a][v0b];[v0a]trim=0:20[v0020];[v0b]trim=20:21,setpts=PTS-STARTPTS[v02021];[1:v]split[v1a][v1b];[v1a]trim=0:20[v1020];[v1b]trim=20:21,setpts=PTS-STARTPTS[v12021];[v02021][v1020]gltransition=duration=2:source=/usr/local/src/ffmpeg-gl-transition/gl-transitions/transitions/InvertedPageCurl.glsl[g01];[v0020][g01][v12021]concat=n=3[outv];[outv]scale=1920:1080[outv]" -map "[outv]" -c:v libx264 -profile:v baseline -preset slow -movflags faststart -pix_fmt yuv420p -threads 5 -preset ultrafast /data/video/ovwq2f20210322171622763.mp4 -y
 
 
任意位置文字水印
 
ffmpeg -i C:UsersheshipingDesktopvideoDown2021.mp4 -vf "drawtext=fontfile=MengNaJianCaiYun-2.ttf: text='heshiping':x=100:y=100:fontsize=29:fontcolor=yellow:shadowy=2" -b:v 3000k C:UsersheshipingDesktopvideoDown222222.mp4 -y
 
 
滚动文字水印
ffmpeg -i C:UsersheshipingDesktopvideoDown2021.mp4 -vf "drawtext=fontfile=Arial.ttf: text='hu': y=h-line_h-10:x=(mod(2*n,w tw)-tw):fontsize=34:fontcolor=yellow:shadowy=2" -b:v 3000k C:UsersheshipingDesktopvideoDown222222.mp4 -y
 
底部文字水印
ffmpeg -i C:UsersheshipingDesktopvideoDown2021.mp4 -vf "drawtext=fontfile=Arial.ttf:text='pruduction by http://baidu.com':y=h-line_h-20:x=(w-text_w)/2:fontsize=34:fontcolor=yellow:shadowy=2" -b:v 3000k C:UsersheshipingDesktopvideoDown222222.mp4 -y
 
水平运动
ffmpeg -y -i demo.mp4 -vf drawtext=arialbd.ttf:text=HelloWorld:x=w-t*5:fontcolor=red:fontsize=30 demo_drawtext_h_dyn.mp4
 
垂直运动
ffmpeg -y -i demo.mp4 -vf drawtext=arialbd.ttf:text=HelloWorld:x=w/2:y=h-t*5:fontcolor=red:fontsize=30 demo_drawtext_v_dyn.mp4

(11)视频剪切

【1】案例1

代码语言:javascript复制
ffmpeg.exe -ss 10 -t 15 -accurate_seek -i love.flv -codec copy -avoid_negative_ts 1 cut.flv
 
参数解释: 
  ffmpeg.exe -ss <起始时间-秒> -t <向后截取-秒> -accurate_seek -i <输入视频文件名称> -codec copy -avoid_negative_ts 1 <输出视频文件名称>
 
可以单独指定音频和视频参数:
-vcodec copy  保留原视频帧率
-acodec copy  保留原视频音频采样率和通道数
-codec copy   这一条指令包含了上面两条指令

【2】案例2

代码语言:javascript复制
ffmpeg -i input.mp4 -ss 00:00:00 -t 10 out.ts
-i : 指定视频
-ss : 开始时间
-t : 指定裁剪的秒数

【3】案例3

代码语言:javascript复制
ffmpeg -i organ.mp3 -ss 00:00:xx -t 120 output.mp3

参数说明:
-i 文件,orgin.mp3 为待处理源文件;
-ss 裁剪时间,后跟裁剪开始时间,以及 -t 裁剪时间;
output.mp3 为处理结果文件;

(12)获取flv视频格式的时长

flv格式的视频不能像其他视频一样直接通过ffprobe输出的json获取,可以通过它的命令行输出截取时间段转换得到时间。

代码语言:javascript复制
    QProcess process;
    process.setProcessChannelMode(QProcess::MergedChannels);
    process.start("C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffprobe.exe -i D:/test1080.flv");
    process.waitForFinished();
    process.waitForReadyRead();
    QString str  = process.readAllStandardOutput();
    process.close();
 
    //分析字符串
    const char *src=str.toStdString().c_str();
    char *p1=strstr(src,"Duration");
    if(p1)
    {
        int addr=p1-src;
        str = str.mid(addr 10);
        str =str.section(',', 0,0);
 
        qDebug("视频的时长(标准时间):%s",str.toStdString().c_str());
 
        //解析数据
        QTime t1=QTime::fromString(str);
        int time_ms=t1.hour()*60*60*1000 t1.minute()*60*1000 t1.second()*1000 t1.msec();
        qDebug()<<"最视频的时长(MS):"<<time_ms;
 
        //反向解析回来对比
        qDebug()<<"还原视频的时长(标准时间):"<<QTime(0,0,0,0).addMSecs(int(time_ms)).toString(QString::fromLatin1("HH:mm:ss.zzz"));
    }

输出结果:

代码语言:javascript复制
视频的时长(标准时间):00:06:37.15
最视频的时长(MS): 397150
还原视频的时长(标准时间): "00:06:37.150"

(13)视频实现各种特效

代码语言:javascript复制
//渐入
ffmpeg -i in.mp4 -vf fade=in:0:90 out.mp4                 
//黑白                    
ffmpeg -i in.mp4 -vf lutyuv="u=128:v=128" out.mp4   
//锐化
ffmpeg -i in.mp4 -vf unsharp=luma_msize_x=7:luma_msize_y=7:luma_amount=2.5 out.mp4   
//反锐化
ffmpeg -i in.mp4 -vf unsharp=7:7:-2:7:7:-2 out.mp4 
//渐晕
ffmpeg -i in.mp4 -vf vignette=PI/4 out.mp4
//闪烁渐晕
ffmpeg -i in.mp4 -vf vignette='PI/4 random(1)*PI/50':eval=frame out.mp4
//视频颤抖
ffmpeg -i in.mp4 -vf crop="in_w/2:in_h/2:(in_w-out_w)/2 ((in_w-out_w)/2)*sin(n/10):(in_h-out_h)/2 ((in_h-out_h)/2)*sin(n/7)" out.mp4  
//色彩变幻
ffmpeg -i in.mp4 -vf hue="H=2*PI*t:s=sin(2*PI*t) 1" out.mp4
//模糊处理
ffmpeg -i in.mp4 -vf boxblur=5:1:cr=0:ar=0 out.mp4
//镜像翻转
ffmpeg -i in.mp4 -vf crop=iw/2:ih:0:0,split[left][tmp];[tmp]hflip[right];[left]pad=iw*2[a];[a][right]overlay=w out.mp4
//水平翻转
ffmpeg -i in.mp4 -vf geq=p(W-X\,Y) out.mp4
//垂直翻转
ffmpeg -i in.mp4 -vf vflip out.mp4
//浮雕效果
ffmpeg -i in.mp4 -vf format=gray,geq=lum_expr='(p(X,Y) (256-p(X-4,Y-4)))/2' out.mp4
//均匀噪声
ffmpeg -i in.mp4 -vf noise=alls=20:allf=t u out.mp4

(14)转为关键帧(实现精确剪切)

平时剪辑视频,可能有些视频裁剪后的效果,如期望一致,00秒开始,30秒结束,总共30秒的视频,但是有些视频裁剪后你会发现可能开始和结束都不是很准确,有可能是从00秒开始,33秒结束。这是为什么呢? 因为这些视频里30秒处地方刚好不是关键帧,而ffmpeg会在你输入的时间点附近调整到最接近的关键帧处,然后做接下来的事情。 如果你不懂什么是关键帧,没关系,这也不影响你使用这个命令。 如果你的项目要求能够接受几秒的误差,那么这个命令完全就可以满足你的需要,接下来的内容你也没有必要往下看了。 如果你的项目里要求很严格,一定要到确定的时间。那么就要用另外一种方式。 上面的造成那样的原因是所选的时间不是关键帧,那如果我们将输入的视频先转换成所有的帧都为关键帧的视频,其实就是将所有的帧的编码方式转为帧内编码

代码语言:javascript复制
ffmpeg -i r001.flv -strict -2 -qscale 0 -intra r002.flv 
# 转换关键帧 帧内编码

剪出视频前6秒

代码语言:javascript复制
ffmpeg -t 00:00:06 -i r002.flv -vcodec copy -acodec copy r001_1.flv
# 指定开始时间和结束时间
# ffmpeg -ss 00:00:00 -t 00:00:06 -i r002.flv -vcodec copy -acodec copy r001_1.flv
# -ss 指定从什么时间开始
# -t 指定需要截取多长时间
# -i 指定输入文件

(15)从视频中提取音频文件

代码语言:javascript复制
# 从r002.mp4视频中提取音频,文件名字为r002.wav,格式为wav
ffmpeg -i g001_2.flv  -vn -acodec copy g001_2.wav

(16)调整音频音量

这是改变音量的命令参数,在合成音频后,可能就是原视频声音很大,但是特效声音小,导致听起来忽大忽小,这种情况下可以统一调整一下音量。

代码语言:javascript复制
0.5倍
ffmpeg -i input.wav -af "volume=0.5" output.wav
 
1.5倍
ffmpeg -i input.wav -af "volume=1.5" output.wav
 
使用分貝
ffmpeg -i input.wav -af "volume=5dB" output.w

(17)给视频添加ASS字幕文件

代码语言:javascript复制
ffmpeg -i 001.mp4 -vf ass=demo.ass -b:v 3000K r001.flv

(18)视频中加入动画

【1】在视频第6秒添加动画

代码语言:javascript复制
ffmpeg -re -i n001_2.flv -vf "movie=dianzan.mov,scale=200*200[test]; [in][test] overlay=x=400:y=100:eof_action=2 [out]" -vcodec libx264 g001_2.flv
#或者使用 gif 也可以 0 重复 1 不重复

命令解释: 给r001_2视频加入动图,x,y 代表坐标,eof_action表示动图结束后的动作,0代表重复前一帧,1代表停止所有流,2代表保留主图层。

(19)给视频添加跑马灯效果(滚动字幕)

【1】从左往右滚

代码语言:javascript复制
ffmpeg -i input.mp4 -vf "drawtext=text=string1 string2 string3 string4 string5 string6 string7 :expansion=normal:fontfile=foo.ttf: y=h-line_h-10:x=(mod(5*n,w tw)-tw): fontcolor=white: fontsize=40: shadowx=2: shadowy=2" output.mp4

【2】从右往左滚

代码语言:javascript复制
ffmpeg -i input.mp4 vf "drawtext=text=string1:fontfile=foo.ttf:y=h-line_h-10:x=w-(t-4.5)*w/5.5:fontcolor=white:fontsize=40:shadowx=2:shadowy=2" output.mp4

【3】从右往左滚,单次滚动时长10秒,间隔30秒滚一次

代码语言:javascript复制
ffmpeg -i input.mp4 -filter:v drawtext="fontfile=Microsoft YaHei Mono.ttf:text='Hello World':fontcolor=white@1.0:fontsize=36:y=h-line_h-10:x=w-tw-w/10*mod(t,30):enable=gt(mod(t,20),10)" -codec:v libx264 -codec:a copy -y output.mp4

(20)FFMPEG 使用GPU加速转码处理视频

【1】软件硬件编码区别

视频转码时如果遇见视频比较大、时长很长的时候,转码压制需要等待很久且及占用cpu,所以就在想有没有什么办法可以加速转码进度呢 ,故本篇文章记录FFMPEG如何调用显卡对转换编码格式或者压制进行加速。

软硬编解码的区分: 软编码:使用CPU进行编码 硬编码:使用非CPU进行编码,如显卡GPU、专用的DSP、FPGA、ASIC芯片等

软硬编解码的区别: 软编码:实现直接、简单,参数调整方便,升级易,但CPU负载重,性能较硬编码低,低码率下质量通常比硬编码要好一点。 硬编码:性能高,低码率下通常质量低于软编码器,但部分产品在GPU硬件平台移植了优秀的软编码算法(如X264)的,质量基本等同于软编码。

【2】查看支持的硬件加速方式

代码语言:javascript复制
D:out>ffmpeg -hwaccels
    
Hardware acceleration methods:
cuda
dxva2
qsv
d3d11va
qsv
cuvid

以上输出代表系统所支持的硬件加速方式,后续会用到。

硬编码后缀解释

qsv:intel显卡的快速视频同步技术(quick sync video)

nvenc:nvidia显卡的硬件视频编码器(nvidia hardware video encoder)

cuvid:nvdec的旧称,只有解码端。

cuda: 同上

amf:amd显卡的amf硬件编码器(amd hardware encoder)

基本上所有的Intel 电脑都支持qsv方式。

【3】硬件加速命令

代码语言:javascript复制
ffmpeg -hwaccel cuvid -c:v h264_cuvid -i input.mp4 -c:v h264_nvenc -b:v 2048k -s 1920x1080 output.mp4

常用命令参数解释 -hwaccel cuvid:使用cuvid进行硬件加速 -c:v h264_cuvid:使用h264_cuvid进行解码 -c:v h264_nvenc:使用h264_nvenc进行编码(nvidia硬件加速x265) -b:v 2000k:比特率,值越大约清晰。 -s 1920x1080:分辨率 -b:v 3500K :视频平均比特率为 3500K -bufsize 6000K:缓存区大小 6000K,建议设定为 当前码率帧率5,也许这里的2pass是针对缓冲区的,缓存未来5s -maxrate 5000K:最大码率为 5000K,每帧的最高码率不超过这个数值 -preset slow:预设方案是 slow,slow已经是最好的选项了 -pix_fmt p010le:输出的像素格式是 p010le 也就10bit,只有新的硬件支持,例如:970m不支持,1070可以支持

【4】使用CUDA与CUVID解码

代码语言:javascript复制
1. 使用 CUDA 的解码示例:
ffmpeg -hwaccel cuda -i input output

2. 使用 CUVID 的解码示例:
ffmpeg -c:v h264_cuvid -i input output

3. 使用 NVDEC 和 NVENC 进行全硬件转码:
ffmpeg -hwaccel cuda -hwaccel_output_format cuda -i input -c:v h264_nvenc -preset slow output

4. 如果 ffmpeg 是在支持 libnpp 的情况下编译的,则它可用于将基于 GPU 的缩放器插入链中:
ffmpeg -hwaccel_device 0 -hwaccel cuda -i input -vf scale_npp=-1:720 -c:v h264_nvenc -preset slow output.mkv
该-hwaccel_device选项可用于指定 ffmpeg 中硬解码要使用的 GPU。

【5】使用qsv解码

代码语言:javascript复制
1. 编码使用硬件
ffmpeg.exe -i 20180206210632.mp4 -vcodec h264_qsv -f mp4 20180206210632-2.mp4

2. 解码也指定硬件解码
ffmpeg.exe -c:v h264_qsv -i 20180206210632.mp4 -vcodec h264_qsv -f mp4 20180206210632-3.mp4

3. 指定硬件加速qsv
ffmpeg.exe -hwaccel qsv -c:v h264_qsv -i 20180206210632.mp4 -vcodec h264_qsv -f mp4 20180206210632-4.mp4
手机拍摄的视频上面转换报错。因为手机拍摄视频带有旋转信息,添加输入参数-noautorotate后为:
ffmpeg.exe -hwaccel qsv -c:v h264_qsv -noautorotate -i 20180206210632.mp4 -vcodec h264_qsv -f mp4 20180206210632-5.mp4

【6】案例

代码语言:javascript复制
剪切视频片段
如果输入的视频格式和输出的视频格式相同. 可以直接采用 -vcodec copy -acodec copy  参数. 可以加快时间
ffmpeg -hwaccel  dxva2 -ss 00:00:10.100 -t 00:00:15.100 -i "D:/test1080.flv" -vcodec copy -acodec copy "D:/linux-share-dir/video_file/output1.mp4"

如果输入的视频格式和输出的视频格式不相同,就要重新编码. 不能采用 -vcodec copy -acodec copy 参数,否则会报错.

ffmpeg -hwaccel  dxva2 -ss 00:00:10.100 -t 00:00:15.100 -i "D:/Video_WMV视频文件.wmv" -c:v h264_qsv "D:/linux-share-dir/video_file/output1.mp4"

ffmpeg -hwaccel  dxva2 -ss 00:00:10.100 -t 00:00:15.100 -i "D:/test1080.flv" -c:v h264_qsv  "D:/linux-share-dir/video_file/output1.mp4"


(1)去掉视频原声:--速度很快---不怎么消耗时间-忽略不计
ffmpeg -hwaccel dxva2 -i "D:/test1080.flv" -c:v copy -an "D:/linux-share-dir/video_file/output1.mp4"

(2)合并音频到视频:---要重新CPU编码--费时间
ffmpeg -hwaccel dxva2 -i "D:/linux-share-dir/video_file/output1.mp4" -i "C:/Users/11266/Music/xiaola.mp3" "D:/linux-share-dir/video_file/output2.mp4"

(3)合并音频到视频:---要重新编码--费时间--可以选择GPU硬件编码---速度很快
ffmpeg -hwaccel dxva2 -i "D:/linux-share-dir/video_file/output1.mp4" -hwaccel dxva2 -i "C:/Users/11266/Music/xiaola.mp3" -c:v h264_qsv "D:/linux-share-dir/video_file/output2.mp4"


视频音频参数转换:
ffmpeg -i "D:/test1080.flv" -y -qscale 0 -vcodec libx264 -acodec aac -ac 1 -ar 48000  out1.mp4


//添加图片水印
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -i D:/666.mp4 -vf "movie=D:/linux-share-dir/video_file/test/image/123.png[wm];[in][wm]overlay=30:10[out]" D:/linux-share-dir/video_file/test/output1.mp4
参数解析:
1. D:/666.mp4 输入的视频
2. image/123.png 要添加进去的图片水印
3. D:/linux-share-dir/video_file/test/output.mp4 合成水印之后输出的视频


//硬件解码、软件编码---主要是编码消耗时间---这个还是很慢
ffmpeg -hwaccel dxva2 -i "D:/test1080.flv" -vf "movie=123.png[wm];[in][wm]overlay=30:10[out]" "D:/linux-share-dir/video_file/output1.mp4"


//硬件解码、软件编码---主要是编码消耗时间---使用GPU硬件编码,速度要快很多
ffmpeg -hwaccel dxva2 -i "D:/test1080.flv" -vf "movie=123.png[wm];[in][wm]overlay=30:10[out]" -c:v h264_qsv "D:/linux-share-dir/video_file/output1.mp4"

(21)ffmpeg获取视频截图

使用ffmpeg可以非常方便的生成视频截图,ffmpeg 通过指定 -vcodec 参数为 mjpeg,或者指定 -f 参数为 mjpeg时,可以输出 jpg截图,指定 -vcodec参数为png,或者指定输出文件扩展名为png,可输出png截图。如果参数指定不当,会导致ffmpeg处理速度非常缓慢。

代码语言:javascript复制
1. 输出 jpg
ffmpeg -ss 00:00:05 -i RevolutionOS.rmvb sample.jpg  -r 1 -vframes 1 -an -vcodec mjpeg

2. 输出 png
ffmpeg -ss 00:00:05 -i RevolutionOS.rmvb sample.png   -r 1 -vframes 1 -an -vcodec mjpeg
大概等待1秒钟,生成的jpg图像为19K,而png格式的图像为222k,大了很多倍,而质量上,并没有太大的差别,所以我决定生成jpg格式。

3. 50分钟处截屏
ffmpeg -ss 00:50:00  -i RevolutionOS.rmvb sample.jpg  -r 1 -vframes 1 -an -vcodec mjpeg
或者使用 -f 参数指定输出的格式为 mjpeg ,效果一样
ffmpeg -ss 00:50:00  -i RevolutionOS.rmvb sample.jpg  -r 1 -vframes 1 -an -f mjpeg

(22)视频尺寸不变,按比例缩放(画黑边)

代码语言:javascript复制
命令示例:
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -i D:/123.mp4 -vf "scale=100:100,pad=500:500:0:300:black" D:/linux-share-dir/video_file/output.mp4
参数解释:
500:500 画布的尺寸  .  (w:h)
100:100 视频帧在画布里的尺寸--按比例缩放的. (w:h)
0:300   视频帧在画面上的位置. (x:y)
black   画布的背景颜色
 

如果有多个视频文件加黑边之后,后续还需要合成一个视频,可以在输出的时候统一重新采样:
C:/FFMPEG/ffmpeg_x86_4.2.2/bin/ffmpeg.exe -i D:/Produce.mpg -vf "scale=100:100,pad=500:500:0:300:black"  -y -qscale 0 -vcodec libx264 -acodec aac -ac 1 -ar 22050 -s 500*500 -r 30 D:/linux-share-dir/video_file/test/output3.mp4
分辨率、帧率、音频采样率不一致是无法正常合并视频的。

(23)视频与图片之间互转

代码语言:javascript复制
视频转为图片:
# ffmpeg -i 123.mp4 image_%d.jpg
将 123.mp4 的视频每一帧画面保存为一张张图片。
图片转为视频:
# ffmpeg -f image2 -i image_%d.jpg video.mpg

(24)ffmpeg推流到rtmp服务器

代码语言:javascript复制
RTMP是Real Time Messaging Protocol(实时消息传输协议)的首字母缩写。是Adobe公司开发的一个基于TCP的应用层协议,也就是说,RTMP是和HTTP/HTTPS一样,是应用层的一个协议族。RTMP在TCP通道上一般传输的是flv 格式流。请注意,RTMP是网络传输协议,而flv则是视频的封装格式。flv封装格式设计出来的目的是为了用于网络传输使用的,因此RTMP FLV可以说是”黄金搭档“。

RTMP协议包括:基本协议及RTMPT/RTMPS/RTMPE等多种变种。从视频协议学习:推流拉流都擅长的 RTMP了解到,RTMP协议家族有以下几个点挺有趣,读者们不妨看看:

RTMP工作在TCP之上,默认使用端口1935,这个是基本形态;
RTMPE在RTMP的基础上增加了加密功能;
RTMPT封装在HTTP请求之上,可穿透防火墙;
RTMPS类似RTMPT,增加了TLS/SSL的安全功能;
RTMFP使用UDP进行传输的RTMP;
    
(1). 在Linux上运行: 推流本地实时音频视频到流媒体服务器
示例:
[wbyq@wbyq linux_c]$ ffmpeg -f video4linux2  -r 12 -s 640x480 -i /dev/video0 -f alsa -i default -ar 44100 -ac 1 -f mp3 -qscale 10 -f flv "rtmp://127.0.0.1:8086/live/123"

参数解析:
-f video4linux2 指定linux下的视频驱动框架
-s 640x480  指定视频尺寸
-i /dev/video0 摄像头节点
f alsa 声卡驱动框架
-i default  选择声卡,这里选择默认声卡
-ar 44100  声音采样频率
-ac 1   单声道
-f mp3  MP3音频
-qscale 10 设置画面质量,值越小画面质量越高
f flv   指定封装格式
"rtmp://127.0.0.1:8086/live/123"  流媒体服务器地址

    
(2). Linux下推流同时保存视频到本地
示例:
[wbyq@wbyq linux-share-dir]$ ffmpeg -thread_queue_size 128 -f video4linux2  -r 12 -s 1280x720 -i /dev/video0 -f alsa -i default -ar 44100 -ac 1 -f mp3 -qscale 5 -f flv "rtmp://127.0.0.1:8086/live/123" output.h264

参数解析:
当这个任务消耗有点大时,-thread_queue_size 必须设置一个比较大的值,不然会看到 FFmpeg输出的日志信息中不停的提醒:[video4linux2,v4l2 @ 0x25fbc40] Thread message queue blocking; consider raising the thread_queue_size option (current value: 8),拍摄到的视频也会出现莫名其妙的错误,比如帧率很高,无法正常播放,视频不流畅等等。把 -thread_queue_size 设置为一个比较大的值,直到看不到该提示即可。

    
    
 (3). 推流视频文件到流媒体服务器
视频文件地址:/Users/jack/test.mp4
推流拉流地址:rtmp://localhost:1935/rtmplive/home
acc:RTMP的音频格式
flv: RTMP的视频格式
ffmpeg -re -i /Users/jack/test.mp4 -vcodec libx264 -acodec aac -f flv rtmp://localhost:1935/rtmplive/home

(25)ffmpeg推流到rtsp服务器

(1)推流视频文件到RTSP服务器

代码语言:javascript复制
ffmpeg -re -i /home/xx/Documents/in.mp4 -c copy -f rtsp rtsp://192.168.74.130:8554/room1
-re  是以流的方式读取
-i  就是输入的文件
-f  格式化输出到哪里
-c copy 编码器不变

(2)将视频文件循环推到RTSP服务器

代码语言:javascript复制
ffmpeg -re -stream_loop -1 -i aa.mp4 -c copy -f rtsp rtsp://192.168.80.49:8554/mystream

(3)录制电脑屏幕并推流到RTSP服务器

代码语言:javascript复制
[1]
ffmpeg -f gdigrab -i desktop -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -f rtsp rtsp://192.168.80.49:8554/mystream


[2]
ffmpeg -re -thread_queue_size 128 -threads 8 -f x11grab -video_size 1920x1080 -framerate 26 -i :0 -vcodec libx264 -preset ultrafast -tune zerolatency -muxdelay 2 -fast-pskip true -buffer_size 10240000 -qp 50 -crf 26 -level 3 -rtsp_transport udp -s 960x540 -max_muxing_queue_size 128 -f rtsp rtsp://ip:port/live/test

(4)推流摄像头视频到RTSP服务器(windows)

代码语言:javascript复制
ffmpeg -f dshow -i video="Integrated Camera" -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -rtsp_transport udp -f rtsp rtsp://127.0.0.1/stream

六、总结

当前文章里先介绍FFmpeg工具集、以MP4、MP3为例介绍音视频文件的封装格式、编码格式,最后再列出了多个ffmpeg命令行处理音视频案例,方便大家快速了解ffmpeg的常用方法。但是ffmpeg的功能并不局限与此,当前文章只是重点介绍ffmpeg命令行处理方式,如果需要在项目里引用ffmpeg完成一些特定项目的开发。比如:视频播放器、音视频剪辑软件,特效制作软件等等,还需要对ffmpeg的源码进行深度了解,熟悉各个API的功能与调用方法。

0 人点赞