FFmpeg command line tool(Android中使用FFmpeg命令行)

关于转码:

网络限制了视频传输的带宽。因为带宽限制,这就要求咱们在传输以前经过实时视频转码将视频数据转换成带宽效率更高的格式。转码的意义在于能够在视频质量几乎不损失的前提下节省大量的网络带宽。FFmpeg主要就是作转码这件事情。html

FFmpeg转码流程示意图:

_______              ______________
|       |            |              |
| 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 => 能够理解为流的过滤器:

    • -map[0:v] 就是选择第一输入源的视频流,流向输出。
    • -map[1:a] 就是选择第二输入源的音频流,流向输出。
  • -max_muxing_queue_size=>若是视频比较大,须要指定这个值比较大(好比9999),不然程序执行会中断。

  • -fps 帧率

  • -vframes 帧数

  • -r帧率

  • -preset

    • preset和crd参数同样,会影响压缩效果,preset能够很大程度影响程序的执行速度,每条命令均可以加,通常加载命令尾部,output以前:
    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
    复制代码

    Concat protocol

视频音频流变速

  • How to speed up / slow down a video 视频速度变成原来的两倍:
    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 复制代码

裁剪时长

  • -ss 裁剪开始时间,单位秒
  • -t 须要裁剪多长时间,单位秒 从第一秒,裁剪3秒视频生成新视频 -y -i input.mp4 -s 1 -t 3 ouput.mp4

生成缩率图

  • 这里涉及两个指令-vframes ,-fps;
    • -vframes是帧数
    • -fps是帧率,(frames per second),时间(秒)fps=vframs -生成某个时刻的缩率图: 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

图片生成幻灯片(多图合成视频)

  • 如何输出的图片是规则的,img001png,img002.pmg,img003.pn... 我生成每秒10帧的幻灯片,默认是25帧每秒: ffmpeg -framerate 10 -i img%03d.png output.mp4 注意:若是生成是h264的视频,加上 -vf format=yuv420p 或者 -pix_fmt yuv420p能够防止某些播放器没法解码视频。 生成幻灯片相关
  • 若是文件名是不规则,也可使用concat协议:
    • 先生成一个text文件,写上对应的file和duration(时长):
      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指令

水印

  • 叠加一张静态图,overlay是picture左上角对应的坐标,(坐标系:以视频左上角为原点,向右为正方向,向下为正方向): ffmpeg -i input -i picture -filter_complex overlay=0:0 output
  • 叠加GIF,若是想要GIF无限循环,使用这条指令(不然能够用上面的指令): 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

GIF

从视频前两秒片断中抽出一张帧率是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相关

Android 使用:

  • 生成一个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) {
          }
    复制代码

如何获取处理进度:

  • FFmpeg在处理的过程会打印出一些信息,好比 frame= 1 fps=0.0 q=0.0 size= 0kB time=00:01:02.71 bitrate= 0.0kbits/s speed=2.88x 咱们能够拿到time信息,这是处理到哪一个时间点的信息,把他专程秒,处理视频时长,就能够获得处理进度。
相关文章
相关标签/搜索