使用JavaCV(ffmpeg)录制视频
JavaCV是对各种常用计算机视觉库的封装后的一组jar包,其中封装了ffmpeg、OpenCV、libdc1394、OpenKinect、videoInput和ARToolKitPlus等计算机视觉编程人员常用库的接口,可以通过其中的utility类方便的在包括Android在内的Java平台上调用这些接口。其中使用最多的应该就是ffmpeg了。
起初Javacv是googlecode下面的一个项目,后续迁移到了github,并且包名也由com.googlecode.javacv
改为org.bytedeco.javacv
,网上的demo主要有两个:
https://github.com/peirenlei/FFmpegRecorder
https://github.com/CrazyOrr/FFmpegRecorder
我是参考的上面那个,但是使用的是最新的版本1.3.1 。
集成过程中遇到很多问题,弄了一个多星期,在此就记录一下。
集成:
https://github.com/bytedeco/javacv/releases
直接下载打包好的jar文件,如下图
其中,javacpp.jar 和 javacv.jar是必须的两个包,然后需要什么功能就添加额外的包。例如我需要用到ffmpeg进行视频录制,则需要添加ffmpeg.jar和ffmpeg-android-arm.jar(打包的arm平台so库)。这里很方便的地方是,so库文件都放在了jar文件里面,所以在集成的时候很简洁明了。
把需要的jar包拷贝到项目的libs目录下就可以直接使用了,
具体的使用则参考demo:https://github.com/brian512/AndroidDemo
下面就说一下遇到的坑:
在Android M平台,会有异常
java.lang.UnsatisfiedLinkError: org.bytedeco.javacpp.avutil
这个问题对应的issue:
https://github.com/bytedeco/javacv/issues/245
https://github.com/bytedeco/javacv/issues/579
我的解决方案是在这个帖子里找到的,但是遇到这个问题的人太多,导致这个问题的原因也比较多,例如版本、平台等。而我遇到的这个情况是,在Android M以下版本都是正常的,所以不会是javacv的版本和打包的问题。
最终是通过ReLinker解决的,这是作者的说明:https://github.com/bytedeco/javacpp-presets/wiki/The-UnsatisfiedLinkError-X-File-%28a-real-experience%29
这是意料之外的,之前从未想过说System.loadLibrary("")
会不可靠,但是仅仅替换为ReLinker.recursively().loadLibrary()
,问题就迎刃而解。录制时的参数设置
初始化Frame的参数:
private int frameDepth = Frame.DEPTH_UBYTE; //DEPTH_UBYTE=8
private int frameChannels = 2;
FFmpegFrameRecorder支持很多格式的录制,所以在进行录制时需要指定数据的格式,这些格式定义在org.bytedeco.javacpp.avutil.AV_PIX_FMT_XXX
,如果是相机预览回调的YUV格式,则只需要用默认的。如果是RGBA的则需要指定为mVideoRecorder.record(mFrameData, AV_PIX_FMT_RGBA);
录制时需要注意视频预览尺寸与视频录制尺寸混淆,特别是相机预览的宽高的颠倒问题。
- javacv库比较大,所以尽量不用gradle的方式集成
- 录制比较耗时
录制540*960的视频需要60ms左右,这个性能已经不太能接受,所以尽量使用独立的线程进行录制。如果后续发现优化方法再更新,也欢迎留言补充!