游客发表
Android设备直接调用网络摄像头的用网RTSP流做扫码识别,这事儿坑比想象中多。络摄别急着上ZXing或ML Kit,扫码先解决视频源接入问题。用网
网络摄像头一般输出RTSP流,络摄Android原生MediaPlayer不支持这协议。扫码第三方库像Vitamio早废了,用网现在主流方案是络摄MediaKit或ExoPlayer配RTSP扩展。实测ExoPlayer的扫码RtspMediaSource在Android 8以上稳定,延迟能控在200ms内,用网够扫码用。络摄
代码大概长这样:
RtspMediaSource.Factory factory = new RtspMediaSource.Factory(); MediaSource mediaSource = factory.createMediaSource(Uri.parse("rtsp://192.168.1.64:554/stream1")); exoPlayer.setMediaSource(mediaSource); exoPlayer.prepare(); 但真正麻烦的扫码是画面预览和扫码逻辑的衔接。摄像头画面得先渲染到SurfaceView或TextureView上,用网然后从这View里截帧做识别。络摄直接拿SurfaceView的扫码bitmap会黑屏,必须用TextureView的getBitmap(),而且得等视频首帧出来后再截,否则拿到的是全黑图。
我调过一个海康的枪机,分辨率设成1080p时帧率掉到15fps,扫码框扫静止的二维码都费劲。后来把摄像头子码流切到720p,反而流畅了。网络摄像头的码流参数直接影响识别速度,别迷信高分辨率。
解码后的帧数据走ZXing的PlanarYUVLuminanceSource最稳。记得把ImageProxy的旋转角度处理好,竖屏设备拿到的帧是横的,不旋转90度识别率直线下降。有个野路子:把TextureView旋转90度,同时把帧数据也旋转,但这样UI和识别结果对不上,不推荐。
实际项目里还有个隐蔽坑——网络延迟抖动。扫码是连续帧操作,偶尔卡一帧没事,但RTSP流如果缓冲策略不对,画面会越积越卡。ExoPlayer的loadTimeout要设短点,我设了3000ms,超时直接重连。摄像头断线重连逻辑必须写,否则设备重启后APP就瞎了。
最后说个玄学问题:部分手机硬解RTSP流时,TextureView的getBitmap()会偶发返回null。我在小米11上遇到过,最后方案是加个Handler轮询,等bitmap非空再送识别,大概延迟30ms,不影响体验。
这套方案跑下来,局域网内识别速度能到每秒10次左右,够用。要是跨公网访问,延迟会飙到1秒以上,扫码基本废了,那种场景建议改走HTTP拉流或直接用摄像头自带的人脸识别接口。
友情链接