WebRTC中getUserMedia停止摄像头失效及通话挂断后关闭摄像头咨询
Hey there! Let's work through your two questions: stopping the camera after a call ends, and fixing the track.stop() not working in Chrome.
1. Properly Stopping Camera via getUserMedia
First off, localStream.getVideoTracks()[0].stop() is technically the right API call—but it often fails in Chrome because the media stream is still referenced by other objects (like your RTCPeerConnection or a <video> element displaying the feed). Chrome keeps the camera active as long as there's an active reference to the stream.
Here's the correct step-by-step approach:
- Remove all references to the stream first:
- If you've attached the stream to a video element, clear that binding:
const localVideo = document.getElementById('your-local-video-element'); if (localVideo.srcObject) localVideo.srcObject = null; - If you added the stream to an RTCPeerConnection, remove it (use the modern API if possible):
// For older PeerConnection implementations peerConnection.removeStream(localStream); // For modern browsers (recommended) localStream.getTracks().forEach(track => { peerConnection.removeTrack(track); });
- If you've attached the stream to a video element, clear that binding:
- Then stop the video tracks:
// Stop all video tracks (safer than targeting just index 0) localStream.getVideoTracks().forEach(track => track.stop()); // Clear the stream reference to free up resources localStream = null;
2. Full Workflow for Stopping Camera After Call Hangup
When ending a WebRTC call, you need to clean up all related resources to ensure the camera turns off properly:
- Close the RTCPeerConnection:
if (peerConnection) { peerConnection.close(); peerConnection = null; } - Clear the video element's stream:
const localVideo = document.getElementById('your-local-video-element'); if (localVideo.srcObject) localVideo.srcObject = null; - Stop all media tracks and clear references:
if (localStream) { // Stop both video and audio tracks if needed localStream.getTracks().forEach(track => track.stop()); localStream = null; }
Quick Optimization for Your Initial Code
Your current getUserMedia setup uses deprecated prefixed methods—switch to the modern promise-based API for better compatibility and cleaner code:
// Initialize camera with modern API async function startCamera() { try { const stream = await navigator.mediaDevices.getUserMedia({ video: true }); const localVideo = document.getElementById('your-local-video-element'); localVideo.srcObject = stream; // Store the stream globally for easy access later window.localStream = stream; } catch (error) { console.error('Failed to access camera:', error); } } // Helper function to stop camera completely function stopCamera() { // Clean up video element const localVideo = document.getElementById('your-local-video-element'); if (localVideo.srcObject) localVideo.srcObject = null; // Stop tracks and clear stream if (window.localStream) { window.localStream.getTracks().forEach(track => track.stop()); window.localStream = null; } // Clean up PeerConnection if exists if (window.peerConnection) { window.peerConnection.close(); window.peerConnection = null; } }
This should resolve the Chrome issue where the camera stays active—by ensuring no active references to the stream remain before stopping the tracks.
内容的提问来源于stack exchange,提问作者vivek dhamecha

