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

使用ExoPlayer播放RTSP流时,如何处理视频帧并做深度学习检测?

基于ExoPlayer+ImageReader实现帧级目标检测方案

核心思路

借助ExoPlayer的VideoFrameMetadataListener获取解码后的帧数据,搭配ImageReader将帧转换为深度学习模型可接收的格式,再送入模型完成目标检测。

步骤与代码示例

1. 初始化ImageReader

创建ImageReader时指定适配的尺寸、格式(优先选ImageFormat.YUV_420_888,这是ExoPlayer默认输出格式)和最大缓存帧数量:

private lateinit var imageReader: ImageReader

// 在页面初始化方法(如onCreate)中执行
imageReader = ImageReader.newInstance(
    videoWidth, // 视频宽度,可从ExoPlayer的MediaMetadata获取
    videoHeight, // 视频高度
    ImageFormat.YUV_420_888,
    2 // 最多缓存2帧,避免内存过载
)
imageReader.setOnImageAvailableListener({ reader ->
    val image = reader.acquireNextImage()
    image?.let {
        processFrameForDetection(it)
        it.close() // 必须关闭,否则会阻塞后续帧输出
    }
}, Handler(Looper.getMainLooper()))

2. 给ExoPlayer绑定帧监听

通过VideoFrameMetadataListener拿到解码后的帧,将其渲染到ImageReader的Surface:

player.addVideoFrameMetadataListener { frameInfo, _ ->
    val surface = imageReader.surface
    frameInfo.surfaceTexture?.apply {
        updateTexImage()
        drawFrame(surface)
    }
}

3. 帧数据转换与模型推理

将Image对象转为模型需要的格式(比如RGB Bitmap或张量),这里以转Bitmap为例:

private fun processFrameForDetection(image: Image) {
    // 将YUV格式转为JPEG字节数组
    val yuvImage = YuvImage(
        image.planes[0].buffer,
        ImageFormat.NV21,
        image.width,
        image.height,
        null
    )
    val outputStream = ByteArrayOutputStream()
    yuvImage.compressToJpeg(Rect(0, 0, image.width, image.height), 100, outputStream)
    val byteArray = outputStream.toByteArray()
    val bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size)
    
    // 调用深度学习模型做目标检测
    detectObjects(bitmap)
    
    bitmap.recycle() // 及时释放Bitmap内存
}

// 替换为你的实际模型推理逻辑
private fun detectObjects(bitmap: Bitmap) {
    val detectionResults = yourDetectionModel.runInference(bitmap)
    detectionResults.forEach { result ->
        // 处理检测结果,比如打印日志、绘制目标框
        Log.d("Detection", "检测到:${result.label},位置:${result.boundingBox}")
    }
}

4. 资源释放

在页面销毁或播放器停止时,务必释放相关资源:

override fun onDestroy() {
    super.onDestroy()
    imageReader.close()
    player.removeVideoFrameMetadataListener()
    player.release()
}

其他可行方案

  • ML Kit视频检测:如果用Google ML Kit,可直接将ExoPlayer的Surface传入ML Kit视频检测器,无需手动处理帧转换,适合快速集成。
  • 自定义VideoRenderer:继承ExoPlayer的VideoRenderer,在解码后直接获取帧数据,性能损耗低,但实现难度高,需要熟悉ExoPlayer渲染流程。
  • AnalyticsListener回调:通过onVideoFrameRendered获取渲染时机,但无法直接拿帧数据,需额外从Surface读取,复杂度较高。

内容的提问来源于stack exchange,提问作者gylns

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 13:17:18