├── .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 | 8 | 9 | 10 | 11 | 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 | } --------------------------------------------------------------------------------