You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android CameraX录制视频时如何提取缓冲区数据

CameraX VideoCapture获取录制缓冲区数据实现方法

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 09:45:18