├── .gitignore
├── README.md
├── build.gradle
├── ffmtool.iml
├── libs
├── arm64-v8a
│ ├── libavcodec.so
│ ├── libavfilter.so
│ ├── libavformat.so
│ ├── libavutil.so
│ ├── libfdk-aac.so
│ ├── libjxffmpegrun.so
│ ├── libswresample.so
│ └── libswscale.so
├── armeabi-v7a
│ ├── libavcodec.so
│ ├── libavfilter.so
│ ├── libavformat.so
│ ├── libavutil.so
│ ├── libfdk-aac.so
│ ├── libjxffmpegrun.so
│ ├── libswresample.so
│ └── libswscale.so
└── armeabi
│ ├── libavcodec.so
│ ├── libavfilter.so
│ ├── libavformat.so
│ ├── libavutil.so
│ ├── libfdk-aac.so
│ ├── libjxffmpegrun.so
│ ├── libswresample.so
│ └── libswscale.so
├── proguard-rules.pro
└── src
├── androidTest
└── java
│ └── com
│ └── esay
│ └── ffmtool
│ └── ExampleInstrumentedTest.java
├── main
├── AndroidManifest.xml
├── java
│ └── com
│ │ └── esay
│ │ └── ffmtool
│ │ └── FfmpegTool.java
└── res
│ └── values
│ └── strings.xml
└── test
└── java
└── com
└── esay
└── ffmtool
└── ExampleUnitTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FFmpegLibrary
2 | 我们在实际开发过程中有时候会遇到这样的问题,有一个视频我们要拿到它的缩略图或者第几秒时间的画面。
3 | Android系统为我们提供了一个视频处理的类MediaMetadataRetriever,但是这个类一次只能获取一张图片,
4 | 不能批量获取,使用循环太麻烦,而且对于分辨率大的视频时间太长。那么视频处理肯定要用到FFmpeg,使用FFmpeg命令行
5 | 是非常方便的一种方式,对于一般的操作,视频的裁剪、压缩、转码等一条命令搞定。但是命令行在手机上进行某些操作的时候
6 | 效率实在不怎么高,获取分辨率为1920*1080视频的一帧图形花费的时间为0.5秒左右,好处是可以批量获取,但是数量到了几十
7 | 甚至上百的时候,就太漫长了。那么又想快又想批量处理的话就要用NDK直接用c语言对视频解码,找到图像帧转换成jpg保存到本地。
8 |
9 |
10 | 该工程是一个library,有两种使用方式。
11 | 1.直接下载下来,以module方式依赖在自己的项目中。
12 | 2.gradle方式依赖。
13 | 在项目根目录的gradle文件中添加
14 | allprojects {
15 | repositories {
16 | ...
17 | maven { url 'https://jitpack.io' }
18 | }
19 | }
20 |
21 | 再在app的gradle文件中添加依赖
22 | compile 'com.github.kui92:FFmpegLibrary:3.2'
23 |
24 |
25 |
26 | 具体用法:在类FfmpegTool中有两个native方法
27 | //执行FFmpeg命令
28 | public static native int cmdRun(String[] cmd);
29 |
30 | 使用方式:
31 | String cmd="FFmpeg命令";
32 |
33 | String regulation="[ \\t]+";
34 |
35 |
36 | final String[] split = cmd.split(regulation);
37 |
38 |
39 | final int result=FfmpegTool.cmdRun(split);
40 |
41 |
42 |
43 |
44 | //将视频解码,每一秒保存为一个jpg图片(因为关键帧的问题,在寻找时间时有时候可能有一两秒左右的偏差)
45 | //srcPath 视频地址 savePath 图片的保存路径 startTime 开始时间 count 要保存图片的数量一秒一幅
46 | public static native int decodToImage(String srcPath,String savePath,int startTime,int count);
47 |
48 | 这两个方法都是阻塞的方法
49 |
50 |
51 |
52 |
53 | 不想自己拼写命令的话还有几个封装方法,内部对命令进行了拼接,外部只需传递参数即可:
54 |
55 | /**
56 | * 视频裁剪
57 | * @param view
58 | */
59 | public void click1(View view){
60 | new Thread(){
61 | @Override
62 | public void run() {
63 | String basePath = Environment.getExternalStorageDirectory().getPath();
64 | String dir=basePath+File.separator+"test"+File.separator;
65 | String videoPath=dir+"c.mp4";
66 | String out=dir+"out.mp4";
67 | //参数说明 视频源 输出结果地址 开始时间单位s 视频时长单位s 标志位 回调
68 | ffmpegTool.clipVideo(videoPath, out, 10, 10, 1, new FfmpegTool.VideoResult() {
69 | @Override
70 | public void clipResult(int code, String src, String dst, boolean sucess, int tag) {
71 | Log.i("MainActivity","code:"+code);
72 | Log.i("MainActivity","src:"+src);
73 | Log.i("MainActivity","dst:"+dst);
74 | Log.i("MainActivity","sucess:"+sucess);
75 | Log.i("MainActivity","tag:"+tag);
76 | clipResutl=dst;
77 | }
78 | });
79 |
80 | }
81 | }.start();
82 | }
83 |
84 |
85 | /**
86 | * 解码成图片
87 | * @param view
88 | */
89 | public void click2(View view){
90 | new Thread(){
91 | @Override
92 | public void run() {
93 | String path= Environment.getExternalStorageDirectory().getPath()+ File.separator+"test"+File.separator;
94 | String video=path+"c.mp4";
95 | FfmpegTool.getInstance(MainActivity.this).videoToImage(video.replaceAll(File.separator, "/"), path.replaceAll(File.separator, "/"), 0, 60, new FfmpegTool.VideoResult() {
96 | @Override
97 | public void clipResult(int code, String src, String dst, boolean sucess, int tag) {
98 | Log.i("MainActivity","code:"+code);
99 | Log.i("MainActivity","src:"+src);
100 | Log.i("MainActivity","dst:"+dst);
101 | Log.i("MainActivity","sucess:"+sucess);
102 | Log.i("MainActivity","tag:"+tag);
103 | }
104 | },0);
105 | }
106 | }.start();
107 |
108 | }
109 |
110 |
111 |
112 | /**
113 | * 视频压缩
114 | */
115 | public void click3(View view){
116 | new Thread(){
117 | @Override
118 | public void run() {
119 | String path= Environment.getExternalStorageDirectory().getPath()+ File.separator+"test"+File.separator;
120 | //参数说明 视频源 压缩结果的保存目录 标志位 回调
121 | FfmpegTool.getInstance(MainActivity.this).compressVideo("/storage/emulated/0/test/out.mp4", path, 2, new FfmpegTool.VideoResult() {
122 | @Override
123 | public void clipResult(int code, String src, String dst, boolean sucess, int tag) {
124 | Log.i("MainActivity","code:"+code);
125 | Log.i("MainActivity","src:"+src);
126 | Log.i("MainActivity","dst:"+dst);
127 | Log.i("MainActivity","sucess:"+sucess);
128 | Log.i("MainActivity","tag:"+tag);
129 | }
130 | });
131 | }
132 | }.start();
133 | }
134 |
135 |
136 |
137 |
138 |
139 | 3.0版本新添加了一个带jni回调的图片解码方法decodToImageWithCall,该方法与decodToImage方法功能完全一样,不过该方法有过程监听,每完成一次图片
140 | 的解码与保存会回调一次decodToImageCall方法(也是一个FfmpegTool类的一个public方法,供jni调用回传参数),并传回新保存图片的地址与当前是图片下标。使用方法:
141 |
142 | FfmpegTool ffmpegTool=FfmpegTool.getInstance(MainActivity.this);
143 | ffmpegTool.setImageDecodeing(new FfmpegTool.ImageDecodeing() {
144 | @Override
145 | public void sucessOne(String path, int i) {
146 | Log.i("decodToImageCall","path:"+path+"___index:"+i);
147 | }
148 | });
149 |
150 | public void click4(View view){
151 | new Thread(){
152 | @Override
153 | public void run() {
154 | String path= Environment.getExternalStorageDirectory().getPath()+ File.separator+"test"+File.separator;
155 | String video=path+"c.mp4";
156 | ffmpegTool.decodToImageWithCall(video.replaceAll(File.separator,"/")
157 | ,Environment.getExternalStorageDirectory().getPath()
158 | + File.separator+"test2"+File.separator,0,10);
159 | }
160 | }.start();
161 | }
162 |
163 |
164 |
165 | 两个native方法的具体实现CSDN:http://blog.csdn.net/qq_28284547/article/details/78151635
166 |
167 |
168 |
169 |
170 |
171 |
172 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.2"
6 |
7 | defaultConfig {
8 | minSdkVersion 15
9 | targetSdkVersion 21
10 | versionCode 1
11 | versionName "1.0"
12 |
13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
14 |
15 | }
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 |
23 | sourceSets {
24 | main {
25 | jniLibs.srcDirs = ['libs']
26 | }
27 | }
28 | }
29 |
30 | dependencies {
31 | compile fileTree(dir: 'libs', include: ['*.jar'])
32 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
33 | exclude group: 'com.android.support', module: 'support-annotations'
34 | })
35 | compile 'com.android.support:appcompat-v7:25.3.1'
36 | testCompile 'junit:junit:4.12'
37 | }
38 |
--------------------------------------------------------------------------------
/ffmtool.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | generateDebugSources
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
--------------------------------------------------------------------------------
/libs/arm64-v8a/libavcodec.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/arm64-v8a/libavcodec.so
--------------------------------------------------------------------------------
/libs/arm64-v8a/libavfilter.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/arm64-v8a/libavfilter.so
--------------------------------------------------------------------------------
/libs/arm64-v8a/libavformat.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/arm64-v8a/libavformat.so
--------------------------------------------------------------------------------
/libs/arm64-v8a/libavutil.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/arm64-v8a/libavutil.so
--------------------------------------------------------------------------------
/libs/arm64-v8a/libfdk-aac.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/arm64-v8a/libfdk-aac.so
--------------------------------------------------------------------------------
/libs/arm64-v8a/libjxffmpegrun.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/arm64-v8a/libjxffmpegrun.so
--------------------------------------------------------------------------------
/libs/arm64-v8a/libswresample.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/arm64-v8a/libswresample.so
--------------------------------------------------------------------------------
/libs/arm64-v8a/libswscale.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/arm64-v8a/libswscale.so
--------------------------------------------------------------------------------
/libs/armeabi-v7a/libavcodec.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/armeabi-v7a/libavcodec.so
--------------------------------------------------------------------------------
/libs/armeabi-v7a/libavfilter.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/armeabi-v7a/libavfilter.so
--------------------------------------------------------------------------------
/libs/armeabi-v7a/libavformat.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/armeabi-v7a/libavformat.so
--------------------------------------------------------------------------------
/libs/armeabi-v7a/libavutil.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/armeabi-v7a/libavutil.so
--------------------------------------------------------------------------------
/libs/armeabi-v7a/libfdk-aac.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/armeabi-v7a/libfdk-aac.so
--------------------------------------------------------------------------------
/libs/armeabi-v7a/libjxffmpegrun.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/armeabi-v7a/libjxffmpegrun.so
--------------------------------------------------------------------------------
/libs/armeabi-v7a/libswresample.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/armeabi-v7a/libswresample.so
--------------------------------------------------------------------------------
/libs/armeabi-v7a/libswscale.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/armeabi-v7a/libswscale.so
--------------------------------------------------------------------------------
/libs/armeabi/libavcodec.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/armeabi/libavcodec.so
--------------------------------------------------------------------------------
/libs/armeabi/libavfilter.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/armeabi/libavfilter.so
--------------------------------------------------------------------------------
/libs/armeabi/libavformat.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/armeabi/libavformat.so
--------------------------------------------------------------------------------
/libs/armeabi/libavutil.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/armeabi/libavutil.so
--------------------------------------------------------------------------------
/libs/armeabi/libfdk-aac.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/armeabi/libfdk-aac.so
--------------------------------------------------------------------------------
/libs/armeabi/libjxffmpegrun.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/armeabi/libjxffmpegrun.so
--------------------------------------------------------------------------------
/libs/armeabi/libswresample.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/armeabi/libswresample.so
--------------------------------------------------------------------------------
/libs/armeabi/libswscale.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kui92/FFmpegLibrary/53744cfdb1ba1438874a2d644ddcc76fd1e45698/libs/armeabi/libswscale.so
--------------------------------------------------------------------------------
/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\studio\standard\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/src/androidTest/java/com/esay/ffmtool/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.esay.ffmtool;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.esay.ffmtool.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/main/java/com/esay/ffmtool/FfmpegTool.java:
--------------------------------------------------------------------------------
1 | package com.esay.ffmtool;
2 |
3 | import android.app.Activity;
4 | import android.util.Log;
5 |
6 | /**
7 | * Created by ZBK on 2017/9/28.
8 | * Describe:
9 | */
10 |
11 | public class FfmpegTool {
12 | /**
13 | * 裁剪视频的回调接口
14 | */
15 | public interface VideoResult{
16 | /**
17 | * 裁剪结果回调
18 | * @param code 返回码
19 | * @param src 视频源
20 | * @param dst 裁剪结果保存地址
21 | * @param sucess 裁剪是否成功 true 成功
22 | */
23 | public void clipResult(int code,String src,String dst,boolean sucess,int tag);
24 | }
25 |
26 | public interface ImageDecodeing{
27 | public void sucessOne(String path,int i);
28 | }
29 |
30 |
31 | private static FfmpegTool instance;
32 |
33 | private Activity activity;
34 | private ImageDecodeing imageDecodeing;
35 |
36 |
37 | public ImageDecodeing getImageDecodeing() {
38 | return imageDecodeing;
39 | }
40 |
41 | public void setImageDecodeing(ImageDecodeing imageDecodeing) {
42 | this.imageDecodeing = imageDecodeing;
43 | }
44 |
45 | private FfmpegTool(){
46 |
47 | }
48 |
49 | private void init(Activity activity){
50 | this.activity=activity;
51 | }
52 |
53 |
54 |
55 | public static FfmpegTool getInstance(Activity activity){
56 | if (instance==null){
57 | synchronized(FfmpegTool.class){
58 | if (instance == null)instance = new FfmpegTool();
59 | }
60 | }
61 | instance.init(activity);
62 | return instance;
63 | }
64 |
65 | static {
66 | System.loadLibrary("avutil");
67 | System.loadLibrary("fdk-aac");
68 | System.loadLibrary("avcodec");
69 | System.loadLibrary("avformat");
70 | System.loadLibrary("swscale");
71 | System.loadLibrary("swresample");
72 | System.loadLibrary("avfilter");
73 | System.loadLibrary("jxffmpegrun");
74 | }
75 |
76 |
77 | public static native int cmdRun(String[] cmd);
78 |
79 | public static native int decodToImage(String srcPath,String savePath,int startTime,int count);
80 |
81 |
82 |
83 | public int videoToImage(final String src, final String dir, int startTime, int count, final VideoResult call, final int tag){
84 | final int result=decodToImage(src,dir,startTime,count);
85 | if (call!=null){
86 | activity.runOnUiThread(new Runnable() {
87 | @Override
88 | public void run() {
89 | boolean ret=true;
90 | if (result!=0){
91 | ret=false;
92 | }
93 | call.clipResult(result,src,dir,ret,tag);
94 | }
95 | });
96 | }
97 | return result;
98 | }
99 |
100 |
101 | //ffmpeg -y -ss 10 -t 15 -i /storage/emulated/0/test/c.mp4 -vcodec copy -acodec copy -strict -2 /storage/emulated/0/test/out.mp4
102 |
103 | /**
104 | * 裁剪视频
105 | * @param src 视频源地址
106 | * @param dst 裁剪结果
107 | * @param startTime 开始裁剪时间
108 | * @param duration 裁剪时长
109 | * @return
110 | */
111 | public int clipVideo(final String src, final String dst, int startTime, int duration, final int tag, final VideoResult call){
112 | String cmd=String.format("ffmpeg -y -ss "+startTime+" -t "+duration+
113 | " -i "+src+" -vcodec copy -acodec copy -strict -2 "+dst);
114 | String regulation="[ \\t]+";
115 | Log.i("clipVideo","cmd:"+cmd);
116 | final String[] split = cmd.split(regulation);
117 | final int result=cmdRun(split);
118 | if (call!=null){
119 | activity.runOnUiThread(new Runnable() {
120 | @Override
121 | public void run() {
122 | call.clipResult(result,src,dst,result==0,tag);
123 | }
124 | });
125 | }
126 | return result;
127 | }
128 |
129 | //ffmpeg -y -i /storage/emulated/0/esay/temp/temp1506592501.mp4 -b:v 1500k -bufsize 1500k -maxrate 2000k -g 26 /storage/emulated/0/esay/temp/temp1506592521.mp4
130 |
131 | /**
132 | * 压缩视频
133 | * @param src 视频源地址
134 | * @param dst 结果目录
135 | * @param tag 标志位
136 | * @param call 回调
137 | * @return
138 | */
139 | public int compressVideo(final String src,final String dst, final int tag, final VideoResult call){
140 | final String dst2=dst+"temp"+System.currentTimeMillis()/1000+".mp4";
141 | String cmd=String.format("ffmpeg -threads 32 -y -i "+src
142 | +" -b:v 1500k -bufsize 3000k -maxrate 2000k -preset superfast "+dst2);
143 | //cmd="ffmpeg -threads 64 -i /storage/emulated/0/test/out.mp4 -c:v libx264 -x264opts bitrate=2000:vbv-maxrate=2500 -crf 20 -preset superfast -vbr 4 /storage/emulated/0/test/tes.mp4";
144 | String regulation="[ \\t]+";
145 | Log.i("compressVideo","cmd:"+cmd);
146 | final String[] split = cmd.split(regulation);
147 | final int result=cmdRun(split);
148 | if (call!=null){
149 | activity.runOnUiThread(new Runnable() {
150 | @Override
151 | public void run() {
152 | call.clipResult(result,src,dst2,result==0,tag);
153 | }
154 | });
155 | }
156 | Log.i("compressVideo","result:"+result);
157 | return result;
158 | }
159 |
160 | /**
161 | * 解析图片过程中jni的回调方法
162 | * @param path
163 | * @param index
164 | */
165 | public void decodToImageCall(final String path,final int index){
166 | if(imageDecodeing!=null){
167 | activity.runOnUiThread(new Runnable() {
168 | @Override
169 | public void run() {
170 | imageDecodeing.sucessOne(path,index);
171 | }
172 | });
173 | }
174 | //Log.i("decodToImageCall","path:"+path+"___index:"+index);
175 | }
176 |
177 | public native int decodToImageWithCall(String srcPath,String savePath,int startTime,int count);
178 |
179 |
180 | public void relase(){
181 | this.activity=null;
182 | }
183 |
184 |
185 | }
186 |
--------------------------------------------------------------------------------
/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | FfmTool
3 |
4 |
--------------------------------------------------------------------------------
/src/test/java/com/esay/ffmtool/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.esay.ffmtool;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------