最近在写文章的时候,要应用视频介绍,就顺道研究学习了一下,发现这个事情并不简单,博客想完全自己放视频,不引用外部视频网站的链接,折腾的还挺多,终于折腾出一个方案。
FFmpeg
FFmpeg 是视频处理最常用的开源软件。它功能强大,用途广泛,大量用于视频网站和商业软件,也是许多音频和视频格式的标准编码/解码实现,可以根据 官方文档 先完成安装,然后把目录下的bin文件夹加到系统环境变量。然后 CMD 输入 $ ffmpeg
可以看见版本信息就说明好了。
一些概念
视频容器
视频文件本身其实是一个容器(container),里面包括了视频和音频,也可能有字幕等其他内容,常见的容器格式有以下几种。一般来说,视频文件的后缀名反映了它的容器格式。查看 FFmpeg 支持的容器 $ ffmpeg -formats
- MP4
- MKV
- WebM
- AVI
编码格式
视频和音频都需要经过编码,才能保存成文件。不同的编码格式(CODEC),有不同的压缩率,会导致文件大小和清晰度的差异。常用的视频编码
- H.262
- H.264
- H.265
⬆️ 上面的编码格式都是有版权的,但是可以免费使用。此外,还有几种无版权的视频编码格式 ⬇️
- VP8
- VP9
- AV1
常用的音频编码
- MP3
- AAC
⬆️上面所有这些都是有损的编码格式,编码后会损失一些细节,以换取压缩后较小的文件体积。无损的编码格式压缩出来的文件体积较大,这里就不介绍了,可以查看 FFmpeg 支持的编码格式,视频编码和音频编码 $ ffmpeg -codecs
编码器
编码器(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}
上面命令中,五个部分的参数依次如下
- 全局参数
- 输入文件参数
- 输入文件
- 输出文件参数
- 输出文件
参数太多的时候,为了便于查看,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的切片,视频转码流 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
GPU
ffmpeg 默认使用CPU跑的,CPU跑这种任务性能自然就不必多说了,电脑一般的,直接爆炸,或者根本跑不动,好在 ffmpeg 是支 GPU的,GPU虽然速度快,但是质量不高,处理后的视频体积较大。而我主要是优化视频体积和质量的,因此在生产环境中我几乎没有用过GPU进行加速,只是在测试时用了下。AMD显卡请直接放弃,不用折腾了,我已经折腾过了,吐血经历只有自己知道。
首先要先安装显卡驱动CUDA
CUDA是Nvidia出的一个GPU计算库,让程序可以驱动Nvidia显卡的GPU进行各种工作,其中就包含了视频的编解码,怎么安装请自行百度下,内容太多,又可以写两篇文章了,这里就不赘述了。查询使用的ffmpeg版本是否支持 CUDA $ ffmpeg -hwaccels
-hwaccel cuvid:指定使用cuvid硬件加速
$ ffmpeg -hwaccel cuvid -c:v h264_cuvid -i 0.mp4 -c:v h264_nvenc -y 00.mp4
将当前目录下的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。视频储存是很多人的一个难题,如果自己买个服务器又需要带宽有需要硬盘够大,如果你服务器牛逼,放自己服务器也可以。个人站长来说流量和存储两部分的费用一般人是玩不起的,反正我是玩不起。其次速度也很重要,不然放出来卡的鸭皮。
这个方案也是目前我在使用的方案,在经历,从播放器,到视频格式,到兼容设备,到云存储,到播放效果几个环节的折腾,终于得出非常低成本,低维护,却高效的方案。
✅播放器的选择:我用的是 DPlayer,这个播放器非常好用,支持 HLS,MP4,flv,mkv等众多格式的播放,在设备的兼容性也非常好,无论是移动端,还是苹果,PC,安卓都兼容。也很轻量化,我用了这么久是没发现任何问题的,并且是开源的。 项目地址
✅视频流的选择:目前我的是使用hls的视频流,然后把视频进行切片处理,并生成m3u8索引,且m3u8也是目前主流的视频方案,许多大厂除了自己研发格式外,或者搞直播的,基本都是采用的这种方案。hls支持的设备很完全,其次是MP4的格式。mkv和flv等格式大部分都在苹果设备上都不支持的,第二就是视频源要进行TS切片,每片的大小约2M左右就好,这样利于加载速度和节约流量,再搭配一个好的存储环境基本可以做到秒开。
m3u8 与 MP4 对比
对m3u8 与MP4 做一个简单对比
- MP4 对 HTML5 和 flash 播放器亲和度都挺好。但是文件头太大,需要加载完成才能播放,其次结构复杂,长视频的大文件头影响加载速度的视频体验,所以 MP4 在短视频的应用更常见
- m3u8 采用苹果的 HLS 协议,目前 ios与android设备均已支持。由于其工作原因是将整个视频流分成一个个小的基于 Http 的文件进行下载播放,因此支持视频直播,和视频加速播放。
简单的来说就是,体积不大的视频用MP4更好,体积超过100M的视频用m3u8更好,更多信息可以自己百度下
✅视频存储的选择:
稳定很重要,不要把视频传上去后,过不久就丢了,那你幸幸苦苦搞得全白费了。
速度要快,有钱的可以选择云厂商的对象存储,买个流量套餐包,体积在5G以内的视频基本上50块就就搞定,配上m3u8可以最大程度上节约流量。我的存储是放在阿里云上的,然后用 AList 搭建的网盘,获取直链,就完全不考虑流量和并发的问题,只是处理视频的时候麻烦点而已,视频源需要固定的直链,这个非常重要。
需要注意一点,使用 m3u8 做索引的时候,存储源一定要允许跨域请求,不然有时候会出现无法播放,或者播放一半就播放不了的情况。
页面嵌入
<iframe src="https://api.nxvav.cn/api/m3u8/?url=https://p.tiax.cn/d/cloud189/2077/a.m3u8" allowfullscreen="allowfullscreen" mozallowfullscreen="mozallowfullscreen" msallowfullscreen="msallowfullscreen" oallowfullscreen="oallowfullscreen" webkitallowfullscreen="webkitallowfullscreen" width="100%" height="500px" frameborder="0"></iframe>
此处评论已关闭