TensorFlow.js配合React Web应用使用coco-ssd检测视频仅返回单次预测如何解决
问题核心原因
你当前的代码仅在依赖状态变更时触发一次预测,没有持续的帧检测循环,同时captureStream参数配置错误导致仅能捕获首帧,因此无法实现逐帧检测。
具体修改方案
- 新增帧循环控制和并发锁的ref,避免重复执行和内存泄漏
// 头部引入useCallback import React, { useEffect, useRef, useState, useCallback } from "react"; // 组件内新增以下ref const rafIdRef = useRef(null); const predictingRef = useRef(false);
- 修正
captureStream的参数,原来的0代表仅捕获静态首帧,改为需要的捕获帧率即可持续获取视频帧
// 找到原来的captureStream调用,修改为 _videoStream.srcObject = _video.captureStream(30);
- 新增预测循环逻辑,用
requestAnimationFrame实现播放过程中持续检测
// 组件内新增回调函数包裹预测逻辑 const runPredictionLoop = useCallback(async () => { // 未满足运行条件时继续循环等待 if (!videoPlaying || !streamReady || !models?.coco_ssd || !videoStreamRef.current || !canvasRef.current) { rafIdRef.current = requestAnimationFrame(runPredictionLoop); return; } // 避免上一次预测未完成时重复调用导致性能问题 if (predictingRef.current) { rafIdRef.current = requestAnimationFrame(runPredictionLoop); return; } try { predictingRef.current = true; const predictions = await models.coco_ssd.detect(videoStreamRef.current); console.log(predictions); // 此处添加canvas绘制边界框的逻辑即可 } catch (err) { console.error("预测失败", err); } finally { predictingRef.current = false; rafIdRef.current = requestAnimationFrame(runPredictionLoop); } }, [videoPlaying, streamReady, models]);
- 新增useEffect控制循环的启动和销毁
// 组件内新增useEffect useEffect(() => { if (videoPlaying && streamReady) { runPredictionLoop(); } // 组件卸载/状态变更时清除循环,避免内存泄漏 return () => { if (rafIdRef.current) { cancelAnimationFrame(rafIdRef.current); } }; }, [videoPlaying, streamReady, runPredictionLoop]);
- 可选优化:可以直接使用第一个video元素作为
detect方法的输入,不需要额外的第二个video中转流,减少资源占用。
内容的提问来源于stack exchange,提问作者hyprstack
相关产品推荐
相关产品推荐

