ffmpeg使用
一、ffmpeg介绍
FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源程序。且提供录制、转换以及流化音视频的完整解决方案。
二、centos7安装ffmpeg
1.yum安装
ffmpeg可源码安装可编译安装
因为编译安装较为麻烦这里直接下载第三方源来yum安装
sudo rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
sudo rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm
yum install ffmpeg ffmpeg-devel -y
完成后测试是否可用
2.源码安装
从官网下载tgz包ffmpeg-4.1.tar.bz2 http://ffmpeg.org/download.html#releases
上传Linux系统准备安装
需注意在编译ffmpeg的时候需要用到yasm
yasm是一款汇编器,重写了nasm的汇编环境,接收nasm和gas语法,支持x86和amd64指令集
从官网下载tgz包yasm-1.3.0.tar.gz
http://yasm.tortall.net/releases/Release1.3.0.html
下载后上传到服务器
tar -xvf yasm-1.3.0.tar.gz
cd yasm-1.3.0/
./configure
make
make install
等yasm编译完成后
tar xvf ffmpeg-4.1.tar.bz2
cd ffmpeg-4.1/
--prefix=/monchickey/ffmpeg(是指定安装的目录)
./configure --enable-shared --prefix=/monchickey/ffmpeg
make
make install
编译完成后 进入到安装目录/monchickey/ffmpeg
安装目录下有bin,include,lib,share,4个目录
bin是ffmpeg主程序二进制目录 include是C/C++头文件目录
lib是编译好的库文件目录 share是文档目录
进入bin目录有命令ffmpeg和ffprobe
./ffmpeg -version
查看当前版本的详细信息,默认情况下一般会报libavdevice.so.57: cannot open shared object file: No such file or directory
原因是lib目录未加载到链接到系统库中,创建下文件 vim /etc/ld.so.conf.d/ffmpeg.conf
添加一行: /monchickey/ffmpeg/lib
保存退出
执行 ldconfig
使配置生效,再次执行./ffmpeg -version
显示正常
为命令设置成环境变量
vim /etc/profile中添加
export PATH=/monchickey/ffmpeg/bin:$PATH
source /etc/profile 生效
到此环境搭建完成
三、Ffmpeg命令使用
1.ffprobe命令 ——查看媒体文件格式
查看命令:
ffprobe test.mp4
Duration: 00:00:13.03, start: 0.000000, bitrate: 9875 kb/s
Stream #0:0(eng): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 9557 kb/s, 25 fps, 25 tbr, 25k tbn, 50 tbc (default)
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 317 kb/s (default)
第一部分的信息是Metadata信息 Duration 第一行内容代表时长 start是开始播放时间 bitrate是比特率 Stream
video是视频流编码方式是H264的格式封装格式是AVC1,每一帧的数据表示是YUV420P的格式,分辨率是1920x1080,视频流的比特率是9557Kbit/s,
帧率是每秒钟25帧(fps是25)
第二个stream是音频流,编码方式是AAC封装格式是MP4A,采用的Profile是LC规格,采样率是48000Hz,声道数是立体声stereo,数据表示格式是浮点型fltp,这路音频流的比特率是317Kbit/s
查看命令:ffprobe -show_format test.mp4
上述命令可以输出格式信息format_name、时间长度duration、文件大小size、比特率bit_rate、流的数目nb_streams等。
查看命令:ffprobe -print_format json -show_streams
上述命令可以以JSON格式的形式输出信息,视频的宽高信息、是否有b帧、视频帧的总数目、视频的编码格式、显示比例、比特率等信息,音频中会有音频的编码格式、表示格式、声道数、时间长度、比特率、帧的总数目等信息
查看命令:ffprobe -show_frames test.mp4
显示帧信息
查看命令:ffprobe -show_packets test.mp4
查看包信息
2.Ffmpeg命令 --常用命令
ffmpeg --help 查看可用选项
ffmpeg -formats 查看支持的格式
ffmpeg -i input.mp4 -ss 00:00:10.0 -codec copy -t 2 output.mp4 剪切视音频
从10秒开始剪切2秒的时间-ss指定偏移时间,-t指定的时长
ffmpeg -i input.mp4 -t 00:00:50 -c copy small-1.mp4 -ss 00:00:50 -codec copy small-2.mp4
将该视频文件切割为多个文件
使用例子
- 视频文件简单转换成另一个格式的视频文件, 会默认使用H264编码格式输出视频文件.
ffmpeg -i input.avi output.mkv
- 把一个视频文件my.avi和一个声音文件my.mp3合并成一个音视频文件my.mkv
ffmpeg –i my.avi –i my.mp3 –vcodec copy –acodec copy my.mkv
- 把音视频文件my.mkv里的声音数据去掉生成只有图像的my.avi文件, 并使用h264编码
ffmpeg -i my.mkv -vcodec h264 -an my.avi
- 把音视频文件my.mkv里的图像数据去掉生成只有声音的my.aac文件, 并使用aac编码
ffmpeg -i my.mkv -acodec aac -vn my.aac
- 把多个图像文件使用h264编码封装成avi文件,如有my0.jpg, my1.jpg … my99.jpg
ffmpeg -i my%d.jpg -vcodec h264 my.avi
- 指定音视频文件把1分30秒到5分20秒的内容输出到另一个文件
ffmpeg -ss 00:01:30 -i my.avi -to 00:05:20 -vcodec copy -acodec copy my.mkv
- 把视频文件里内容输出成多张图像
ffmpeg -i my2.avi -r 1 -f image2 my%d.jpg
只输出一张图像
ffmpeg -i my2.avi -r 1 -f image2 -t 0.0001 my%d.jpg
- 从音视频文件里生成yuyv422格式的数据
ffmpeg -i 99bear.mp4 -r 1 -f rawvideo -pix_fmt yuyv422 my.yuyv
//yuv数据可用ffplay来播放
ffplay -f rawvideo -video_size 640x480 -pixel_format yuyv422 my.yuyv
- 改变原视频文件的分辨率大小为640x480, 使用h264编码, 声音使用aac编码, 并指定视频输出的码率为100k.
ffmpeg -i 78.flv -vcodec h264 -acodec aac -s 640x480 -b:v 100k 78.avi
- 指定把视频文件里在第500秒开始30帧图像数据保存为gif, 指定一秒2张图像的速率
ffmpeg -ss 500 -r 2 -i 99bear.mp4 -vframes 30 my.gif
- 合并多个同格式的视频文件. 如把"1.flv 2.flv 3.flv"三个文件合并为my.avi
先创建一个文本文件files.txt, 里面记录要合并的文件名:
files.txt:
file '1.flv'
file '2.flv'
file '3.flv'
然后:
ffmpeg -f concat -i files.txt -vcodec copy -acodec copy my.avi
- 视频文件增加logo.
ffmpeg -i God.rm -i logo.png -filter_complex overlay my.avi
指定logo的位置, overlay=logo在视频里开始显示的x坐标:y坐标. 可以用变量W/w, H/h来表示, W表示视频图像的宽度 H表示视频图像的高度, w表示logo的宽度, h表示logo的高度
如右下角: ffmpeg -i God.rm -i logo.png -filter_complex overlay=W-w:H-h my.avi
如居中: ffmpeg -i God.rm -i logo.png -filter_complex overlay=W/2-w/2:H/2-h/2 my.avi
- 操作摄像头.
查看摄像头所支持的数据格式及分辨率:
ffmpeg -f v4l2 -list_formats all -i /dev/video0
录制10秒摄像头里的内容, 并指定帧率为10和使用h264编码:
ffmpeg -t 10 -f v4l2 -r 10 -i /dev/video0 -vcodec h264 ./a.avi
录制摄像头的内容为gif,并指定分辨率及帧率:
ffmpeg -f v4l2 -video_size 320x240 -r 2 -i /dev/video0 o.gif
- 操作声卡, 录音10秒并使用aac编码:
ffmpeg -t 10 -f alsa -i default -acodec aac my.aac
录音10秒保存为wav文件:
ffmpeg -t 10 -f alsa -i default my.wav
- 录屏,指定录制的分辨率及帧率, 并使用h264编码:
ffmpeg -f x11grab -video_size 1024x768 -r 10 -i :0 -vcodec h264 ./a.avi
录屏,并指定从屏幕的坐标10:20开始区域录制:
ffmpeg -f x11grab -video_size 800x600 -r 5 -i :0.0+10,20 -vcodec h264 ./b.avi
录屏并录制声音:
ffmpeg -f x11grab -r 5 -i :0 -f alsa -i default -vcodec h264 -acodec aac my.avi
四、拓展
视频压缩中,每帧代表一幅静止的图像。而在实际压缩时,会采取各种算法减少数据的容量,其中IPB就是最常见的。
(1)I帧表示关键帧,你可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成(因为包含完整画面)
(2)P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。(也就是差别帧,P帧没有完整画面数据,只有与前一帧的画面差别的数据)
(3)B帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别(具体比较复杂,有4种情况),换言之,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是解码时CPU会比较累。
从上面的解释看,我们知道I和P的解码算法比较简单,资源占用也比较少,I只要自己完成就行了,P呢,也只需要解码器把前一个画面缓存一下,遇到P时就使用之前缓存的画面就好了,如果视频流只有I和P,解码器可以不管后面的数据,边读边解码,线性前进,大家很舒服。但网络上的电影很多都采用了B帧,因为B帧记录的是前后帧的差别,比P帧能节约更多的空间,但这样一来,文件小了,解码器就麻烦了,因为在解码时,不仅要 用之前缓存的画面,还要知道下一个I或者P的画面(也就是说要预读预解码),而且,B帧不能简单地丢掉,因为B帧其实也包含了画面信息,如果简单丢掉,并 用之前的画面简单重复,就会造成画面卡(其实就是丢帧了),并且由于网络上的电影为了节约空间,往往使用相当多的B帧,B帧用的多,对不支持B帧的播放器 就造成更大的困扰,画面也就越卡。 一般平均来说,I的压缩率是7(跟JPG差不多),P是20,B可以达到50,可见使用B帧能节省大量空间,节省出来的空间可以用来保存多一些I帧,这样在相同码率下,可以提供更好的画质。
编解码过程
1. 注册所有容器格式和CODEC:av_register_all()
2. 打开文件:av_open_input_file()
3. 从文件中提取流信息:av_find_stream_info()
4. 穷举所有的流,查找其中种类CODEC_TYPE_VIDEO
5. 查找对应的解码器:avcodec_find_decoder()
6. 打开编解码器:avcodec_open()
7. 为解码帧分配内存:avcodec_alloc_frame()
8. 不停地从码流中提取出帧数据:av_read_frame()
9. 判断帧的类型,对于视频用:avcodec_decode_video()
10. 解码完后,释放解码器:avcodec_close()
11. 关闭输入文件:av_close_input_file()
组成
1、libavformat:用于各种音视频封装格式的生成和解析,包括获取解码所需信息以生成解码上下文结构和读取音视频帧等功能,包含demuxers和muxer库;
2、libavcodec:用于各种类型声音/图像编解码;
3、libavutil:包含一些公共的工具函数;
4、libswscale:用于视频场景比例缩放、色彩映射转换; 5、libpostproc:用于后期效果处理;
6、ffmpeg:是一个命令行工具,用来对视频文件转换格式,也支持对电视卡实时编码;
7、ffsever:是一个HTTP多媒体实时广播流服务器,支持时光平移; 8、ffplay:是一个简单的播放器,使用ffmpeg库解析和解码,通过SDL显示;