FFmpeg

FFmpeg 是视频处理最常用的开源软件。它功能强大,用途广泛,大量用于视频网站和商业软件,也是许多音频和视频格式的标准编码/解码实现。

什么?! 你还没安装,可以根据 官方文档 先完成安装。
然后把目录下的bin文件夹加到系统环境变量。然后CMD输入 ffmpeg可以看见版本信息就说明好了

环境变量
环境变量
版本信息
版本信息

 

基本概念

1 .容器

视频文件本身其实是一个容器(container),里面包括了视频和音频,也可能有字幕等其他内容。
常见的容器格式有以下几种。一般来说,视频文件的后缀名反映了它的容器格式。

  • MP4
  • MKV
  • WebM
  • AVI

查看 FFmpeg 支持的容器

$ ffmpeg -formats

 

2 .编码格式

视频和音频都需要经过编码,才能保存成文件。不同的编码格式(CODEC),有不同的压缩率,会导致文件大小和清晰度的差异。

常用的视频编码

  • H.262
  • H.264
  • H.265

上面的编码格式都是有版权的,但是可以免费使用。此外,还有几种无版权的视频编码格式

  • VP8
  • VP9
  • AV1

常用的音频编码

  • MP3
  • AAC

上面所有这些都是有损的编码格式,编码后会损失一些细节,以换取压缩后较小的文件体积。无损的编码格式压缩出来的文件体积较大,这里就不介绍了,可以查看 FFmpeg 支持的编码格式,视频编码和音频编码

$ ffmpeg -codecs

 

3 .编码器

编码器(encoders)是实现某种编码格式的库文件。只有安装了某种格式的编码器,才能实现该格式视频/音频的编码和解码。

这是一些 FFmpeg 内置的视频编码器

  • libx264:最流行的开源 H.264 编码器
  • NVENC:基于 NVIDIA GPU 的 H.264 编码器
  • libx265:开源的 HEVC 编码器
  • libvpx:谷歌的 VP8 和 VP9 编码器
  • libaom:AV1 编码器

音频编码器如下

  • libfdk-aac
  • aac

查看 FFmpeg 已安装的编码器

$ ffmpeg -encoders

 

参数

$ ffmpeg {1} {2} -i {3} {4} {5}

上面命令中,五个部分的参数依次如下

1. 全局参数
2. 输入文件参数
3. 输入文件
4. 输出文件参数
5. 输出文件

参数太多的时候,为了便于查看,ffmpeg 命令可以写成多行

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

例子

$ ffmpeg \
-y \ # 全局参数
-c:a libfdk_aac -c:v libx264 \ # 输入文件参数
-i input.mp4 \ # 输入文件
-c:v libvpx-vp9 -c:a libvorbis \ # 输出文件参数
output.webm # 输出文件

上面的命令将 mp4 文件转成 webm 文件,这两个都是容器格式。输入的mp4 文件的音频编码格式是 aac,视频编码格式是 H.264;输出的 webm 文件的视频编码格式是 VP9,音频格式是 Vorbis
如果不指明编码格式,FFmpeg 会自己判断输入文件的编码。
因此,上面的命令可以简单写成下面的样子

$ ffmpeg -i input.avi output.mp4

 

实例

这是我最常用的,也是博客上视频使用的方式,把MP4切割成TS的切片,并生成M3U8索引,视频转码流hls和音频ACC时间

$ ffmpeg -i mp4\22.mp4 -c:v libx264 -hls_time 10 -hls_list_size 0 -c:a aac -threads 5 -preset ultrafast -strict -2 -f hls ia223\itgsa.m3u8

命令说明

  • -i 源视频绝对路径
  • -c 视频流和没一片的时间 time这里 8,表示每片8秒时长
  • -threads 5 -preset 使用多线程,如果你的设备好,可以多开几个
  • acc 音频
  • strict -2 -f hls 存放的绝对路径
  • .m3u8 输入的文件名,不要写数字,顺序容易出错

注:使用多线程切出来的积极较大,几乎会增加一半的体积,看个人需要,下面是使用默认线程切割

$ ffmpeg -i mp4\33.mp4 -c:v libx264 -hls_time 8 -hls_list_size 0 -c:a aac -strict -2 -f hls ia223\itgsa.m3u8

开始切割

切割

完成之后是这样子的,第一个是索引文件

完成

不转码直接切,切的很快

ffmpeg -i 1.mp4 -c copy -strict -2 -bsf:v h264_mp4toannexb -f hls -hls_list_size 0 -hls_time 10 test/1.m3u8

 

转码

$ ffmpeg -i out.ogv -vcodec h264 out.mp4
$ ffmpeg -i out.ogv -vcodec mpeg4 out.mp4
$ ffmpeg -i out.ogv -vcodec libxvid out.mp4
$ ffmpeg -i out.mp4 -vcodec wmv1 out.wmv
$ ffmpeg -i out.mp4 -vcodec wmv2 out.wmv

-i 后面是输入文件名,-vcodec 后面是编码格式,h264 最佳,但 Windows 系统默认不安装,如果是要插入 ppt 的视频,选择 wmv1 或 wmv2 基本上万无一失。
附加选项

  • -r 指定帧率
  • -s 指定分辨率
  • -b 指定比特率

于此同时可以对声道进行转码

  • -acodec 指定音频编码
  • -ab 指定音频比特率
  • -ac 指定声道数

$ ffmpeg -i out.ogv -s 640x480 -b 500k -vcodec h264 -r 29.97 -acodec libfaac -ab 48k -ac 2 out.mp4

 

剪切

-ss -t 选项, 从第 30 秒开始,向后截取 10 秒的视频,并保存

$ ffmpeg -i input.wmv -ss 00:00:30.0 -c copy -t 00:00:10.0 output.wmv
$ ffmpeg -i input.wmv -ss 30 -c copy -t 10 output.wmv

达成相同效果,也可以用 -ss -to 选项, 从第 30 秒截取到第 40

$ ffmpeg -i input.wmv -ss 30 -c copy -to 40 output.wmv

值得注意的是,ffmpeg 为了加速,会使用关键帧技术, 所以有时剪切出来的结果在起止时间上未必准确。 通常来说,把 -ss 选项放在 -i 之前,会使用关键帧技术; 把 -ss 选项放在 -i 之后,则不使用关键帧技术。 如果要使用关键帧技术又要保留时间戳,可以加上 -copyts 选项

$ ffmpeg -ss 00:01:00 -i video.mp4 -to 00:02:00 -c copy -copyts cut.mp4

 

合并

把多个个视频文件合并成一个,在视频文件所在目录下新建一个文件filelist.txt,内容如下

file '1.mp4'
file '2.mp4'
file '3.mp4'
file '4.mp4'
file '5.mp4'
file '6.mp4'

在目录执行

ffmpeg -f concat -i filelist.txt -c copy output.mp4

更多时候,由于输入文件的多样性,需要转成中间格式再合成

ffmpeg -i input1.avi -qscale:v 1 intermediate1.mpg
ffmpeg -i input2.avi -qscale:v 1 intermediate2.mpg
cat intermediate1.mpg intermediate2.mpg > intermediate_all.mpg
ffmpeg -i intermediate_all.mpg -qscale:v 2 output.avi

 

GPU

ffmpeg默认使用CPU跑的,CPU跑这种任务性能自然就不必多说了,电脑一般的,直接爆炸,或者根本跑不动,好在ffmpeg是支持GPU的,GPU虽然速度快,但是质量不高,处理后的视频体积较大。而我主要是优化视频体积和质量的,因此在生产环境中我几乎没有用过GPU进行加速,只是在测试时用了下。AMD显卡请直接放弃,不用折腾了,我已经折腾过了 吐血经历只有自己知道

 
1、首先要先安装显卡驱动CUDA
CUDANvidia出的一个GPU计算库,让程序可以驱动Nvidia显卡的GPU进行各种工作,其中就包含了视频的编解码,怎么安装请自行百度下,内容太多,又可以写两篇文章了,这里就不赘述了。

 
2、查询使用的ffmpeg版本是否支持 CUDA,小站网盘提供的下载版本是支持的,在ZIP里,自己下载

$ ffmpeg -hwaccels

查看

 
3、测试下
参数

  • -hwaccel cuvid:指定使用cuvid硬件加速
$ ffmpeg -hwaccel cuvid -c:v h264_cuvid -i 0.mp4 -c:v h264_nvenc -y 00.mp4
1

将当前目录下的0.mp4转成00.mp4

$ ffmpeg -hwaccel cuvid -c:v h264_cuvid -i 0.mp4 -c:v h264_nvenc -r 15 -b 500k -y 00.mp4

 

个人站长视频解决方案

说实话,对于个人博客上放视频,有点难搞,涉及到两个最大的问题,第一无非就是流量和存储环境的问题,第二还有速度的问题,一个视频几百M,放几次流量就去没了几个G。视频储存是很多人的一个难题,如果自己买个服务器又需要带宽有需要硬盘够大,如果你服务器牛逼,放自己服务器也可以,那么这个方案就不用看了。小白请直接劝退,这部分内容不写教怎么一步一步做,而是解决思路和方法。

对于个人站长来说流量和存储两部分的费用一般人是玩不起的,反正我是玩不起。其次速度也很重要,不然放出来卡的鸭皮,谁TM看啊。放5秒 卡1秒,看的人直接心态爆炸,看尼玛

这个方案也是目前我在使用的方案,在经历,从播放器,到视频格式,到兼容设备,到云存储,到播放效果几个环节的折腾,终于得出非常低成本,低维护,却高效的方案,我另一个音乐站(blog.itggg.cn)放了几十个视频上去,播放一点也不卡,进度条随便拖,几百个人同时看都可以,苹果,安卓,PC,都可以完美支持。

 
1、播放器的选择:我用的是 DPlayer,这个播放器非常好用,支持HLS,MP4,flv,mkv等众多格式的播放,在设备的兼容性也非常好,无论是移动端,还是苹果,PC,安卓都兼容。也很轻量化,我用了这么久是没发现任何问题的,并且是开源的。 项目地址

 
2、视频流的选择:目前我的是使用hls的视频流,然后把视频进行切片处理,并生成m3u8索引,且m3u8也是目前主流的视频方案,许多大厂除了自己研发格式外,或者搞直播的,基本都是采用的这种方案。hls支持的设备很完全,其次是MP4的格式。mkv和flv等格式大部分都在苹果设备上都不支持的,第二就是视频源要进行TS切片,每片的大小约2M左右就好,这样利于加载速度和节约流量,再搭配一个好的存储环境基本可以做到秒开。

 

m3u8 与 MP4 对比

对m3u8 与MP4 做一个简单对比

  • MP4HTML5flash播放器亲和度都挺好。但是文件头太大,需要加载完成才能播放,其次结构复杂,长视频的大文件头影响加载速度的视频体验,所以MP4在短视频的应用更常见
  • m3u8 采用苹果的HLS协议,目前 iosandroid设备均已支持。由于其工作原因是将整个视频流分成一个个小的基于Http的文件进行下载播放,因此支持视频直播,和视频加速播放。

简单的来说就是,体积不大的视频用MP4更好,体积超过100M的视频用m3u8更好,更多信息可以自己百度下

播放对比,这个MP4源视频体积约266M,切片后总约大小14M

 

MP4播放


M3U8播放

 
3、视频存储的选择
3.1.稳定很重要,不要把视频传上去后,过不久就丢了,那你幸幸苦苦搞得全白费了。

3.2.速度要快,有钱的可以选择云厂商的对象存储,买个流量套餐包,体积在5G以内的视频基本上50块就就搞定,配上m3u8可以最大程度上节约流量。没钱的可以选择一些免费的图床啊啥的,比如github,npm这些。
还有一种非常快且安全的方法是,把你的站接入百度云加速,视频都放在服务器上,然后在百度云加速上面的 “特定页面规则” 去缓存目录里所有的TS切片,这样你服务器目录下的TS切片就全部缓存在百度云的节点上面了,百度云的节点有多快就不必多说了。
前两种免费的方法都有限制,gitbuh上传切片麻烦,且单一文件最大20M。百度云节点的缓存命中率也不是特别高,且免费流量每天10G,视频不多的可以考虑。想完全白嫖几乎不太可能,如果你真的做到了,请留言分享下好吗,我在这里先谢谢您了

我的存储是放在世纪互联的OneDrive上的,就完全不考虑流量和并发的问题,只是处理视频的时候麻烦点而已

3.3.视频源需要固定的直链,这个非常重要。

需要注意一点,使用m3u8做索引的时候,存储源一定要允许跨域请求,不然有时候会出现无法播放,或者播放一半就播放不了的情况。

最后,这个方案也是我折腾了很久才搞出来的屌丝站长视频播放终极解决方案,希望对你有帮助,请我喝杯奶茶也可以,谢谢您,谢谢您全家

Last modification:April 10, 2022
如果你想请我喝奶茶的话