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

关于转码:

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

FFmpeg转码流程示意图:

 _______              ______________
|       |            |              |
| input |  demuxer   | encoded data |   decoder
| file  | ---------> | packets      | -----+
|_______|            |______________|      |
                                           v
                                         _________
                                        |         |
                                        | decoded |
                                        | frames  |
                                        |_________|
 ________             ______________       |
|        |           |              |      |
| output | <-------- | encoded data | <----+
| file   |   muxer   | packets      |   encoder
|________|           |______________| 
复制代码

基本命令解释:

  • -y => 覆盖输出

  • -i => 输入源头,比如一个视频的绝对路径:/sdcard/....,输出我们也是写绝对路径

  • -f => 输出格式,如果省略就取输出录制的后缀名为输出格式,比如输入mp4格式:-y -i input -f mp4 output

  • -c:v => 针对视频流的编码 ,等介于-vcodec

  • -c:a => 针对音频流的编码,等介于-acodec

  • -c:v h264 => 指定视频流h264编码方式,有时候也写成libx264,FFmpeg也可以识别

  • -c:a aac => 指定音频流aac编码方式

  • copy => 不编码,如-c:v copy就是对视频流不编码,注意:如果加了不必要的编码操作,会影响执行效率。

  • -an => 禁用音频

  • -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信息,这是处理到哪个时间点的信息,把他专程秒,处理视频时长,就可以得到处理进度。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Android 上配置并使用 FFmpeg 命令行环境,可以按照以下步骤操作: 1. 下载 FFmpegAndroid 编译工具链,例如 Android NDK:https://developer.android.com/ndk/downloads 2. 解压下载好的工具链,将其添加到环境变量。 3. 下载 FFmpeg 源代码,例如从官方网站下载:https://www.ffmpeg.org/download.html 4. 解压 FFmpeg 源代码,并进入到 FFmpeg 的目录。 5. 配置 FFmpeg 编译选项,例如: ``` ./configure \ --prefix=$PREFIX \ --enable-shared \ --disable-static \ --disable-doc \ --disable-ffmpeg \ --disable-ffplay \ --disable-ffprobe \ --disable-ffserver \ --disable-avdevice \ --disable-swresample \ --disable-swscale \ --disable-avfilter \ --disable-postproc \ --enable-gpl \ --enable-version3 \ --enable-pic \ --enable-jni \ --enable-mediacodec \ --enable-decoder=h264 \ --enable-decoder=hevc \ --enable-decoder=mpeg4 \ --enable-decoder=vp8 \ --enable-decoder=vp9 \ --enable-decoder=aac \ --enable-decoder=opus \ --enable-encoder=libx264 \ --enable-encoder=libx265 \ --enable-encoder=mpeg4 \ --enable-encoder=aac \ --enable-encoder=opus \ --extra-cflags="-I$ANDROID_PREFIX/include -O3 -Wall -fPIC -DANDROID -DNDEBUG" \ --extra-ldflags="-L$ANDROID_PREFIX/lib -Wl,-rpath-link=$ANDROID_PREFIX/lib -Wl,--no-warn-mismatch -Wl,-z,noexecstack -ldl -lc -lm -llog" ``` 其,`$PREFIX` 是 FFmpeg 安装路径,`$ANDROID_PREFIX` 是 Android NDK 的路径。 6. 执行 `make` 命令编译 FFmpeg。 7. 执行 `make install` 命令安装 FFmpeg 到指定的路径。 8. 在 Android 项目使用 FFmpeg 命令行,例如: ```java Process ffmpegProcess = Runtime.getRuntime().exec("/path/to/ffmpeg -i /path/to/input.mp4 -c:v libx264 -c:a aac /path/to/output.mp4"); ``` 其,`/path/to/ffmpeg` 是 FFmpeg 可执行文件的路径,`/path/to/input.mp4` 和 `/path/to/output.mp4` 是输入和输出文件的路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值