最近两个月在搞 Android 音视频相关方面的需求,下面是记录一次音视频开发的实操记录;
最下面有demo;
移动端具体的需求是这个样子的:
录制视频 + 同时语音识别 + 同时人脸识别 + 同时语音合成;视频时长大概是一个小时,不能压缩处理。
OK,需求出来我是崩溃的,Android 原生不支持录制视频的同时去实现语音识别,而 iOS 原生支持,这就加长了 Android 开发周期;其次 Android 麦克风不支持同时两个音频源同时输入音频,也就是说要使用 MediaCodec (编解码器) 和 MediaFormat ;这对于九窍已通八窍的我着实有点难度;
认真分析之后给出了下面几种方案:
方案一:
开一个线程使用 AudioRecord 录制音频流,将音频流拿去解析实现语音识别同时使用 MediaCodec 编码成 AAC 音频格式文件;
另一个线程使用 Camera 录制视频流,拿到视频流去实现人脸识别同时使用 MediaCodec 编码成 H264 格式视频流文件;
最后将 AAC 与 H264 合成为 MP4 格式视频文件;
方案二:
开一个线程使用 AudioRecord 录制音频流,将音频流拿去解析实现语音识别同时使用 MediaCodec 编码成 AAC 音频格式文件;
另一个线程使用 Camera 录制视频流,拿到视频流去实现人脸识别同时使用 MediaCodec 编码成 H264 格式视频流文件;
第三个线程为混合线程,将音视频流分别添加音视频轨道,实时合成 MP4 格式文件;
方案确定就开始实现,我在写语音识别用的是百度AI的SDK,因为测试阶段需要用到免费SDK,确定后才能购买SDK;我对比了两种语音识别的SDK:
科大讯飞,语音识别SDK价格最贵,成功率最高,95%左右;
百度AI,语音识别模块部分不收费,成功率稍低,90%左右;
所以选择了百度AI,毕竟不要钱;
将 SDK 集成之后,发现了一个不可思议的地方:
百度AI支持识别音频流,但是只要使用百度AI,就要给它麦克风权限,但是我传入的是音频流啊!积极联系百度AI人员之后,他们也发现了这个问题;
既然如此,那直接用百度AI进行语音识别,然后 SDK 会返回音频流,我拿着音频流保存到 AAC 文件,最后进行音视频合成;
当代码写完才发现,音视频合成会出现不同步的现象,查阅资料发现可能是因为时间戳的问题;认真检查代码后发现,时间戳明明是正确的。
研究了几天后恕我无能,最终还是使用了第二种方案,为音视频分包添加轨道,并实时的合成,这种方案是成功没有问题的;
录制没有问题,语音识别也没有问题,就开始研究视频流人脸识别,人脸识别就更加花哨了:
虹软人脸识别、OpenCV、face++ 等等;
好在人脸识别都是免费的,进行了一番筛选,上面的都需要添加各种 jar 包,会增加apk包的体积,并且要按照它们要使用 CameraSurfaceView 和 CameraGLSurfaceView ,这也就意味着要替换调我封装好的代码;
这样我是绝望的,奔着不修改原有代码的原则,我选择了 Google 自带的 FaceDetectionListener ,这样保证代码量修改最少,并且我只需要自定义 view,将人脸框画出来就可以了。
其实选择 Google 自带的 FaceDetectionListener 还有一个很重要的原因:
现在已经除了主线程之外,已经有三个线程同时工作:音频线程、视频线程、音视频流合成线程;如果使用第三方SDK,SDK消耗内存是非常大的,还需要再开启一个线程;不要忘记后面的语音合成还需要一个线程单独工作;
这个需求就是这样实现的,具体还是非常的麻烦的,因为线程过多,写的时候要注意内存泄漏的问题。
下面是具体的实现代码,以及完整的 demo,demo 包括录制视频 + 语音识别 + 人脸识别:
GitHub:https://github.com/wuqingsen/RecordVideoWu
这个 demo 是音视频流文件录制编码以及合成为mp4格式文件,可以作为参考:
GitHub:https://github.com/wuqingsen/ToMp4Wu
这是实现的效果图,(左侧是语音识别结果,中间白框为人脸画框):
后面会整理出,详细的代码模块和基础的音视频编码等;