Android最简单的基于FFmpeg的例子(四)---以命令行的形式来使用ffmpeg

FFmpeg

FFmpeg使用第四步,以命令行的形式来使用ffmpeg.

编译环境

  • Mac OS X Capitan 10.11.3
  • NDK-r10e (64-bit)
  • FFmpeg 3.0

简介

在前面编译FFmpeg类库编译ffmpeg时,编译脚本中使用了参数 –disable-ffmpeg,所以是不会生成ffmpeg工具的,即使生成了,
在android应用下也无法直接使用。

但是,FFmpeg 命令行是十分强大易用的,我们可以用命令行完成大部分的需求,So,Let’s Do it.

Let’s Do it !

编译FFmpeg成一个SO库一文中,已经将 libffmpeg.so 编译好了,这里直接复用这个文件.

Step 1: 新建工程

新建一个Android工程,在 src/main/ 目录下新建 jni 目录,如图:

create_newproject_ffmpeg_command_line

编写 FFmpegKit.java 代码:

      
      
1
2
3
4
5
6
7
8
9
10
11
      
      
package com.ihubin.ffmpegstudy;
public class FFmpegKit {
static{
System.loadLibrary( "ffmpeg");
System.loadLibrary( "ffmpeginvoke");
}
public native static int run(String[] commands);
}

获取C语言的接口函数声明

在命令行中切换到src/main/java文件夹下,输入如下命令:

      
      
1
      
      
javah com.ihubin.ffmpegstudy.FFmpegKit

在 src/main/java 目录生成了 com_ihubin_ffmpegstudy_FFmpegKit.h 文件,将这个文件移动到 jni 目录.

Step 2: 拷贝文件

编译FFmpeg成一个SO库生成的 libffmpeg.so 文件拷贝至 jni 目录.

复制FFmpeg源码文件 ffmpeg.h, ffmpeg.c, ffmpeg_opt.c, ffmpeg_filter.c,cmdutils.c, cmdutils.h, cmdutils_common_opts.h 到jni目录下.

在 jni 目录新建文件 Android.mk Application.mk com_ihubin_ffmpegstudy_FFmpegKit.c

此时,工程目录是这样的,如图:

create_newproject_ffmpeg_command_line_finish

Step 3: 代码实现

修改ffmpeg.c和ffmpeg.h

找到ffmpeg.c,把int main(int argc, char argv) 改名为 int run(int argc, char argv)

找到ffmpeg.h, 在文件末尾添加函数申明: int run(int argc, char **argv);

cmodify_ffmpegh_file_over

修改cmdutils.c 和 cmdutils.h

找到cmdutils.c中的exit_program函数,删掉函数中原来的内容, 添加 return ret;并修改函数的返回类型为int

修改前:

before_modify_cmdutils

修改后:

after_modify_cmdutils

找到cmdutils.h中exit_program的申明,也把返回类型修改为int。

修改前:

before_modify_cmdutils_header

修改后:

after_modify_cmdutils_header

在 com_ihubin_ffmpegstudy_FFmpegKit.c 中实现 com_ihubin_ffmpegstudy_FFmpegKit.h 中的方法

com_ihubin_ffmpegstudy_FFmpegKit.c

      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
      
      
#include <stdio.h>
#include "com_ihubin_ffmpegstudy_FFmpegKit.h"
#include "ffmpeg.h"
JNIEXPORT jint JNICALL Java_com_ihubin_ffmpegstudy_FFmpegKit_run
(JNIEnv *env, jclass obj, jobjectArray commands){
int argc = (*env)->GetArrayLength(env, commands);
char *argv[argc];
int i;
for (i = 0; i < argc; i++) {
jstring js = (jstring) (*env)->GetObjectArrayElement(env, commands, i);
argv[i] = ( char*) (*env)->GetStringUTFChars(env, js, 0);
}
return run(argc, argv);
}

编写 Android.mk

Android.mk

      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
      
      
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeg
LOCAL_SRC_FILES := libffmpeg.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeginvoke
LOCAL_SRC_FILES := com_ihubin_ffmpegstudy_FFmpegKit.c ffmpeg.c ffmpeg_opt.c cmdutils.c ffmpeg_filter.c
# 这里的地址改成自己的 FFmpeg 源码目录
LOCAL_C_INCLUDES := /Users/hubin/Desktop/ffmpeg-3.0
LOCAL_LDLIBS := -llog -lz -ldl
LOCAL_SHARED_LIBRARIES := ffmpeg
include $(BUILD_SHARED_LIBRARY)

编写 Application.mk 文件

Application.mk

      
      
1
2
      
      
APP_ABI := armeabi-v7a
APP_PLATFORM := android-14

Step 4: 编译

在命令行中定位到 src/main/jni 目录中,直接执行脚本

      
      
1
      
      
ndk-build

编译完成后就生成了所要的SO库文件:

ffmpeg_command_line_compile_success

ffmpeg_command_line_compile_so

做个Demo测试一下

△ Demo需要SD卡读写权限,所以先加两个权限:SD卡读写权限

      
      
1
2
      
      
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

△ Demo需要SD卡上有 input.mp4 和 input.mp3 两个文件

如果没有小文件,可以使用我提供的这两个文件:

input.mp3

input.mp4

Demo中的功能是:将input.mp4 和 input.mp3 两个文件合并成一段以input.mp3为背景音乐的 merge.mp4 文件

△ Demo运行命令行在主线程,操作文件比较大就会ANR,直接点取消别关闭,为了Demo简单,就不加异步了,需要的自己实现 3Q

MainActivity.java

      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
      
      
package com.ihubin.ffmpegstudy;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.ihubin.ffmpeg_command_line.R;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void run(View view){
String base = Environment.getExternalStorageDirectory().getPath();
Log.e( "PATH", base);
String[] commands = new String[ 9];
commands[ 0] = "ffmpeg";
commands[ 1] = "-i";
commands[ 2] = base + "/input.mp4";
commands[ 3] = "-i";
commands[ 4] = base + "/input.mp3";
commands[ 5] = "-strict";
commands[ 6] = "-2";
commands[ 7] = "-y";
commands[ 8] = base + "/merge.mp4";
int result = FFmpegKit.run(commands);
if(result == 0){
Toast.makeText(MainActivity. this, "命令行执行完成", Toast.LENGTH_SHORT).show();
}
}
}

activity_main.xml

      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
      
      
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools= "http://schemas.android.com/tools"
android:layout_width= "match_parent"
android:layout_height= "match_parent"
android:orientation= "vertical"
tools:context= "com.ihubin.ffmpegstudy.MainActivity">
<Button
android:onClick= "run"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:text= "Run"/>
</LinearLayout>

FFmpeg 命令行都可以执行了,还不赶紧做个App玩玩 !! 

源码

源码地址在这里 

Module:FFmpeg-Command-Line

Demo APK下载地址:https://www.pgyer.com/FFmpegCommandLine

也可以扫码下载体验:

app-qrcode-FFmpegCommandLine.png


来源地址:

http://www.ihubin.com/blog/android-ffmpeg-demo-4/

参考资料


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值