Signatur
Beschreibung
Mit removeTrack() teilst du dem lokalen Ende einer RTCPeerConnection mit, dass über einen bestimmten RTCRtpSender keine Medien mehr gesendet werden sollen. Als Argument erwartet die Methode den Sender, also nicht den MediaStreamTrack. Den Sender bekommst du als Rückgabewert von addTrack() oder über getSenders().
Der Sender bleibt dabei in der Verbindung erhalten. Die Methode setzt sender.track auf null und ändert die Richtung (direction) des zugehörigen RTCRtpTransceiver: aus sendrecv wird recvonly, aus sendonly wird inactive. Weil sich damit die Sitzungsbeschreibung ändert, gilt die Verbindung als „negotiation needed“ und löst das Ereignis negotiationneeded aus. Erst nach einem neuen Angebot-/Antwort-Austausch (Offer/Answer) erfährt die Gegenseite von der Änderung. Dort wird der entfernte Track stummgeschaltet (mute), und im zugehörigen MediaStream feuert removetrack.
Typische Anwendungsfälle sind: Bildschirmfreigabe beenden, die Kamera abschalten, während der Ton weiterläuft, oder einen Track komplett aus einem Gespräch nehmen. Willst du nur die Quelle austauschen, zum Beispiel von der Frontkamera auf die Rückkamera wechseln, ist RTCRtpSender.replaceTrack() meist besser, weil dabei keine Neuverhandlung nötig ist.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $sender Pflicht | RTCRtpSender | Der RTCRtpSender, dessen Übertragung beendet werden soll. Er muss zu genau dieser RTCPeerConnection gehören. |
Rückgabewert
undefined).Beispiele
Kamera-Track entfernen und neu verhandeln
const pc = new RTCPeerConnection();
const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
// Sender merken – removeTrack() braucht den Sender, nicht den Track
const senders = stream.getTracks().map((track) => pc.addTrack(track, stream));
pc.addEventListener('negotiationneeded', async () => {
await pc.setLocalDescription();
// signaling.send({ description: pc.localDescription });
console.log('Neues Angebot erstellt:', pc.localDescription.type);
});
// Später: Video abschalten, Ton bleibt
const videoSender = senders.find((s) => s.track?.kind === 'video');
const videoTrack = videoSender.track;
pc.removeTrack(videoSender);
videoTrack.stop(); // Kamera wirklich freigeben
console.log(videoSender.track); // null
Bildschirmfreigabe über getSenders() beenden
const stopScreenShare = (pc, screenTrack) => {
const sender = pc.getSenders().find((s) => s.track === screenTrack);
if (!sender) return false;
pc.removeTrack(sender);
screenTrack.stop();
return true;
};
const pc = new RTCPeerConnection();
const screen = await navigator.mediaDevices.getDisplayMedia({ video: true });
const [screenTrack] = screen.getVideoTracks();
pc.addTrack(screenTrack, screen);
// Wenn der Nutzer die Freigabe über die Browser-Leiste beendet
screenTrack.addEventListener('ended', () => stopScreenShare(pc, screenTrack));
console.log(stopScreenShare(pc, screenTrack));
Auswirkung auf den Transceiver prüfen
const pc = new RTCPeerConnection();
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const sender = pc.addTrack(stream.getAudioTracks()[0], stream);
const transceiver = pc.getTransceivers().find((t) => t.sender === sender);
console.log(transceiver.direction);
pc.removeTrack(sender);
console.log(transceiver.direction);
console.log(pc.getSenders().includes(sender)); // Sender bleibt erhalten
// Wichtig · Fallstricke
- Sender statt Track übergeben:
pc.removeTrack(track)wirft einenTypeError. Gehört der Sender zu einer anderen Verbindung, wird einInvalidAccessErrorgeworfen. - Ist die Verbindung geschlossen (
signalingState === 'closed'), wird einInvalidStateErrorgeworfen. - Die Methode stoppt den Track nicht. Kamera und Mikrofon bleiben aktiv, und die Aufnahme-Anzeige im Browser leuchtet weiter, bis du
track.stop()aufrufst. - Ohne einen Handler für
negotiationneededund einen neuen Angebot-/Antwort-Austausch bemerkt die Gegenseite die Änderung nicht. - Der Transceiver bleibt bestehen. Ein späteres
addTrack()derselben Medienart kann ihn wiederverwenden. Wenn du ihn endgültig loswerden willst, nutzetransceiver.stop(). - Nur für einen Quellwechsel ist
sender.replaceTrack()effizienter, weil keine Neuverhandlung nötig ist. - Ältere Browser hatten stattdessen die veraltete Methode
removeStream(). Wenn du alte Versionen unterstützen musst, hilft adapter.js.