Start · Sprachen · JavaScript · Referenz · RTCRtpSender.replaceTrack()

RTCRtpSender.replaceTrack()

Methode

Ersetzt die Spur, die ein <code>RTCRtpSender</code> gerade sendet, durch eine neue <code>MediaStreamTrack</code> oder <code>null</code>, ohne die Verbindung neu auszuhandeln.

seit JavaScript Baseline: alle modernen Browser (Chrome 65+, Firef Kategorie: webapi

Signatur

RTCRtpSender.prototype.replaceTrack(newTrack)

Beschreibung

replaceTrack() tauscht die Medienquelle eines bestehenden RTCRtpSender im laufenden Betrieb aus. Typische Fälle sind der Wechsel zwischen Front- und Rückkamera, das Umschalten von Kamera auf Bildschirmfreigabe oder der Wechsel des Mikrofons. Die Gegenseite empfängt die neuen Medien nahtlos über denselben Transceiver.

Der große Vorteil gegenüber removeTrack() und anschließendem addTrack(): Es ist keine neue SDP-Aushandlung nötig. Es wird also kein negotiationneeded-Ereignis ausgelöst und kein Offer/Answer-Austausch über den Signalisierungskanal. Das spart Zeit und vermeidet Aussetzer.

Die neue Spur muss dieselbe kind haben wie die bisherige ("audio" oder "video"). Mit null hört der Sender auf zu senden, ohne dass der Transceiver entfernt wird. So lässt sich z. B. „Kamera aus“ umsetzen, und die Spur kann später wieder eingesetzt werden.

Parameter

Name Typ Default Beschreibung
$newTrack Pflicht MediaStreamTrack | null Die neue Spur, die gesendet werden soll. Sie muss dieselbe kind wie die bisherige Spur haben. Mit null wird das Senden beendet, der Sender bleibt aber bestehen.

Rückgabewert

Typ
Promise<undefined>
Beschreibung
Ein Promise, das erfüllt wird, sobald die Spur ersetzt wurde. Bei einem Fehler wird es verworfen, z. B. mit InvalidModificationError (neue Aushandlung wäre nötig), InvalidStateError (Verbindung geschlossen) oder TypeError (falsche kind).

Beispiele

Zwischen Front- und Rückkamera wechseln

const pc = new RTCPeerConnection();
const stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'user' } });
const [videoTrack] = stream.getVideoTracks();
pc.addTrack(videoTrack, stream);

const switchCamera = async (facingMode) => {
  const newStream = await navigator.mediaDevices.getUserMedia({ video: { facingMode } });
  const [newTrack] = newStream.getVideoTracks();
  const sender = pc.getSenders().find((s) => s.track?.kind === 'video');
  const oldTrack = sender.track;
  await sender.replaceTrack(newTrack);
  oldTrack?.stop(); // alte Kamera freigeben
  console.log('Kamera gewechselt:', newTrack.label);
};

await switchCamera('environment');
Kamera gewechselt: Rückkamera

Bildschirmfreigabe statt Kamera senden

const shareScreen = async (pc) => {
  const screen = await navigator.mediaDevices.getDisplayMedia({ video: true });
  const [screenTrack] = screen.getVideoTracks();
  const sender = pc.getSenders().find((s) => s.track?.kind === 'video');
  const cameraTrack = sender.track;

  await sender.replaceTrack(screenTrack);

  // Beendet der Nutzer die Freigabe über die Browser-UI, zurück zur Kamera
  screenTrack.addEventListener('ended', async () => {
    await sender.replaceTrack(cameraTrack);
    console.log('Zurück zur Kamera');
  });
};

Kamera stummschalten ohne Neuverhandlung

const toggleVideo = async (sender, track, enabled) => {
  try {
    await sender.replaceTrack(enabled ? track : null);
    console.log(enabled ? 'Video an' : 'Video aus');
  } catch (err) {
    console.error('replaceTrack fehlgeschlagen:', err.name);
  }
};

// const sender = pc.getSenders()[0];
// await toggleVideo(sender, cameraTrack, false);
Video aus

// Wichtig · Fallstricke

  • Gleiche Art nötig: Eine Audio-Spur kann keine Video-Spur ersetzen und umgekehrt. Das führt zu einem TypeError.
  • Alte Spur nicht automatisch gestoppt: replaceTrack() beendet die bisherige Spur nicht. Rufe oldTrack.stop() selbst auf, sonst bleiben Kamera oder Mikrofon aktiv (inklusive Aufnahme-Anzeige des Browsers).
  • Neue Parameter: Weichen Auflösung oder Bildrate stark ab, oder bräuchte die neue Spur einen anderen Codec, kann das Promise mit InvalidModificationError verworfen werden. Dann bleibt nur removeTrack()/addTrack() mit neuer Aushandlung.
  • Lokale Vorschau: Das lokale <video>-Element wird nicht automatisch aktualisiert. Setze srcObject selbst neu.
  • null vs. track.enabled = false: Mit enabled = false werden schwarze Bilder bzw. Stille weitergesendet, mit null wird gar nichts gesendet.
  • Wird in allen modernen Browsern unterstützt. Ältere Safari-Versionen (vor 11) und der alte Edge hatten Einschränkungen.