写点什么

FFmpeg 的一些使用实践

作者:为自己带盐
  • 2021 年 12 月 25 日
  • 本文字数:3857 字

    阅读完需:约 13 分钟

FFmpeg的一些使用实践

背景

之前基于 ffmpeg 这个工具上做过一些扩展性的探索,主要是录像,直播推流,拉流以及转流,简单介绍下这几个功能。

录像

录像我觉得主要是两种需求一是录屏幕,就是把你的操作过程录下来,主要用在录制操作流程,教程的方面;另一个就是调用摄像头来录像;这两点 FFmpeg 都可以轻松做到首先要录像的话,需要检测一下设备,摄像头,麦克风之类的,当然如果你要录屏的话,摄像头不是必须的,但需要安装一个小插件,名字叫:dshow 下载地址:https://sourceforge.net/projects/screencapturer/files/(其实不安装也可以,下面我会介绍到)然后通过如下指令获取音视频设备

ffmpeg -list_devices true -f dshow -i dummy
复制代码

回车确定后,计算机给出设备列表,如下


我画红圈的地方,是我们获取的录屏软件的设备名字,如果需要录屏的话,借助刚才我们安装的 screen-capture-recorder 来完成,通过如下指令来操作只录制视频

ffmpeg -f dshow -i video="screen-capture-recorder" v-out.mp4
复制代码

只录制音频

ffmpeg -f dshow -i audio="screen-capture-recorder" a-out.aac
复制代码

同时录制音视频

ffmpeg -f dshow -i video="screen-capture-recorder":audio="virtual-audio-capturer" av-out.mp4
复制代码

还可以查看一些视频录制的可选参数

ffmpeg -f dshow -list_options true -i video="screen-capture-recorder"
复制代码

我的机器得到的结果如下

通过这些参数,我们可以制定录制的一些特殊选项,比如指定录制的长宽比,帧率,清晰度等

ffmpeg -f dshow -video_size 1680x1050 -framerate 30 -pixel_format yuv420p -i video="screen-capture-recorder":audio="virtual-audio-capturer" av-out.mp4
复制代码


前面指定的设备名字,如果改成摄像头和麦克风的名称,就可以录制实时拍到的画面了,比如我的输入摄像头名字为 c922 Pro Stream Webcam,为了获取摄像头的画面,就可以这样

ffmpeg -f dshow -i video="c922 Pro Stream Webcam" v-out.mp4
复制代码

录下来的画面是这样

前面我提到,不通过 screen-capture-recorder 也可以录屏的,相关的指令如下

ffmpeg -f gdigrab -i desktop out.mp4
复制代码

同样,也可以指定屏幕尺寸和帧率

ffmpeg -f gdigrab -framerate 5 -offset_x 10 -offset_y 20 -video_size 640x480 -i desktop out.mp4
复制代码

注意,这个 gdigrab 是基于 GDI 的抓屏设备,只适用于 Windows 环境的,linux 的环境我这里没有介绍,因为我也没在 linux 上玩转,所以留到该系列的第 3 篇再写吧~

推流

推流的话,现在一般都是用云服务,但自己推流也是没问题的,就是做扩展可能困难些。需要准备一个流媒体服务,如果你有私人的服务器,或者可以在自己设备或者公司服务器上测试的话,可以自己搭一个流媒体服务,这里我还是只介绍 Windows 环境下的,更深入详尽,包括 linux 下的配置介绍以后有时间再说。首先,需要在服务器安装 nginx,同时安装 nginx-rtmp-module 组件,下载地址https://github.com/arut/nginx-rtmp-module/#start-of-content,这里呢,我分享一个已经配置好的 nginx 的完整版(也是前人整理的),你下载下来修改一下配置文件,就可以直接使用,链接地址: https://pan.baidu.com/s/1a7MFkkftCq8kAm44kQRJmA 提取码: ydsj,下载下来后,查看 conf 路径下的 nginx-win-rtmp.conf

上图是 rtmp 协议的相关配置,其他的如果你需要修改 nginx 的指定端口,再自行修改就可以了,我这里就不多说了另外,关于 rtmp 协议,其实还是有很多东西值得说,和 http 协议一样,rtmp 也是建立在 tcp 传输协议上的,只不过直播的时候,我们常用 rtmp 或者 rtsp,而点播的时候一般用 http,更多内容自行百度吧。好了,当我们配置好流媒体服务之后,就可以做推流了。比如,我们把屏幕录制的视频推流到流媒体服务,然后通过拉流或者类似 VLC media player 这种软件,就可以实时看到我们推流的内容了,屏幕推流的指令如下

ffmpeg -f gdigrab -i desktop -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -f flv rtmp://10.185.1.75:1935/live/home
复制代码

推流后的效果


然后,通过 VLC 软件,看到我们实时推流的画面

同样的,通过 ffmpeg 同组的 ffplay 工具一样可以查看,指令如下

ffplay rtmp://10.185.1.75:1935/live/home
复制代码

除了可以推送录制的视频,我们也可以把本地已有的视频资源进行推流,指令如下

ffmpeg.exe -re -i film.flv -vcodec copy -acodec copy -f flv -y rtmp://10.185.1.75:1935/live/home
复制代码

拉流

拉流的操作除了借助 VLC 或者 ffplay 直接播放推流画面外,我们也可以把拉流的数据保存成文件,如同保留录像资源,为后续的点播服务做准备,操作指令为

ffmpeg -i rtmp://10.185.1.75:1935/live/home -vcodec h264 -f flv -acodec aac -ac 2 save.flv
复制代码

关于推拉流的操作,在 nginx 的日志下都会记录

转流

转流操作我没有试,但看到有教程有相关介绍,我这里直接引用一下以 rtsp 转 rtmp 为例

ffmpeg -i rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov -rtsp_transport tcp -vcodec h264 -acodec aac -f flv rtmp://0.185.1.75:1935/live/home
复制代码

大概就是这些,这里面还是有一些关键的配置项没有说清楚,比如码率相关的协议,h.264,h.265,以及采用 rtmp 的协议,支持的视频格式就是 flv 和 f4v,如果需要推送视频的话,需要对视频先进行格式转换,然后在推流,而 rtsp 则是支持 mov,MP4 等格式的。总的来说,关于 ffmpeg 在上篇的基础上,扩展了不少东西,同样的,也带来了更多需要思考的问题,关于配置的细节,ffmpeg 的机制等等,ffmpeg 虽然很强大,但不是那种可以快速上手的工具,需要一定的学习成本,最好是在理解其工作原理的基础上进行操作,这样我们也会更加的熟练。


拾人牙慧

额外说两句关于转码时的相关参数(这里是引用另外一位博友的内容,怕以后找不到了,转发贴一下)

ffmpeg -i INPUT.AVI -vcodec libx264 -preset slower -crf 18 -threads 4 -acodec copy OUTPUT.MKV
复制代码

-i 待转码文件

-vcodec 选择视频编码。做过一番搜索,相比与 MPEG2, MPEG4 等,H.264 是公认最好的高清编码格式,同时压缩率也高于 MPEG4,所以我选择使用 H.264(libx264)进行视频编码。

-preset 选择编码预设,更慢=更好的视频质量,可选取值为 ultrafast,superfast, veryfast, faster, fast, medium, slow, slower, veryslow, placebo。placebo 是没用的取值。

-crf Constant Rate Factor,0~51 之间取值,0 为无损,23 为默认取值,取值越大,视频整体质量越差。一般建议在 18~28 之间取值。18 已经达到视觉无损的效果,即人眼几乎察觉不到和原片的差别。

-threads 编码使用线程数,CPU 几个核心就设置几个线程好了。

-vf 滤镜,我们只需要用到旋转滤镜 transpose=2,transpose 滤镜可取 0-3,0 为逆时针 90°且垂直翻转,1 为顺时针旋转 90°,2 为逆时针旋转 90°,3 为顺时针 90°且垂直翻转。

-acodec 音频编码,这里直接设置为 copy 保留原文件音频编码。

最后设置输出文件为 OUTPUT.MKV


在简单说一下关于码率,帧率,分辨率的区别和联系(传送门:http://www.voidcn.com/article/p-tneeoreg-wn.html

视频文件一般涉及到三个参数:帧率、分辨率和码率。

1.区别

帧率:每秒显示的图片数。影响画面流畅度,与画面流畅度成正比;帧率越大,画面越流畅;帧率越小,画面越有跳动感。由于人类眼睛的特殊生理结构,如果所看画面之帧率高于 16 的时候,就会认为是连贯的,此现象称之为视觉暂留。并且当帧速达到一定数值后,再增长的话,人眼也不容易察觉到有明显的流畅度提升了。

分辨率:(矩形)图片的长度和宽度,即图片的尺寸。

码率:把每秒显示的图片进行压缩后的数据量。影响体积,与体积成正比:码率越大,体积越大;码率越小,体积越小。 (体积=码率×时间)

2.联系

帧率×分辨率=压缩前的每秒数据量(单位应该是若干个字节)压缩比=压缩前的每秒数据量/码率 (对于同一个视频源并采用同一种视频编码算法,则:压缩比越高,画面质量越差。所谓“清晰”,是指画面十分细腻,没有马赛克。并不是分辨率越高图像就越清晰。

简单说: 在码率一定的情况下,分辨率与清晰度成反比关系:分辨率越高,图像越不清晰,分辨率越低,图像越清晰。在分辨率一定的情况下,码率与清晰度成正比关系,码率越高,图像越清晰;码率越低,图像越不清晰。

但是,事实情况却不是这么简单。

可以这么说: 在码率一定的情况下,分辨率在一定范围内取值都将是清晰的;

同样地,在分辨率一定的情况下,码率在一定范围内取值都将是清晰的。

在视频压缩的过程中, I 帧是帧内图像数据压缩,是独立帧。而 P 帧则是参考 I 帧进行帧间图像数据压缩,不是独立帧。在压缩后的视频中绝大多数都是 P 帧,故视频质量主要由 P 帧表现出来。由于 P 帧不是独立帧,而只是保存了与邻近的 I 帧的差值, 故实际上并不存在分辨率的概念,应该看成一个二进制差值序列。而该二进制序列在使用熵编码压缩技术时会使用量化参数进行有损压缩,视频的质量直接由量化参数决定,而量化参数会直接影响到压缩比和码率。

视频质量可以通过主观和客观方式来表现,主观方式就是通常人们提到的视频清晰度,而客观参数则是量化参数或者压缩比或者码率。在视频源一样,压缩算法也一样的前提下比较,量化参数,压缩比和码率之间是有直接的比例关系的。   

分辨率的变化又称为重新采样。由高分辨率变成低分辨率称为下采样,由于采样前数据充足,只需要尽量保留更多的信息量,一般可以获得相对较好的结果。而由低分辨率变成高分辨率称为上采样,由于需要插值等方法来补充(猜测)缺少的像素点,故必然会带有失真,这就是一种视频质量(清晰度)的损失。压缩前数据量(体积)=分辨率×帧率 130 万像素经过压缩以后,压缩率去处系统开销以后,一般在 30 倍以上,所以: 1300000*25(帧)/1024/30(压缩率)=1057Kbps

好了就这些了~

用户头像

学着码代码,学着码人生。 2019.04.11 加入

狂奔的小码农

评论

发布
暂无评论
FFmpeg的一些使用实践