android 高级之旅 (十七)FFmpeg移植android的崎岖路!

经过快十天的摸爬滚打,我终于从一个没听说过ffmpeg的傻x成长到一个成功移植ffmpeg到android的不那么傻的傻x。 其中的艰辛真是难以言表。特此记录,以让后来人少走弯路。 ————————————————————————

一 、开始

啥是ffmpeg?
FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序

一番百度谷歌csdn简书巴拉巴拉千辛万苦后,认清了啥是ffmpeg ,咋搞?照着别人的博客啥的一步步跟着来呗,好吧,至此,我的一只脚已经踏入坑中。

#二 、步骤

1. 第一步编译ffmpeg源码呗


其中步骤,大概可分为以下几点:
“编译FFmpeg类库”、“编写Java端代码”、“编写C语言端代码”


具体步骤,我都是按照下面链接这位大婶的指引来的
http://www.jianshu.com/p/dfd0de17601c

但是几番周折,在公司电脑编译几次,永远都会报错,报文件丢失 后,又换了自己的电脑来编译,这次,依然失望而归!还是编译失败!

妈卖批??? 还能不能好好玩了???

但是倔强的我心想,不能就此做罢 ,既然我编译不出来 ,咋办?

那我TM就不自己编译了呗!!! 哈哈哈哈哈

于是下载好别人已经编译成功的DEMO 再次感谢大神,链接奉上

https://github.com/codeqian/ffmpegCLDemo

下载好项目解压下来之后,可以再项目中找到编译好的ffmpeg源码压缩包
这里写图片描述

再次解压就能得到已经编译好的源码了。但是里面有很多配置信息以及代码需要改成我们自己的项目中的包名以及目录地址。


2. 修改下载的源码

这里的步骤挺多的,我真是看了好多天,现在对这些步骤都很熟悉了,本觉得是很僵硬的步骤,大家百度一下应该就都能知道,但是考虑到大家可能暂时还没我这么熟悉,还是一步步贴一下吧。

1) 创建好自己的项目,在 src/main/ 目录下新建 jni 目录。并将libffmpeg.so文件丢进去。,这里可以图方便,将我们前面下载的项目中的jni目录中的一系列文件都复制过来好了。(要注意,下面的com_jtjsb_wssysp_FFmpegKit.c 和com_jtjsb_wssysp_FFmpegKit.h 两个文件是等下编译生成的,不要复制demo中的这两个文件)
android 高级之旅 (十七)FFmpeg移植android的崎岖路!_第1张图片

2) 复制demo FFmpegKit.java 文件到自己的项目中,注意包名导入是否正确。这个是用来调用ffmpeg可执行文件的。

3)在终端中切到src/main/java文件夹下,输入:

javah XXX.XXX.XXX.FFmpegKit   这里要填入你自己的正确的报名路径,点换成

然后执行之后就会在该目录生成 com_jtjsb_wssysp_FFmpegKit.h 文件,将这个文件移动到 jni 目录。

4) 自己新建一个com_jtjsb_wssysp_FFmpegKit.c的文件,或者复制demo中的这个.c文件 改好文件名对应自己的包,文件需要修改一下两个地方 注意都改成自己的项目下的 包名
android 高级之旅 (十七)FFmpeg移植android的崎岖路!_第2张图片

5) 编辑Android.mk
修改以下地方为自己的路径
android 高级之旅 (十七)FFmpeg移植android的崎岖路!_第3张图片

6)在终端中定位到jni目录,执行ndk -build
到这一步,如果你的操作都没问题,应该会顺利执行完。如果执行过程报文件找不到,那你再好好检查检查 哈哈哈哈哈~~~

7)在build.gradle文件中修改下库文件地址的指向

android {
    sourceSets {
        main {
            jniLibs.srcDirs = ['src/main/libs']
            jni.srcDirs=[]
        }
    }
}

8) 啊啊啊啊 okokok终于可以在android中使用ffmpeg库了。


3.什么?怎么用??

其实你自习看看demo中的mainactivity中的代码就可以发现用法 其中唯一要研究一下的就是执行时候传入的命令参数的意义。
参见
http://blog.csdn.net/l_yangliu/article/details/7274968
http://www.xuebuyuan.com/1675738.html

下面是我的项目中的添加水印的代码

 private void makeVideo() {
        Log.d("test", "makeVideo: --------------videoUrl=" + videoUrl + " ---imageUrl=" + imageUrl);
        Runnable compoundRun=new Runnable() {
            @Override
            public void run() {
                String[] commands = new String[12];
                commands[0] = "ffmpeg";
                commands[1] = "-i";
                commands[2] = videoUrl;
                commands[3] = "-i";
                commands[4] = imageUrl;
                commands[5] = "-filter_complex";
                commands[6] = "overlay=10:10";
                commands[7] = "-b";        这个
                commands[8] = "2048k";     和这个 是为了使视频质量不掉的太严重
                commands[9] = "-codec:a";
                commands[10] = "copy";
                commands[11] = outputUrl;
//                添加水印的命令 对应数组中的元素 :
                /**
                 * "-y
                 * -i "+
                 * filename+
                 * " -acodec copy -b 300k -vf \"movie="
                 * +imagename+
                 * " [watermark]; [in][watermark] overlay=10:10 [out]\" "
                 * +newfilename+
                 * "";
                  */

//                ffmpeg -iWildlife.wmv-vf "movie=panda.png[watermark];[in][watermark] overlay=10:10[out]"
//                原始视频文件路径:Wildlife.wmv
//                水印图片路径:panda.png
//                水印位置:(x,y)=(10,10)<=(left,top)距离左侧、顶部各10像素;
//                输出文件路径:Marked.wmv

                FFmpegKit.execute(commands, new FFmpegKit.KitInterface() {
                    @Override
                    public void onStart() {
                        Log.d("FFmpegLog LOGCAT","FFmpeg 命令行开始执行了...");

                    }

                    @Override
                    public void onProgress(int progress) {
                        Log.d("FFmpegLog LOGCAT","done com"+"FFmpeg 命令行执行进度..."+progress);

                    }

                    @Override
                    public void onEnd(int result) {
                        Log.d("FFmpegLog LOGCAT","FFmpeg 命令行执行完成...");

                        playVideo();//播放视频
                    }
                });
            }
        };
        ThreadPoolUtils.execute(compoundRun);
    }

上面参数可能你看的还是有点云里雾里 这就需要你好好看看或者查查关于ffmpeg的命令的资料了。


在FFmpegKit.java中 的最后的run方法永远是红的,这个不用管他
android 高级之旅 (十七)FFmpeg移植android的崎岖路!_第4张图片


ok 至此,已经成功将ffmpeg移植到安卓了,虽然过程中有些投机取巧的部分不建议大家学习,但在实际工作中,没有充足时间自习了解技术又没人教的情况下,不失为一种可行的方法,但是空余时候一定要好好吃透他,ffmpeg是真的很强大很重要的东西。


有任何疑问,留言或者私信,在我力所能及范围内我乐意帮助你。


分享是会让人快乐啊,一起high一起成长吧~谁让我也是个菜鸟呢

你可能感兴趣的:(android,高级之旅)