FFmpeg 视频处理等相关
FFmpeg 是一个非常受欢迎的、完备的、跨平台的、 开源的 用于处理多媒体内容(如音频、视频、字幕及其他相关元数据)的库和工具集。本篇介绍 FFmpeg 的相关概念和基本使用方法。所有命令以 Ubuntu 为例进行介绍,Windows 和 Mac 同样适用。
FFmpeg 安装
想要使用 FFmpeg (Linux中对应的程序为
ffmpeg
),必须首先安装它。Ubuntu(Centos 安装 FFmpeg的方法参考我的另一篇:
Centos安装ffmpeg
。Ubuntu 切换镜像源的方法参考我的另一篇:
ubuntu 更改镜像源
) 安装 FFmpeg 非常方便,命令如下:
1 |
sudo apt update |
容器
在介绍 FFmpeg 处理视频之前,我们需要对视频有个了解。从计算上来说,视频文件是一个容器 (container),在该容器中包含了视频(图片序列,无声音)、音频、字幕等内容。
常见的视频容器有如下几种,常常以文件后缀名来反映其容器格式:
FFmpeg 支持很多种容器,使用如下命令可查看它支持的格式有哪些:
1 |
ffmpeg -formats |
特别说明:在 HTML5 中的 video 标签中支持三种视频格式:MP4,Webm,Ogg。如果网页出现没有视频画面的情况,可能是编码格式不正确。那三种视频格式分别支持的编码格式有:
编码格式
无论是视频还是音频都需要进行编码。不同的编码有不同的压缩率。编码可以将视频文件变得更小,但一定程度上会丢失信息,导致清晰度降低。
常用的视频编码格式:
常用的音频编码格式:
使用如下命令,可以查看 FFmpeg 支持的编码格式(包括视频和音频):
1 |
ffmpeg -codecs |
编解码器
有了编码方法,需要一些程序或软件来实现文件(视频或音频)的编解码,这就是编解码器。
FFmpeg 中内置的视频编编解码器:
FFmpeg 中内置的音频编解码器有:
ffmpeg 命令的使用
1 |
ffmpeg [全局参数] [输入文件参数] -i 输入文件 [输出文件参数] [输出文件] |
常用的参数有
-c
:指定编码器
-c copy
:直接复制,不经过重新编码(这样比较快)
-c:v
:指定视频编码器
-c:a
:指定音频编码器
-i
:指定输入文件
-an
:去除音频流
-vn
: 去除视频流
-preset
:指定输出的视频质量,会影响文件的生成速度,有以下几个可用的值 ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow。
-y
:不经过确认,输出时直接覆盖同名文件。
查看视频元信息
1 |
ffmpeg -i input.mp4 |
更改容器格式(扩展名改变)
1 |
# 把 avi 视频转换为 mp4 视频 |
更改分辨率
1 |
# 缩放视频到较小的显示设备上,例如平板电脑和手机 |
压缩视频文件
1 |
# 减小视频文件的大小,将损失视频质量。如果 24 太有侵略性,可以降低 -crf 值到或更低值 |
压缩音频文件
1 |
# 96kbps, 112kbps, 128kbps, 160kbps, 192kbps, 256kbps, 320kbps |
更改编码格式(扩展名可不变)
1 |
# 把 H.265 更改为 H.264 编码,(这里以 MP4 容器输入文件 input.mp4 为例,其他容器格式也可以) |
提取音频
1 |
# -vn表示去掉视频,-c:a copy表示不改变音频编码,直接拷贝。 |
提取视频(没有声音)移除音频
1 |
# 速度较快 |
转换音频格式
1 |
# 网页播放视频需要aac音频编码。视频不转码,直接拷贝。 |
添加音频(增加音轨)
1 |
ffmpeg -i input.aac -i input.mp4 output.mp4 |
多音轨只保留一个
有时候,有些电源有国语、粤语、英语等,但默认是英语,使得播放不方便(直接百度云或阿里云播放时,默认英文)。但想要直接用国语为默认播放语音,则可以如下:
1 |
# -map 0:0 表示视频,无声 |
调整码率
调整码率(transrating)指的是,改变编码的比特率,一般用来将视频文件的体积变小。下面的例子指定码率最小为964K,最大为3856K,缓冲区大小为 2000K。
1 |
ffmpeg -i input.mp4 -minrate 964K -maxrate 3856K -bufsize 2000K output.mp4 |
截图
从指定时间开始00:01:24,连续对1秒钟00:00:01的视频进行截图。
1 |
ffmpeg -i input.mp4 -ss 00:01:24 -t 00:00:01 output_%3d.jpg |
如果只需要截一张图,可以指定只截取一帧。
1 |
# -vframes 1指定只截取一帧 |
每秒提取一张图片
1 |
# -r – 设置帧速度。即,每秒提取帧到图像的数字。默认值是 25 |
1 |
# 从视频提取图像的基本命令:把每一帧都保留下来,即使用默认帧率保存图像 |
切分视频文件为多个部分
一些网站将仅允许上传具体指定大小的视频。此时需要切分大的视频文件到多个较小的部分
1 |
# -t 00:00:30 表示从视频的开始到视频的第 30 秒创建一部分视频 |
截取视频的中间一部分
1 |
# -ss 表示从视频的第 00:01:00 时刻开始截取 |
接合或合并多个视频部分到一个
创建包含所有需要合并的视频路径的
join.txt
文件。所有的视频都应该是相同的格式(相同的编码格式)。所有文件的路径应该按顺序逐个列出:
1 |
file /home/sk/myvideos/part1.mp4 |
1 |
ffmpeg -f concat -i join.txt -c copy output.mp4 |
裁剪
裁剪(cutting)指的是,截取原始视频里面的一个片段,输出为一个新视频。可以指定开始时间(start)和持续时间(duration),也可以指定结束时间(end)。
1 |
# -t 表示总的持续时间 |
选择范围裁剪
1 |
# -filter:v – 表示视频过滤器 |
转换视频的某一部分到其他格式
1 |
# 转换视频 input.mp4 文件的开始 10 秒到视频 .avi 格式 |
设置视频的屏幕高宽比
1 |
# 常用宽高比: |
为音频添加封面
有些视频网站只允许上传视频文件。如果要上传音频文件,必须为音频添加封面,将其转为视频,然后上传。下面命令可以将音频文件,转为带封面的视频文件。
1 |
# cover.jpg 是封面图片 |
添加字幕到一个视频文件
常见字幕格式
字幕格式可以互相转换
1 |
ffmpeg -i subtitle.srt subtitle.vtt |
添加软字幕
1 |
ffmpeg -i input.mp4 -i subtitle.srt -map 0 -map 1 -c copy -c:v libx264 -crf 23 -preset veryfast output.mp4 |
添加硬字幕
硬字幕就是嵌入到视频帧里面的字幕,它就像视频水印一样作为视频帧的一分部分了,不管再任何平台字幕看起来都是一样的,而且也不再要求播放器单独对字母进行渲染。
1 |
ffmpeg -i input.mp4 -vf subtitles=subtitle.srt output.mp4 |
1 |
ffplay video.mp4 |
增加/减少视频播放速度
1 |
# 增加播放速度 |
视频/图片到 gif
1 |
# -ss : indicates the starting point of GIF |
把图片序列合成gif
1 |
# -framerate 越小越慢 |
gif 转 视频
1 |
# 一般 |
图片合成视频
1 |
ffmpeg -framerate 30 -pattern_type glob -i '*.png' -c:v libx264 -pix_fmt yuv420p out.mp4 |
也可以指定不同路径的图片,需要把各图片路径写的
input.txt
中,格式大概如下:
1 |
file '/home/jinzhongxu/a/b/c.png' |
合成方法如下:
1 |
# -framerate 表示一副图一帧 |
ffprobe 命令的使用
ffprobe 一般和 ffmpeg 一起被安装,它是非常强大的视频分析工具,可非常方便的从多媒体视流(视频、音频等)中获取文件描述信息,并且可以指定的格式输出结果。
显示视频总帧数、宽、高等信息
1 |
ffprobe -show_streams xc.mp4 |
也可以屏蔽版本参数信息:
1 |
ffprobe -v quiet -show_streams xc.mp4 |
已 json 格式显示结果:
1 |
# 除 json 外,还可以指定 xml, csv, ini 等 |
只看指定的信息
1 |
# 只显示视频帧率 r_frame_rate |
显示每一帧的信息
1 |
ffprobe -v quiet -print_format json -show_frames xc.mp4 |
显示包信息
1 |
ffprobe -v quiet -print_format json -show_packets xc.mp4 |
显示封装格式信息
1 |
ffprobe -v quiet -print_format json -show_format xc.mp4 |
更多是使用如下命令查看:
1 |
man ffprobe |
文件名中含空格
如果文件名中含有空格,直接使用 ffmpeg 会报错,此时,需要把文件名用双引号括起来:
1 |
ffmpeg -i "input 2023.05.08.avi" -c:v libx264 "output 2023.05.08.mp4" |