Skip to content
Administrator edited this page Jun 26, 2020 · 3 revisions

引入

根据最新版本替换下面的${latestVersion},当前最新版本 Download

implementation 'com.coder.command:ffmpeg:${latestVersion}'

如果对apk大小有严格的要求,可以使用mini版本

implementation 'com.coder.command:ffmpeg-mini:${latestVersion}'

配置

一般我们使用CPU_ABI时只需要armeabi-v7aarm64-v8a就行了,所以只需要在app的bulid.gradle下加入如下代码:

android {
    ...
    defaultConfig {
        ...
        ndk {
            abiFilters 'armeabi-v7a', 'arm64-v8a'
            moduleName "app"
        }
    }
}

Debug模式

可以在Application或者使用之前设置Debug模式

 FFmpegCommand.setDebug(true);

使用之后将会打印类似如下信息,正式上线建议关闭

2020-04-14 11:24:34.316 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd: Input #0, mp3, from '/storage/emulated/0/Android/data/com.coder.ffmpegtest/cache/test.mp3':
2020-04-14 11:24:34.316 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd:   Metadata:
2020-04-14 11:24:34.316 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd:     track           : 
2020-04-14 11:24:34.316 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd: 4
2020-04-14 11:24:34.316 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd:     album           : 
2020-04-14 11:24:34.316 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd: 老妖的奇异之旅
2020-04-14 11:24:34.316 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd:     artist          : 
2020-04-14 11:24:34.316 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd: 音频怪物
2020-04-14 11:24:34.316 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd:     title           : 
2020-04-14 11:24:34.316 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd: 琴师
2020-04-14 11:24:34.316 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd:     comment         : 
2020-04-14 11:24:34.317 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd: 163 key(Don't modify):L64FU3W4YxX3ZFTmbZ+8/XaHu4ttkjqeshXxH3KzUJIjW7TiQPO7yhdBvVocH3+T10bijFQrb4/8IlKOGmuqVuqY66JjiWF+FKWZIAtFkegR9A1hA0/PQDlrk3QgW2ecLZDxWBvu4ei9113YaekyVuHRKrPI+2wF4Bvt6VS8oTFrOPTNN2kZa8OZq0PUedCDDqfXUU1SGPu6yJt7rwpEOSCMI2WbS1OrwXRuyJQ43
2020-04-14 11:24:34.317 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd:     encoder         : 
2020-04-14 11:24:34.317 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd: Lavf58.20.100
2020-04-14 11:24:34.317 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd:   Duration: 
2020-04-14 11:24:34.317 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd: 00:00:39.99
2020-04-14 11:24:34.317 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd: , start: 
2020-04-14 11:24:34.317 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd: 0.011995
2020-04-14 11:24:34.317 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd: , bitrate: 
2020-04-14 11:24:34.317 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd: 320 kb/s
2020-04-14 11:24:34.317 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd:     Stream #0:0
2020-04-14 11:24:34.317 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd: , 50, 1/14112000
2020-04-14 11:24:34.317 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd: : Audio: mp3, 44100 Hz, stereo, fltp, 320 kb/s
2020-04-14 11:24:34.317 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd:     Metadata:
2020-04-14 11:24:34.317 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd:       encoder         : 
2020-04-14 11:24:34.317 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd: Lavc57.89
2020-04-14 11:24:34.317 15221-15304/com.coder.ffmpegtest D/ffmpeg-cmd: Successfully opened the file.

调用

FFmpegCommand方法

方法 功能 加入版本
FFmpegCommand->setDebug(boolean debug) Dubug模式,可打印日志,默认true 1.1.1
FFmpegCommand->runSync(final String[] cmd) 同步执行ffmpeg命令,外部需添加延时线程 1.1.1
FFmpegCommand->runSync(final String[] cmd, OnFFmpegCommandListener listener) 同步执行ffmpeg命令,并回调 完成,取消,进度 1.1.3
FFmpegCommand->runAsync(final String[] cmd, IFFmpegCallBack callBack) 异步执行,外部无需添加延时线程,并回调 开始,完成,取消,进度 1.1.3
FFmpegCommand->getInfoSync(String path,@Attribute int type) 获取媒体信息,type值必须为@Attribute中注解参数 1.1.1
FFmpegCommand->cancel() 退出当前ffmpeg执行 1.1.3
FFmpegCommand->runMoreSync(List<String[]> cmds, OnFFmpegCommandListener listener) 同步多命令执行,并回调 完成,取消,进度 1.1.5
FFmpegCommand->runMoreAsync(List<String[]> cmds, IFFmpegCallBack callBack) 同步多命令执行,并回调开始,完成,取消,进度 1.1.5

使用runSync

FFmpegCommand.runSync(final String[] cmd)方法不能直接使用,需要在子线程中运行,其中参数由FFmpegUtils工具类提供,也可以自己添加

String cmd = "ffmpeg -y -i %s -an -c:v rawvideo -pixel_format yuv420p %s";
final String result = String.format(Locale.CHINA, cmd, videoPath,output);
new Thread(
        new Runnable() {
            @Override
            public void run() {
                FFmpegCmd.runCmd(result.split(" "));
            }
        }
).start();

还可以使用获取进度的方法FFmpegCommand.runSync(final String[] cmd, FFmpegCommand.OnFFmpegCommandListener listener)

new Thread(new Runnable() {
            @Override
            public void run() {
                FFmpegCommand.runSync(FFmpegUtils.videoHLS(mVideoPath, targetPath, 10),new FFmpegCommand.OnFFmpegCommandListener() {
                    @Override
                    public void onProgress(int progress) {
                        Log.d("CmdProgress", progress + "");
                    }
                });
            }
        }).start();

使用runAsync

runAsync调用FFmpeg为异步方式,不需要单独开启子线程。强烈建议使用此方法进行音视频处理!!!
直接调用FFmpegCommand.runAsync(String[] cmd, IFFmpegCallBack callback)方法,其中第一个参数由FFmpegUtils工具类提供,也可以自己添加

final long startTime = System.currentTimeMillis();

FFmpegCommand.runAsync(FFmpegUtils.cutAudio(input, "00:00:30", "00:00:40", output),
    new CommonCallBack() {
         @Override
         public void onComplete() {
         Log.d("FFmpegTest", "run: 耗时:" + (System.currentTimeMillis() - startTime));

         @Override
         public void onCancel() {
             Log.d("FFmpegTest", "Cancel");
         }

         @Override
         public void onProgress(int progress) {
             Log.d("FFmpegTest",progress+"");
         }
    }
});

自定义FFmpeg命令

这里只是演示了音频剪切,很多如上述功能请自行查阅FFmpegUtils 如果其中不满足需求,可添加自己的FFmpeg命令.例如:

String cmd = "ffmpeg -y -i %s -vn -acodec copy -ss %s -t %s %s";
String result = String.format(cmd, input, "00:00:30", "00:00:40", output);

FFmpegCommand.runAsync(result.split(" "), new CommonCallBack() {
     @Override
     public void onComplete() {
         Log.d("FFmpegTest", "run: 耗时:" + (System.currentTimeMillis() - startTime));
     }

     @Override
     public void onCancel() {
         Log.d("FFmpegTest", "Cancel");
     }

     @Override
     public void onProgress(int progress) {
         Log.d("FFmpegTest",progress+"");
     }
})

多命令执行

1.1.5版本新增了多命令执行方式,可以多条命令一同执行,可返回总进度,提供了两种方式去实现

  • runMoreSync 多条命令同步执行
  • runMoreAsync 多条命令异步执行
FFmpegCommand.runMoreAsync(st, object : CommonCallBack() {
    override fun onStart() {
        mErrorDialog?.show(supportFragmentManager, "Dialog")
    }

    override fun onComplete() {
        mErrorDialog?.setContent(0)
        mErrorDialog?.dismissAllowingStateLoss()
        ToastUtils.show("多命令执行完成")
        val target = targetAAC + "\n" + targetAVI + "\n" + targetYUV
        tvContent!!.text = target
    }

    override fun onCancel() {
        ToastUtils.show("用户取消")
    }

    override fun onProgress(progress: Int) {
        mErrorDialog?.setContent(progress)
    }
})

需要注意的是:

1.1.5版本之后可以使用多条同步命令进行执行,但不可同时使用多条异步命令

Thread(Runnable {
	FFmpegCommand.runSync(FFmpegUtils.transformAudio(audioPath, targetPath), object : FFmpegCommand.OnFFmpegCommandListener{})
	FFmpegCommand.runSync(FFmpegUtils.decode2YUV(mVideoPath, targetPath), object : FFmpegCommand.OnFFmpegCommandListener{})
  FFmpegCommand.runSync(FFmpegUtils.transformVideo(videoPath, targetPath), object : FFmpegCommand.OnFFmpegCommandListener())
}).start()

取消执行

执行下面方法后将会回调 CommonCallBack->onCancel()OnFFmpegCommandListener->onCancel() 方法

FFmpegCommand.cancel();

使用getInfoSync

FFmpegCommand.getInfoSync(String path,@Attribute int type)提供了获取媒体文件大小,视频宽高,比特率,音频采样率等属性值方法

val AV_TIME_BASE = 1000000;
val duration = FFmpegCommand.getInfoSync(mVideoPath, Attribute.DURATION)
var secs = duration / AV_TIME_BASE
al us = duration % AV_TIME_BASE
var mins = secs / 60
secs %= 60
val hours = mins / 60
mins %= 60

val result = String.format("%02d:%02d:%02d.%02d", hours, mins, secs, (100 * us) / AV_TIME_BASE)
tvContent?.text = result

参考