调用track.stop无法关闭设备摄像头,指示灯常亮该如何解决
问题核心原因
你代码里的startStreaming函数重复调用了两次getUserMedia:
- 第一次调用
navigator.mediaDevices.getUserMedia(constraints).then(gotStream).then(gotDevices).catch(handleError)没有把返回的媒体流赋值给cameraStream变量,这个流没有被任何变量引用,后续stopStreaming根本找不到它,也没法停止,所以摄像头会一直被这个漏管的流占用,指示灯常亮。 - 第二次调用是在下方
if (mediaSupport && null == cameraStream)分支内,返回的流赋值给了cameraStream,是唯一能被stopStreaming控制的流。
另外你现有的stopStreaming只停止了索引为0的轨道,如果存在多个音视频轨道也会出现遗漏。
修复方案
1. 清理startStreaming的重复逻辑
删掉函数里第一次多余的getUserMedia调用,修改后代码如下:
function startStreaming() { if (cameraStream) { cameraStream.getTracks().forEach(track => track.stop()); stream.srcObject = null; cameraStream = null; } const mediaSupport = 'mediaDevices' in navigator; if (!mediaSupport) { alert('Your browser does not support media devices.'); return; } const videoSource = videoSelect.value; const constraints = { video: { deviceId: videoSource ? {exact: videoSource} : undefined } }; navigator.mediaDevices.getUserMedia(constraints) .then(function (mediaStream) { // 新增判断:如果模态框已经关闭,直接终止流不继续执行 if (!$('#photoStudio').is(':visible')) { mediaStream.getTracks().forEach(track => track.stop()); return; } cameraStream = mediaStream; stream.srcObject = mediaStream; stream.play(); }) .then(gotDevices) .catch(handleError); }
2. 优化stopStreaming的轨道停止逻辑
遍历所有媒体轨道全部停止,同时清空video元素的流引用:
function stopStreaming() { if (cameraStream) { // 停止所有轨道,不区分音视频、不依赖索引 cameraStream.getTracks().forEach(track => track.stop()); // 清空video的流引用,彻底释放资源 if (stream) { stream.srcObject = null; } cameraStream = null; } }
额外注意点
getUserMedia是异步API,如果用户打开模态框后立刻关闭,可能stopStreaming执行时流还没返回赋值给cameraStream,等异步回调返回后还是会启动摄像头。上面修改后的startStreaming里已经新增了模态框可见性判断,避免这种异步时序问题。
内容的提问来源于stack exchange,提问作者user2399035
相关产品推荐
相关产品推荐

