React.js+react-media-recorder:停止录制后关闭摄像头的问题解决
解决React Media Recorder停止录制后摄像头仍运行的问题
问题根源
你的代码存在两个核心问题:
- 重复获取媒体流:你在
status === "idle"时手动调用getUserMedia获取预览流,而react-media-recorder插件在启动录制时也会独立获取媒体流,导致两个流同时占用摄像头。停止录制时仅尝试停止自己的预览流,插件内部的流仍在运行,摄像头无法关闭。 - 无效的停止逻辑:你最初在
onStop里重新获取新流并停止,这和当前正在使用的摄像头流完全无关,自然无法关闭摄像头;后来尝试停止previewStream但未处理插件内部的流,仍有残留轨道在占用设备。
解决方案
使用插件内置的预览流管理功能,无需手动获取流,同时配置插件自动停止媒体轨道:
- 移除手动获取
previewStream的逻辑,直接使用useReactMediaRecorder返回的previewStream。 - 添加
stopTracksOnStop: true配置项,让插件在停止录制时自动停止所有媒体轨道。 - 调整组件渲染逻辑,使用插件提供的流做预览。
修改后的完整代码
import React, { useEffect, useRef} from "react"; import { useReactMediaRecorder } from "react-media-recorder"; const VideoPreview: React.FC<{ stream: MediaStream | null }> = ({ stream }) => { const videoRef = useRef<HTMLVideoElement>(null); useEffect(() => { if (videoRef.current && stream) { videoRef.current.srcObject = stream; } return () => { if (videoRef.current) { videoRef.current.srcObject = null; } }; }, [stream]); if (!stream) { return null; } return <video ref={videoRef} width={500} height={500} autoPlay playsInline />; }; const App: React.FC = () => { const { status, startRecording, stopRecording, mediaBlobUrl, clearBlobUrl, previewStream // 直接使用插件提供的预览流 } = useReactMediaRecorder({ video: true, stopTracksOnStop: true, // 停止录制时自动停止媒体轨道 onStop: () => { console.log("录制已停止"); }, }); const handleReset = () => { clearBlobUrl(); }; return ( <div className="m-16"> <> {status === "idle" && ( <button className="bg-yellow-300 mx-5 p-3" onClick={startRecording}> Start Recording </button> )} {(status === "recording" || status === "stopped") && ( <button className="bg-red-400 p-3 mx-5" onClick={stopRecording}> Stop Recording </button> )} <button className="bg-lime-500 p-3 mx-5" onClick={handleReset}> Reset Recording </button> </> {(status === "idle" || status === "recording") && ( <VideoPreview stream={previewStream} /> )} {mediaBlobUrl && ( <video src={mediaBlobUrl} className="m-5 w-88" controls autoPlay /> )} </div> ); }; export default App;
关键修改点说明
- 移除手动流获取:删除了
previewStream的useRef和对应的useEffect,改用插件返回的previewStream,避免重复占用摄像头。 - 启用自动停止轨道:
stopTracksOnStop: true会让插件在调用stopRecording时,自动遍历所有媒体轨道并调用track.stop(),彻底释放摄像头设备。 - 优化视频属性:给预览视频添加
playsInline属性,避免在移动端出现全屏播放的问题(可选,但提升用户体验)。
内容的提问来源于stack exchange,提问作者Kirushanthi
相关产品推荐
相关产品推荐

