网络限制了视频传输的带宽。因为带宽限制,这就要求咱们在传输以前经过实时视频转码将视频数据转换成带宽效率更高的格式。转码的意义在于能够在视频质量几乎不损失的前提下节省大量的网络带宽。FFmpeg主要就是作转码这件事情。html
_______ ______________
| | | |
| input | demuxer | encoded data | decoder
| file | ---------> | packets | -----+
|_______| |______________| |
v
_________
| |
| decoded |
| frames |
|_________|
________ ______________ |
| | | | |
| output | <-------- | encoded data | <----+
| file | muxer | packets | encoder
|________| |______________|
复制代码
-y => 覆盖输出java
-i => 输入源头,好比一个视频的绝对路径:/sdcard/....,输出咱们也是写绝对路径android
-f => 输出格式,若是省略就取输出录制的后缀名为输出格式,好比输入mp4格式:-y -i input -f mp4 outputgit
-c:v => 针对视频流的编码 ,等介于-vcodecgithub
-c:a => 针对音频流的编码,等介于-acodec数组
-c:v h264 => 指定视频流h264编码方式,有时候也写成libx264,FFmpeg也能够识别bash
-c:a aac => 指定音频流aac编码方式网络
copy => 不编码,如-c:v copy就是对视频流不编码,注意:若是加了没必要要的编码操做,会影响执行效率。app
-an => 禁用音频ide
-vn => 禁用视频
-x264-params keyint=10 => 为视频设置关键帧,每隔10帧生成一个关键帧
-crf => 动态码率,压缩效果佳,不是一味追求体积,画质佳,H.264的CRF数字范围在0~51,23是默认值。
-b:v => 静态码率,压缩效率比较爆炸,一味控制体积
-filter_complex => 滤镜,简单滤镜是-vf,经常使用的有变速滤镜,水印滤镜等
-map => 能够理解为流的过滤器:
-max_muxing_queue_size=>若是视频比较大,须要指定这个值比较大(好比9999),不然程序执行会中断。
-fps 帧率
-vframes 帧数
-r帧率
-preset
preset | 描述 |
---|---|
ultrafast | 编码速度最快 ,压缩效果最差 |
superfast | ··· |
veryfast | ··· |
faster | ··· |
fast | ··· |
medium | – default preset |
slow | ··· |
slower | ··· |
veryslow | 编码速度最慢 ,压缩效果从最好 |
h264编码相关,涉及CRF,Preset等,Encode/H.264
使用concat协议:把视频转成ts流,contact合并多个ts生成视频:
mp4-->ts:
remux an MP4 file containing an H.264 stream to mpegts format with ffmpeg,
you can use the command:
ffmpeg -i INPUT.mp4 -codec copy -bsf:v h264_mp4toannexb OUTPUT.ts
多个ts合并:
ffmpeg -i "concat:input1.ts|input2.ts|input3.ts" -c copy output
复制代码
ffmpeg -i input.mkv -filter:v "setpts=0.5*PTS" output.mkv
音频速度变成原来的两倍: ffmpeg -i input.mkv -filter:a "atempo=2.0" -vn output.mkv
若是是音频和视频一致加速两杯: 这里会涉及到滤镜的概念和-map指令的使用,输入有多个流,咱们就可能用到-map指定: 假设有音频流和视频流:speed是目标速率,好比2.
-y -i input -filter_complex [0:v]setpts=" + 1d/speed + "*PTS[v];[0:a]atempo=" + speed + "[a] output
复制代码
若是只有视频流:
-y -i input -vf [0:v]setpts=" + 1d/speed + "*PTS" output 复制代码
-y -i input.mp4 -s 1 -t 3 ouput.mp4
ffmpeg -i input.flv -ss 00:00:14.435 -vframes 1 out.png
每秒生成一张图片,命名为thumb1.png,thumb2.png,thumb3.png.....(输出是绝对路径) ffmpeg -i input -vf fps=1 thumb%d.png
每秒生成两张图片,命名为thumb001.png,thumb002.png,thumb003.png,-s指令来指定分辨率100100..... ffmpeg -i input -s 100X100 -vf fps=2 thumb%3d.png
ffmpeg -framerate 10 -i img%03d.png output.mp4
注意:若是生成是h264的视频,加上 -vf format=yuv420p 或者 -pix_fmt yuv420p能够防止某些播放器没法解码视频。 生成幻灯片相关duration 5
file '/path/to/cat.png'
duration 1
file '/path/to/rat.png'
duration 3
file '/path/to/tapeworm.png'
duration 2
file '/path/to/tapeworm.png'
复制代码
ffmpeg -f concat -i input.txt -vsync vfr -pix_fmt yuv420p output.mp4
ffmpeg -i input -s width*height -c:v h264 output
在起点(x,y)的地方裁剪下长高为wh的区域对应的视频(坐标系:以视频左上角为原点,向右为正方向,向下为正方向) ffmpeg -i -vf crop=w:h:x:y output
crop指令
ffmpeg -i input -i picture -filter_complex overlay=0:0 output
ffmpeg -i input -ignore_loop 0 -i gif -filter_complex overlay=shortest=1
若是须要加坐标: ffmpeg -i input -ignore_loop 0 -i gif -filter_complex overlay=x:y:shortest=1
从视频前两秒片断中抽出一张帧率是10的GIF ffmpeg -i INPUT -ss 0 -t 2 -r 10 out.gif
上门的指令生成的GIF是比较模糊的,若是要生成高清的GIF: 先生成调色板,再利用调色板生成GIF,假设fps=10, ffmpeg -i INPUT -r 10 -vf fps=10,scale=300:-1:flags=lanczos,palettegen colorPalette.png
scale是缩放的意思,这里是设置宽为300,-1是保持宽高比. ffmpeg -i input -i colorPalette.png -r 10 -lavfi fps=10,scale=300:-1:flags=lanczos[x];[x][1:v]paletteuse
获得清晰GIF相关
生成一个Shell命令数组,丢给FFmpeg可执行文件处理便可 tips:文档上的命令都是用空格隔开,其实把他理解成数组就好,重点是数组内的元素不要错便可;
String ffmpegSplitWord = "若是是空格容易出错,尽可能是一个不容易和其余命令出突的字符(尽可能和文件名不冲突)";
StringBuilder sb = new StringBuilder("-y");
sb.append(ffmpegSplitWord + "-i");
sb.append(ffmpegSplitWord + input.toString());
sb.append(ffmpegSplitWord + "-c:v");
sb.append(ffmpegSplitWord + "libx264");
sb.append(ffmpegSplitWord + "-x264-params");
sb.append(ffmpegSplitWord + "keyint=" + Constant.Camerasettings.keyint);
setBitRate(ffmpegSplitWord, sb);
setPreset(ffmpegSplitWord, sb);
sb.append(ffmpegSplitWord + output.toString());
String ffmpeg_s = sb.toString();
String[] command=ffmpeg_s.split(ffmpegSplitWord);
try {
FFmpeg.getInstance(IApplication.getInstance()).execute(command, new ExecuteBinaryResponseHandler() {
@Override
public void onFailure(String s) {
}
@Override
public void onSuccess(String s) {
}
@Override
public void onProgress(String s) {
}
@Override
public void onStart() {
}
@Override
public void onFinish() {
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
}
复制代码
frame= 1 fps=0.0 q=0.0 size= 0kB time=00:01:02.71 bitrate= 0.0kbits/s speed=2.88x
咱们能够拿到time信息,这是处理到哪一个时间点的信息,把他专程秒,处理视频时长,就能够获得处理进度。