FFmpeg 视频处理等相关

七月 01, 2024 [虚拟化与容器] #obsidian #发行版 #容器 #音视频

FFmpeg 视频处理等相关

FFmpeg 是一个非常受欢迎的、完备的、跨平台的、开源的用于处理多媒体内容(如音频、视频、字幕及其他相关元数据)的库和工具集。本篇介绍 FFmpeg 的相关概念和基本使用方法。所有命令以 Ubuntu 为例进行介绍,Windows 和 Mac 同样适用。

FFmpeg 安装

想要使用 FFmpeg (Linux中对应的程序为 ffmpeg),必须首先安装它。Ubuntu(Centos 安装 FFmpeg的方法参考我的另一篇:Centos安装ffmpeg。Ubuntu 切换镜像源的方法参考我的另一篇:ubuntu 更改镜像源) 安装 FFmpeg 非常方便,命令如下:

1
2
sudo apt update
sudo apt install ffmpeg

容器

在介绍 FFmpeg 处理视频之前,我们需要对视频有个了解。从计算上来说,视频文件是一个容器 (container),在该容器中包含了视频(图片序列,无声音)、音频、字幕等内容。

常见的视频容器有如下几种,常常以文件后缀名来反映其容器格式:

FFmpeg 支持很多种容器,使用如下命令可查看它支持的格式有哪些:

1
ffmpeg -formats

特别说明:在 HTML5 中的 video 标签中支持三种视频格式:MP4,Webm,Ogg。如果网页出现没有视频画面的情况,可能是编码格式不正确。那三种视频格式分别支持的编码格式有:

编码格式

无论是视频还是音频都需要进行编码。不同的编码有不同的压缩率。编码可以将视频文件变得更小,但一定程度上会丢失信息,导致清晰度降低。

常用的视频编码格式:

常用的音频编码格式:

使用如下命令,可以查看 FFmpeg 支持的编码格式(包括视频和音频):

1
ffmpeg -codecs

编解码器

有了编码方法,需要一些程序或软件来实现文件(视频或音频)的编解码,这就是编解码器。

FFmpeg 中内置的视频编编解码器:

FFmpeg 中内置的音频编解码器有:

ffmpeg 命令的使用

ffmpeg 命令的格式如下:

1
ffmpeg [全局参数] [输入文件参数] -i 输入文件 [输出文件参数] [输出文件]

常用的参数有

查看视频元信息

1
2
3
4
5
6
7
ffmpeg -i input.mp4
ffprobe input.mp4
ffmpeg -i input.mp4 -hide_banner

更改容器格式(扩展名改变)

1
2
3
4
5
6
7
8
9
10
11
ffmpeg -i input.avi output.mp4
ffmpeg -i input.webm output.mp4
ffmpeg -i input.mkv output.mp4
ffmpeg -i input.webm -qscale 0 output.mp4

更改分辨率

改变视频分辨率(transsizing)

1
2
3
4
5
ffmpeg -i input.mp4 -filter:v scale=1280:720 -c:a copy output.mp4
ffmpeg -i input.mp4 -s 1280x720 -c:a copy output.mp4
ffmpeg -i input.mp4 -vf scale=480:-1 output.mp4

压缩视频文件

1
2
ffmpeg -i input.mp4 -vf scale=1280:-1 -c:v libx264 -preset veryslow -crf 24 output.mp4

压缩音频文件

1
2
ffmpeg -i input.mp3 -ab 128 output.mp3

更改编码格式(扩展名可不变)

1
2
3
4
5
ffmpeg -i input.mp4 -c:v libx264 output.mp4
ffmpeg -i input.mp4 -acodec copy -vcodec libx264 output.mp4

提取音频

1
2
3
4
5
6
7
8
9
10
11
12
13
ffmpeg -i input.mp4 -vn -c:a copy output.aac
ffmpeg -i input.mp4 -vn -c:a copy output.mp4
ffmpeg -i input.mp4 -vn -ar 44100 -ac 2 -ab 320 -f mp3 output.mp3

提取视频(没有声音)移除音频

1
2
ffmpeg -i input.mp4 -an -c:v copy output.mp4

转换音频格式

1
2
ffmpeg -i input.mp4 -acodec aac -vcodec copy output.mp4

添加音频(增加音轨)

1
ffmpeg -i input.aac -i input.mp4 output.mp4

多音轨只保留一个

有时候,有些电源有国语、粤语、英语等,但默认是英语,使得播放不方便(直接百度云或阿里云播放时,默认英文)。但想要直接用国语为默认播放语音,则可以如下:

1
2
3
4
5
6
ffmpeg -i 魔法满屋-英语国语粤语.mp4 -map 0:0 -map 0:2 -c copy -disposition0 default -y 魔法满屋-国语.mp4

调整码率

调整码率(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
2
3
ffmpeg -ss 01:23:45 -i input -vframes 1 -q:v 2 output.jpg

每秒提取一张图片

1
2
3
ffmpeg -i input.mp4 -r 1 -f image2 image-%2d.png
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ffmpeg -i input.mp4 %d.png
ffmpeg -i input.mp4 %06d.png
ffmpeg -i input.mp4 -vf fps=1 %06d.png
ffmpeg -i input.mp4 -vf fps=1/4 %06d.png
ffmpeg -ss 00:00:04 -i input.mp4 %06d.png
ffmpeg -ss 00:00:04 -t 2 -i input.mp4 %06d.png
ffmpeg -ss 00:00:04 -i input.mp4 -frames:v 1 screenshot.png
ffmpeg -i input.mp4 -s 640x480 %06d.png
ffmpeg -i input.mp4 -vf scale=640:-1 %06d.png

切分视频文件为多个部分

一些网站将仅允许上传具体指定大小的视频。此时需要切分大的视频文件到多个较小的部分

1
2
3
ffmpeg -i input.mp4 -t 00:00:30 -c copy part1.mp4 -ss 00:00:30 -codec copy part2.mp4

截取视频的中间一部分

1
2
3
4
5
6
7
ffmpeg -ss 00:01:00 -t 10 -i input.webm -c:v libx264 -c:a copy -strict -2 -y output.mp4

接合或合并多个视频部分到一个

创建包含所有需要合并的视频路径的 join.txt 文件。所有的视频都应该是相同的格式(相同的编码格式)。所有文件的路径应该按顺序逐个列出:

1
2
3
file /home/sk/myvideos/part1.mp4
file /home/sk/myvideos/part2.mp4
file /home/sk/myvideos/part3.mp4
1
2
3
ffmpeg -f concat -i join.txt -c copy output.mp4
ffmpeg -f concat -safe 0 -i join.txt -c copy output.mp4

裁剪

裁剪(cutting)指的是,截取原始视频里面的一个片段,输出为一个新视频。可以指定开始时间(start)和持续时间(duration),也可以指定结束时间(end)。

1
2
3
ffmpeg -ss [start] -i [input] -t [duration] -c copy [output]
ffmpeg -ss [start] -i [input] -to [end] -c copy [output]

选择范围裁剪

1
2
3
4
5
6
7
8
9
ffmpeg -i input.mp4 -filter:v "crop=w:h:x:y" output.mp4
ffmpeg -i input.mp4 -filter:v "crop=640:480:200:150" output.mp4

转换视频的某一部分到其他格式

1
2
3
ffmpeg -i input.mp4 -t 10 output.avi

设置视频的屏幕高宽比

1
2
3
ffmpeg -i input.mp4 -aspect 16:9 output.mp4

为音频添加封面

有些视频网站只允许上传视频文件。如果要上传音频文件,必须为音频添加封面,将其转为视频,然后上传。下面命令可以将音频文件,转为带封面的视频文件。

1
2
3
4
5
ffmpeg -loop 1 -i cover.jpg -i input.mp3 -c:v libx264 -c:a aac -b:a 192k -shortest output.mp4

常见字幕格式

不同的字幕文件有不同的格式,常见的字幕格式有:

字幕格式可以互相转换

1
2
ffmpeg -i subtitle.srt subtitle.vtt
ffmpeg -i subtitle.srt subtitle.ass

添加软字幕

软字幕也叫内挂字幕、封装字幕、内封字幕,字幕流等,就是把前面的外挂字幕的字幕文件嵌入到视频中作为流的一部分,如果一个视频有多个字幕流那么播放视频是还得选择对应的字幕流。外挂字幕是一个单独的外部字幕文件,格式类型一般有srt、vtt、ass等等。播放视频时,需要把外挂字幕和视频放在同一目录下,并在播放器中选择字幕文件才可以在视频中看到字幕。不管是外挂字幕还是软字幕,字幕要正常显示播放器必须要支持字幕的渲染。

1
2
3
4
5
6
7
ffmpeg -i input.mp4 -i subtitle.srt -map 0 -map 1 -c copy -c:v libx264 -crf 23 -preset veryfast output.mp4
ffmpeg -i input.mp4 -i subtitle.srt -c copy -c:v libx264 -crf 23 -preset veryfast output.mp4
ffmpeg -i input.mp4 -f srt -i subtitle.srt -c:v copy -c:a copy -c:s mov_text output.mp4

添加硬字幕

硬字幕就是嵌入到视频帧里面的字幕,它就像视频水印一样作为视频帧的一分部分了,不管再任何平台字幕看起来都是一样的,而且也不再要求播放器单独对字母进行渲染。

1
ffmpeg -i input.mp4 -vf subtitles=subtitle.srt output.mp4
1
2
ffplay video.mp4
ffplay audio.mp3

增加/减少视频播放速度

1
2
3
4
5
ffmpeg -i input.mp4 -vf "setpts=0.5*PTS" output.mp4
ffmpeg -i input.mp4 -vf "setpts=4.0*PTS" output.mp4

视频/图片到 gif

截取视频部分到 gif

1
2
3
4
5
6
7
8
9
10
11
ffmpeg -ss 00:00:20 -i input.mp4 -to 10 -r 10 -vf scale=200:-1 output.gif
ffmpeg -i small.mp4 -b 2048k small.gif

把图片序列合成gif

1
2
3
4
5
ffmpeg -f image2 -framerate 9 -i image_%003d.jpg -vf scale=531x299,transpose=1,crop=299,431,0,100 -loop -1 out.gif

gif 转 视频

1
2
3
4
5
6
7
ffmpeg -f gif -i animation.gif animation.mp4
ffmpeg -i input.gif -vf scale=420:-2,format=yuv420p out.mp4
ffmpeg -i guoying.gif -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" video.mp4

图片合成视频

1
ffmpeg -framerate 30 -pattern_type glob -i '*.png' -c:v libx264 -pix_fmt yuv420p out.mp4

也可以指定不同路径的图片,需要把各图片路径写的 input.txt 中,格式大概如下:

1
2
file '/home/jinzhongxu/a/b/c.png'
file '/home/jinzhongxu/d/f/g/k.png'

合成方法如下:

1
2
3
ffmpeg -f concat -i input.txt -framerate 1 -i orig/audio.ogg -c:v libx264 -c:a copy -shortest -r 30 -pix_fmt yuv420p output.mp4

ffprobe 命令的使用

ffprobe 一般和 ffmpeg 一起被安装,它是非常强大的视频分析工具,可非常方便的从多媒体视流(视频、音频等)中获取文件描述信息,并且可以指定的格式输出结果。

显示视频总帧数、宽、高等信息

1
ffprobe -show_streams xc.mp4

也可以屏蔽版本参数信息:

1
ffprobe -v quiet -show_streams xc.mp4

已 json 格式显示结果:

1
2
ffprobe -v quiet -print_format json -show_streams xc.mp4

只看指定的信息

1
2
3
ffprobe -v quiet -select_streams v -show_entries stream=r_frame_rate xc.mp4

显示每一帧的信息

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
2
man ffprobe
ffprobe --help

文件名中含空格

如果文件名中含有空格,直接使用 ffmpeg 会报错,此时,需要把文件名用双引号括起来:

1
ffmpeg -i "input 2023.05.08.avi" -c:v libx264 "output 2023.05.08.mp4"

参考链接

  1. How to Install and Use FFmpeg on Ubuntu 18.04
  2. FFmpeg 视频处理入门教程
  3. 给新手的 20 多个 FFmpeg 命令示例
  4. ffmpeg-给视频添加字幕(二十四) - 简书
  5. centos8平台用ffprobe获取视频文件信息(ffmpeg4.2.2)
  6. 使用 ffmpeg 实现 MP4 与 GIF 的互转
  7. gvoze32/ffmpeg GIF to MP4.MD
  8. How to Extract Images from a Video Using FFmpeg