Android CameraX录制视频时如何提取缓冲区数据
CameraX 1.1.0及以上稳定版本已经开放了录制过程中的缓冲区获取入口,不需要修改框架源码,只要根据自己的处理场景选择对应配置即可,不要使用默认直接绑定输出文件的调用方式——默认prepareRecording绑定FileOutputOptions的写法会把帧处理、编码、写入全流程封装在内部,无法拦截中间缓冲。
场景1:需要拿到编码前的原始采集帧(适用于加滤镜、帧内容编辑、AI实时处理等需求)
并行绑定一个和VideoCapture参数完全匹配的ImageAnalysis用例即可,CameraX底层会自动复用同一路相机采集流,不会产生额外的性能开销。注意两个用例的目标分辨率、帧率、旋转角度配置必须完全一致,同时ImageAnalysis使用STRATEGY_KEEP_ONLY_LATEST回压策略避免帧堆积。
参考配置代码:// 初始化录制用例 val videoCapture = VideoCapture.withConfig( Recorder.Builder() .setQualitySelector(QualitySelector.from(Quality.HD)) .build() ) // 初始化帧抓取用例,参数和VideoCapture完全对齐 val frameGrabber = ImageAnalysis.Builder() .setTargetResolution(Size(1280, 720)) .setTargetFrameRate(Range(30, 30)) .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .build() .apply { setAnalyzer(Executors.newSingleThreadExecutor()) { imageProxy -> // 此处即可拿到和录制流同源的YUV格式原始帧缓冲区 val framePlanes = imageProxy.planes // 执行自定义帧处理逻辑 customFrameProcess(framePlanes) // 若需要将修改后的帧送回录制链路,需要通过OpenGL共享Surface做帧交换,直接修改planes数据不会生效 imageProxy.close() } } // 两个用例同时绑定到生命周期即可 cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, videoCapture, frameGrabber)场景2:需要拿到编码后的视频码流缓冲(适用于视频加密、自定义封装、边录边推流等需求)
CameraX 1.2.0及以上版本的Recorder开放了编码器回调,不需要绑定文件输出选项,直接注册回调即可拿到编码完成的H264/H265码流缓冲,处理完成后可以自行通过MediaMuxer写入文件,或者推到流媒体服务。
参考配置代码:// 初始化MediaMuxer用于后续写文件 val mediaMuxer = MediaMuxer(outputFilePath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4) var videoTrackIndex = -1 val recorder = Recorder.Builder() .setQualitySelector(QualitySelector.from(Quality.HD)) .setEncoderCallback(Executors.newSingleThreadExecutor()) { encodedSample -> // 首次拿到输出格式时添加音轨 if (encodedSample is EncodedSample.Format) { videoTrackIndex = mediaMuxer.addTrack(encodedSample.format) mediaMuxer.start() return@setEncoderCallback } // 拿到编码后的码流缓冲 val buffer = encodedSample.byteBuffer val bufferInfo = encodedSample.bufferInfo // 执行自定义码流处理逻辑(加密、封包等) val processedBuffer = customStreamProcess(buffer) // 处理完成后写入文件 mediaMuxer.writeSampleData(videoTrackIndex, processedBuffer, bufferInfo) } .build()
注意:如果需要对原始帧做修改后再编码,不要直接修改ImageProxy返回的内存数据,这部分内存是相机和编码链路共享的只读缓冲区,直接修改会导致帧错乱、花屏,必须通过OpenGL创建离屏Surface,把处理后的帧绘制到VideoCapture的编码输入Surface上。
内容的提问来源于stack exchange,提问作者Aatman Vaidya

