最近发现抖音特效里有视频倒播,看起来比较酷。于是自己用FFmpeg在Android平台做了一遍,现在方案是先用FFmpeg把视频反序,再进行视频倒放。最终效果长这样:
主要用到的是FFmpeg的filter_complex来实现,拼接命令行:
/**
* 视频反序倒播
* @param inputFile 输入文件
* @param targetFile 反序文件
*
* @return 视频反序的命令行
*/
public static String[] reverseVideo(String inputFile, String targetFile){
String reverseVideo = "ffmpeg -i %s -filter_complex [0:v]reverse[v] -map [v] %s";
reverseVideo = String.format(reverseVideo, inputFile, targetFile);
return reverseVideo.split(" ");
}
执行FFmpeg命令行:
/**
* 执行ffmpeg命令行
* @param commandLine commandLine
*/
private void executeFFmpegCmd(final String[] commandLine){
if(commandLine == null){
return;
}
FFmpegCmd.execute(commandLine, new FFmpegCmd.OnHandleListener() {
@Override
public void onBegin() {
Log.i(TAG, "handle video onBegin...");
}
@Override
public void onEnd(int result) {
Log.i(TAG, "handle video onEnd...");
mHandler.sendEmptyMessage(MSG_PLAY);
}
});
}
开启子线程在JNI层执行FFmpeg命令行:
//开子线程调用native方法进行音视频处理
public static void execute(final String[] commands, final OnHandleListener onHandleListener){
new Thread(new Runnable() {
@Override
public void run() {
if(onHandleListener != null){
onHandleListener.onBegin();
}
//调用ffmpeg进行处理
int result = handle(commands);
if(onHandleListener != null){
onHandleListener.onEnd(result);
}
}
}).start();
}
private native static int handle(String[] commands);
最终是在JNI层调用ffmpeg.c源码执行FFmpeg命令行:
JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_FFmpegCmd_handle
(JNIEnv *env, jclass obj, jobjectArray commands){
int argc = (*env)->GetArrayLength(env, commands);
char **argv = (char**)malloc(argc * sizeof(char*));
int i;
int result;
for (i = 0; i < argc; i++) {
jstring jstr = (jstring) (*env)->GetObjectArrayElement(env, commands, i);
char* temp = (char*) (*env)->GetStringUTFChars(env, jstr, 0);
argv[i] = malloc(1024);
strcpy(argv[i], temp);
(*env)->ReleaseStringUTFChars(env, jstr, temp);
}
//执行ffmpeg命令
result = run(argc, argv);
//释放内存
for (i = 0; i < argc; i++) {
free(argv[i]);
}
free(argv);
return result;
}
等待视频反序处理完毕,使用VideoView开始播放。不够完美的是需要等待,如果能做到在线倒播那就好了。视频的在线倒播就是从最后一帧反序播放,需要解决的问题是I帧、P帧解码时间,甚至还有B帧。后续有待研究......