RTCPeerConnection: addTrack()-Methode
Baseline
Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since Januar 2020.
Die addTrack()-Methode des RTCPeerConnection-Interfaces fügt einen neuen Medientrack zu der Menge von Tracks hinzu, die an den anderen Peer übertragen werden sollen.
Hinweis:
Das Hinzufügen eines Tracks zu einer Verbindung löst eine Neuverhandlung aus, indem ein negotiationneeded-Ereignis ausgelöst wird.
Siehe Beginn der Verhandlung für Details.
Syntax
addTrack(track)
addTrack(track, stream1)
addTrack(track, stream1, stream2)
addTrack(track, stream1, stream2, /* …, */ streamN)
Parameter
track-
Ein
MediaStreamTrack-Objekt, das den Medientrack repräsentiert, der zur Peer-Verbindung hinzugefügt werden soll. stream1, …,streamNOptional-
Ein oder mehrere lokale
MediaStream-Objekte, zu denen der Track hinzugefügt werden soll.
Der angegebene track muss nicht unbedingt bereits Teil eines der angegebenen streams sein.
Stattdessen dienen die streams dazu, Tracks auf der Empfangsseite der Verbindung zu gruppieren und sicherzustellen, dass sie synchronisiert sind.
Alle Tracks, die auf der lokalen Seite der Verbindung zu demselben Stream hinzugefügt werden, befinden sich auch auf der entfernten Seite auf demselben Stream.
Rückgabewert
Das RTCRtpSender-Objekt, das verwendet wird, um die Mediendaten zu übertragen.
Hinweis:
Jeder RTCRtpSender ist mit einem RTCRtpReceiver gekoppelt, um einen RTCRtpTransceiver zu bilden.
Der zugehörige Receiver ist stummgeschaltet (was anzeigt, dass er keine Pakete liefern kann), bis und sofern nicht ein oder mehrere Streams von dem entfernten Peer zum Receiver hinzugefügt werden.
Ausnahmen
InvalidAccessErrorDOMException-
Wird ausgelöst, wenn der angegebene Track (oder alle seine zugrunde liegenden Streams) bereits Teil der
RTCPeerConnectionist. InvalidStateErrorDOMException-
Wird ausgelöst, wenn die
RTCPeerConnectiongeschlossen ist.
Hinweise zur Verwendung
>Tracks zu mehreren Streams hinzufügen
Nach dem track-Parameter können Sie optional ein oder mehrere MediaStream-Objekte angeben, zu denen der Track hinzugefügt werden soll.
Nur Tracks werden von einem Peer zum anderen gesendet, nicht Streams.
Da Streams für jeden Peer spezifisch sind, bedeutet das Angeben eines oder mehrerer Streams, dass der andere Peer automatisch einen entsprechenden Stream (oder Streams) auf der anderen Seite der Verbindung erstellt und dann den empfangenen Track zu diesen Streams hinzufügt.
Streamlose Tracks
Wenn keine Streams angegeben sind, ist der Track streamlos.
Das ist vollkommen akzeptabel, obwohl es dem entfernten Peer überlassen bleibt zu entscheiden, in welchen Stream der Track eingefügt werden soll, falls überhaupt.
Dies ist eine sehr gebräuchliche Art, addTrack() zu verwenden, wenn Sie viele Arten von einfachen Anwendungen erstellen, bei denen nur ein Stream benötigt wird.
Zum Beispiel, wenn Sie dem entfernten Peer nur einen einzigen Stream mit einem Audio- und einem Videotrack teilen, müssen Sie sich nicht darum kümmern, welcher Track in welchem Stream ist, daher können Sie es einfach dem Transceiver überlassen, dies für Sie zu handeln.
Hier ist ein Beispiel, dass eine Funktion zeigt, die getUserMedia() verwendet, um einen Stream von der Kamera und dem Mikrofon eines Benutzers zu erhalten, dann jeden Track aus dem Stream zur Peer-Verbindung hinzufügt, ohne einen Stream für jeden Track anzugeben:
async function openCall(pc) {
const gumStream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true,
});
for (const track of gumStream.getTracks()) {
pc.addTrack(track);
}
}
Das Ergebnis ist eine Menge von Tracks, die an den entfernten Peer gesendet werden, ohne Streamzuordnungen.
Der Handler für das track-Ereignis auf dem entfernten Peer ist dafür verantwortlich, zu bestimmen, welchem Stream jeder Track hinzugefügt wird, selbst wenn das bedeutet, dass sie alle demselben Stream hinzugefügt werden.
Der ontrack-Handler könnte so aussehen:
let inboundStream = null;
pc.ontrack = (ev) => {
if (ev.streams && ev.streams[0]) {
videoElem.srcObject = ev.streams[0];
} else {
if (!inboundStream) {
inboundStream = new MediaStream();
videoElem.srcObject = inboundStream;
}
inboundStream.addTrack(ev.track);
}
};
Hier fügt der track-Ereignishandler den Track dem ersten Stream hinzu, der vom Ereignis angegeben wird, falls ein Stream angegeben ist.
Andernfalls wird beim ersten Aufruf von ontrack ein neuer Stream erstellt und dem Videoelement zugeordnet, und dann der Track zu dem neuen Stream hinzugefügt.
Ab dann werden neue Tracks zu diesem Stream hinzugefügt.
Sie könnten auch einfach für jeden empfangenen Track einen neuen Stream erstellen:
pc.ontrack = (ev) => {
if (ev.streams && ev.streams[0]) {
videoElem.srcObject = ev.streams[0];
} else {
let inboundStream = new MediaStream(ev.track);
videoElem.srcObject = inboundStream;
}
};
Zuordnung von Tracks zu bestimmten Streams
Durch das Angeben eines Streams und das Ermöglichen, dass RTCPeerConnection Streams für Sie erstellt, wird die Zuordnung der Tracks zu den Streams automatisch von der WebRTC-Infrastruktur verwaltet.
Dies umfasst Dinge wie Änderungen der direction des Transceivers und das Anhalten von Tracks mit removeTrack().
Zum Beispiel könnte eine Anwendung diese Funktion verwenden, um das Kameraund Mikrofonsignal eines Gerätes über eine RTCPeerConnection zu einem entfernten Peer zu streamen:
async function openCall(pc) {
const gumStream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true,
});
for (const track of gumStream.getTracks()) {
pc.addTrack(track, gumStream);
}
}
Der entfernte Peer könnte dann einen track-Ereignishandler verwenden, der so aussieht:
pc.ontrack = ({ streams: [stream] }) => (videoElem.srcObject = stream);
Dies stellt den aktuellen Stream des Videoelements auf den ein, der den hinzugefügten Track enthält.
Wiederverwendete Sender
Diese Methode gibt entweder einen neuen RTCRtpSender oder eine vorhandene Instanz zur Wiederverwendung zurück.
Eine RTCRtpSender-Instanz ist nur zur Wiederverwendung geeignet, wenn sie die folgenden Kriterien erfüllt:
- Es ist kein Track bereits mit dem Sender assoziiert.
- Der mit dem Sender assoziierte
RTCRtpTransceiververfügt über einenRTCRtpReceiver, dessentrack-Eigenschaft einenMediaStreamTrackangibt, dessenkindmit demkinddes angegebenentrack-Parameters bei Aufruf vonRTCPeerConnection.addTrack()übereinstimmt. Dies stellt sicher, dass ein Transceiver nur Audio oder Video und niemals beides gleichzeitig verarbeitet. - Die
RTCRtpTransceiver.currentDirection-Eigenschaft ist nicht"stopped". - Der betrachtete
RTCRtpSenderwurde noch nie zum Senden von Daten verwendet. Wenn diecurrentDirectiondes Transceivers jemals"sendrecv"oder"sendonly"war, kann der Sender nicht wiederverwendet werden.
Wenn alle diese Kriterien erfüllt sind, wird der Sender wiederverwendet, was zu diesen Änderungen an dem bestehenden RTCRtpSender und seinem RTCRtpTransceiver führt:
- Der
RTCRtpSender'strackwird auf den angegebenen Track gesetzt. - Die Menge der mit dem Sender verbundenen Streams wird auf die Liste der in dieser Methode übergebenen Streams gesetzt,
stream1, …,streamN. - Der zugeordnete
RTCRtpTransceiverhat seinecurrentDirectionaktualisiert, um anzuzeigen, dass er sendet; wenn sein aktueller Wert"recvonly"ist, wird es"sendrecv", und wenn sein aktueller Wert"inactive"ist, wird es"sendonly".
Neue Sender
Wenn kein vorhandener Sender zur Wiederverwendung existiert, wird ein neuer erstellt. Dies führt auch zur Erstellung der damit verbundenen Objekte, die existieren müssen. Der Prozess der Erstellung eines neuen Senders führt zu diesen Änderungen:
- Der neue
RTCRtpSenderwird mit dem angegebenen Track und einer Menge von Stream(s) erstellt. - Ein neuer
RTCRtpReceiverwird mit einem neuenMediaStreamTrackals seinertrack-Eigenschaft erstellt (nicht der Track, der als Parameter beim Aufruf vonaddTrack()angegeben wurde). Daskinddieses Tracks wird auf daskinddes als Eingabeparameter bereitgestellten Tracks gesetzt. - Ein neuer
RTCRtpTransceiverwird erstellt und mit dem neuen Sender und Receiver verknüpft. - Die
directiondes neuen Transceivers wird auf"sendrecv"gesetzt. - Der neue Transceiver wird in die Menge der Transceiver der
RTCPeerConnectionaufgenommen.
Beispiele
Dieses Beispiel stammt aus dem im Artikel Signaling und Videoanrufe vorgestellten Code und dem zugehörigen Beispielcode.
Es stammt aus der dortigen handleVideoOfferMsg()-Methode, die aufgerufen wird, wenn eine Angebotsnachricht von dem entfernten Peer empfangen wird.
const mediaConstraints = {
audio: true, // We want an audio track
video: true, // And we want a video track
};
const desc = new RTCSessionDescription(sdp);
pc.setRemoteDescription(desc)
.then(() => navigator.mediaDevices.getUserMedia(mediaConstraints))
.then((stream) => {
previewElement.srcObject = stream;
stream.getTracks().forEach((track) => pc.addTrack(track, stream));
});
Dieser Code nimmt SDP, das vom entfernten Peer empfangen wurde, und konstruiert eine neue RTCSessionDescription zur Übergabe an setRemoteDescription().
Sobald dies erfolgreich ist, wird MediaDevices.getUserMedia() verwendet, um Zugriff auf die lokale Webcam und das Mikrofon zu erhalten.
Wenn das erfolgreich ist, wird der resultierende Stream als Quelle für ein <video>-Element zugewiesen, das durch die Variable previewElement referenziert wird.
Der letzte Schritt besteht darin, das lokale Video über die Peer-Verbindung an den Anrufer zu senden.
Dies erfolgt durch Hinzufügen jedes Tracks im Stream, indem über die von MediaStream.getTracks() zurückgegebene Liste iteriert und sie an addTrack() zusammen mit dem stream, dessen Bestandteil sie sind, übergeben werden.
Spezifikationen
| Specification |
|---|
| WebRTC: Real-Time Communication in Browsers> # dom-rtcpeerconnection-addtrack> |
Browser-Kompatibilität
Loading…