对这一段时间来,一直调查的方向做个总结。
UVC Camera
Android 设备要连接 USB 外置摄像头,需要对接 UVC
协议,这方面,大多数推荐的库为 saki4510t/UVCCamera
。绝大多数的第三方库都基于此库进行修改、完善和封装。
百度百科:UVC全称为 USB Video Class,即:USB视频类,是一种为USB视频捕获设备定义的协议标准。是Microsoft与另外几家设备厂商联合推出的为USB视频捕获设备定义的协议标准,已成为USB org标准之一。
RTMP
通用的流程一般就是调用 Camera/Camera2 以及麦克风进行音视频采集之后合成推流 1:
Android 上支持流媒体解析或推流的库主要有以下几个:
- yasea
- 纯 Java 编译
- 不支持 UVC
- EasyRTMP
- 平台支持:Windows、Linux、ARM(各种交叉编译工具链)、Android、iOS
- 支持 UVC
- 收费
- rtmp-rtsp-stream-client-java
- 支持 RTMP、RTSP
- Java 编写
- 不支持 UVC
- Native - 通过 JNI 调用 C++,不支持 UVC
- AndroidUSBCamera
- 基于
saki4510t
- USB 摄像头 (UVC) 视频录制和图片抓拍,支持边推流边录像
- 需手动适配设备本身的 Camera
- 基于
- JavaCV
- 用 JNI 封装了OpenCV,FFmpeg,libdc1394,PGR FlyCapture,OpenKinect,librealsense,CL PS3 Eye Driverx,videoInput,ARToolKitPlus以及flandmark 等的接口,从而为 Java 操作提供便捷方式
- 全平台支持 RTMP、RTSP
- 因为有 opencv,所以可以做图像处理方面的工作
- 不支持 UVC
- 其他SDK
- 大牛直播 SDK
- 金山云等
所以,综上考虑一下,采用 AndroidUSBCamera+JavaCV是一个很好的方式,一个负责画面展示,一个负责音频以及数据解析:
本身 AndroidUSBCamera
提供预览接口,所以我们可以设置变量在录制时通过 setOnPreviewFrameListener
处理传来的视频 nv21
信息;而 JavaCV
则可以处理音频数据,然后借助 ffmpeg
合成推流。主要参考就是示例工程中的 RecordActivity
3。
坑
AndroidUSBCamera
这个 saki4510t UVCCamera
的依赖库最好还是直接下载 aar
和 jar
更快一些,也避免一些编译错误。
JavaCV
因为是全平台的,所以最好删减一下,但是在使用过程中,会爆出 couldn't find "libjniavutil.so"
5 的错误,我这边的解决方式为:
1 | ndk { |
测试服务器
- OSSRS SRS - 支持 RTMP/HLS/WebRTC/SRT/GB28181
- nginx-rtmp-win32 - Windows 下开箱即用,比较简单
- Node-Media-Server +
flvjs
优化
这里需要对 ffmpeg
的参数有所了解,通过一些控制参数来降低推流的延迟7:
- 关闭 sync-lookahead
- 降低 rc-lookahead,但别小于 10,默认是 -1
- 降低 threads(比如从 12 降到 6)
- 禁用 rc-lookahead
- 禁用 b-frames
- 缩小 GOP
- 开启 x264 的 -preset fast/faster/verfast/superfast/ultrafast 参数
- 使用 -tune zerolatency 参数
具体到 JavaCV
代码中9:
1 | // FFmpegFrameRecorder(String filename, int imageWidth, int imageHeight, |
结语
从前年直播答题开始的预热,到去年抖音、快手的直播、连麦、短视频、KOL 带货等的推动,加之现在疫情期间在线授课、远程工作的加持,借助 4/5G 网络,这算是当前一直很火热的领域了;以前觉得集成集成一个就行,而现在用户经过培育之后,体验方面要求也越来越高,稳定性、安全性更不用说了,真是需要积累的。这也算是一种倒逼吧。
经过这段时间的摸索,感觉流媒体技术方面是个很大的“坑”——网上的资料大部分都是初级的入门教程,却没有一个深入的讲解,绝大部分不能用于生产环境。除去说的资源和教程少,单单拿出的细分领域也多,而协议更多,比如 RTMP、RTSP、HLS、webRTC……以及还要对各家的摄像头和 NVR 的对接要做的了然于胸。深深感觉到自己的菜,自研的话技术壁垒确实高,入门曲线特别抖,核心代码一般都是 C++,而且还要交叉编译到各个平台,😵。而借助开源库虽然可以实现一些功能,但是要改动的话还是要对一些库做功课,这个不是一朝一夕的功夫,如果有个带头大哥真是再好不过。