[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/de/docs/Web/API/WebRTC_API/Using_DTMF [Back]  [Original]

Verwendung von DTMF mit WebRTC - Web-APIs | MDN

Dieser Inhalt wurde automatisch aus dem Englischen bersetzt, und kann Fehler enthalten. Erfahre mehr ber dieses Experiment.

View in English Always switch to English

Verwendung von DTMF mit WebRTC

Um die Untersttzung von Audio-/Video-Konferenzen zu verbessern, untersttzt WebRTC das Senden von DTMF an den Remote-Teilnehmer auf einer RTCPeerConnection. Dieser Artikel bietet einen kurzen berblick auf hoher Ebene darber, wie DTMF ber WebRTC funktioniert, und liefert dann einen Leitfaden fr Entwickler, wie DTMF ber eine RTCPeerConnection gesendet werden kann. Das DTMF-System wird oft als "Tonwahl" bezeichnet, nach einem alten Handelsnamen fr das System.

WebRTC sendet DTMF-Codes nicht als Audiodaten. Stattdessen werden sie auerhalb des Bandes als RTP-Nutzdaten gesendet. Beachten Sie jedoch, dass es zwar mglich ist, DTMF mit WebRTC zu senden, es derzeit jedoch keine Mglichkeit gibt, eingehende DTMF zu erkennen oder zu empfangen. WebRTC ignoriert derzeit diese Nutzlasten; dies liegt daran, dass die DTMF-Untersttzung von WebRTC in erster Linie fr die Verwendung mit lteren Telefonsystemen gedacht ist, die auf DTMF-Tne angewiesen sind, um Aufgaben wie diese durchzufhren:

  • Telefonkonferenzsysteme
  • Mensysteme
  • Voicemail-Systeme
  • Eingabe von Kreditkarten oder anderen Zahlungsinformationen
  • Passcode-Eingabe

Hinweis: Obwohl das DTMF nicht an den Remote-Teilnehmer als Audio gesendet wird, knnen Browser als Teil ihrer Benutzererfahrung den entsprechenden Ton dem lokalen Benutzer vorspielen, da Benutzer typischerweise daran gewhnt sind, ihre Telefone die Tne hrbar abspielen zu hren.

In diesem Artikel

Senden von DTMF auf einer RTCPeerConnection

Eine bestimmte RTCPeerConnection kann mehrere Medienspuren haben, die gesendet oder empfangen werden. Wenn Sie DTMF-Signale bermitteln mchten, mssen Sie zuerst entscheiden, auf welcher Spur Sie diese senden mchten, da DTMF als eine Serie von auerhalb des Bandes befindlichen Nutzlasten ber den RTCRtpSender gesendet wird, der fr die bertragung der Daten dieser Spur an den anderen Teilnehmer verantwortlich ist.

Sobald die Spur ausgewhlt ist, knnen Sie von ihrem RTCRtpSender das RTCDTMFSender-Objekt erhalten, das Sie zum Senden von DTMF verwenden werden. Von dort aus knnen Sie RTCDTMFSender.insertDTMF() aufrufen, um DTMF-Signale zu senden, die ber die Spur an den anderen Teilnehmer gesendet werden sollen. Der RTCRtpSender sendet dann die Tne zusammen mit den Audiodaten der Spur als Pakete an den anderen Teilnehmer.

Jedes Mal, wenn ein Ton gesendet wird, empfngt die RTCPeerConnection ein tonechange-Ereignis mit einer tone-Eigenschaft, die angibt, welcher Ton gerade abgespielt wurde, was eine Gelegenheit bietet, beispielsweise Interface-Elemente zu aktualisieren. Wenn der Tonpuffer leer ist, was bedeutet, dass alle Tne gesendet wurden, wird ein tonechange-Ereignis mit seiner tone-Eigenschaft als "" (ein leerer String) an das Verbindungsobjekt geliefert.

Wenn Sie mehr darber erfahren mchten, wie dies funktioniert, lesen Sie RFC 3550: RTP: A Transport Protocol for Real-Time Applications und RFC 4733: RTP Payload for DTMF Digits, Telephony Tones, and Telephony Signals. Die Details, wie DTMF-Nutzlasten auf RTP behandelt werden, liegen auerhalb des Umfangs dieses Artikels. Stattdessen konzentrieren wir uns darauf, wie DTMF im Kontext einer RTCPeerConnection verwendet wird, indem wir untersuchen, wie ein Beispiel funktioniert.

Einfaches Beispiel

Dieses einfache Beispiel erstellt zwei RTCPeerConnections, etabliert eine Verbindung zwischen ihnen und wartet dann darauf, dass der Benutzer auf eine "Whlen" Schaltflche klickt. Wenn die Schaltflche geklickt wird, wird ein DTMF-String ber die Verbindung gesendet, indem RTCDTMFSender.insertDTMF() verwendet wird. Sobald die Tne bertragen wurden, wird die Verbindung geschlossen.

Hinweis: Dieses Beispiel ist offensichtlich etwas konstruiert, da normalerweise die beiden RTCPeerConnection-Objekte auf verschiedenen Gerten existieren wrden und das Signalisieren ber das Netzwerk stattfinden wrde, anstatt es wie hier inline verbunden zu sein.

HTML

Das HTML fr dieses Beispiel ist sehr einfach; es gibt nur drei wichtige Elemente:

  • Ein <audio>-Element, um das Audio wiederzugeben, das von der RTCPeerConnection, die "angerufen" wird, empfangen wird.
  • Ein <button>-Element, um das Erstellen und Verbinden der beiden RTCPeerConnection-Objekte zu starten, und dann die DTMF-Tne zu senden.
  • Ein <div>, das den Log-Text empfngt und anzeigt, um Statusinformationen zu zeigen.
html
<p>
  This example demonstrates the use of DTMF in WebRTC. Note that this example is
  "cheating" by generating both peers in one code stream, rather than having
  each be a truly separate entity.
</p>

<audio id="audio" autoplay controls></audio><br />
<button name="dial" id="dial">Dial</button>

<div class="log"></div>

JavaScript

Werfen wir als nchstes einen Blick auf den JavaScript-Code. Beachten Sie, dass der Prozess des Verbindungsaufbaus hier etwas konstruiert ist; normalerweise wrden Sie nicht beide Enden der Verbindung im selben Dokument erstellen.

Globale Variablen

Zuerst legen wir globale Variablen fest.

js
let dialString = "12024561111";

let callerPC = null;
let receiverPC = null;
let dtmfSender = null;

let hasAddTrack = false;

let mediaConstraints = {
  audio: true,
  video: false,
};

Diese sind in der Reihenfolge:

dialString

Der DTMF-String, den der Anrufer senden wird, wenn die "Whlen"-Schaltflche geklickt wird.

callerPC und receiverPC

Die RTCPeerConnection-Objekte, die den Anrufer bzw. den Empfnger darstellen. Diese werden initialisiert, wenn der Anruf startet, in unserer connectAndDial()-Funktion, wie im Abschnitt Starten des Verbindungsprozesses unten gezeigt.

dtmfSender

Das RTCDTMFSender-Objekt fr die Verbindung. Dieses wird whrend des Verbindungsaufbaus in der gotStream()-Funktion erhalten, die im Abschnitt Hinzufgen des Audios zur Verbindung gezeigt wird.

hasAddTrack

Da einige Browser RTCPeerConnection.addTrack() noch nicht implementiert haben und daher die Verwendung der veralteten addStream()-Methode erforderlich machen, verwenden wir dieses Boolean, um festzustellen, ob der Benutzeragent addTrack() untersttzt; wenn nicht, werden wir zu addStream() zurckfallen. Dies wird herausgefunden in connectAndDial(), wie im Abschnitt Starten des Verbindungsprozesses gezeigt.

mediaConstraints

Ein Objekt, das die Einschrnkungen angibt, die beim Starten der Verbindung verwendet werden sollen. Wir mchten eine reine Audioverbindung, daher ist video auf false, whrend audio auf true gesetzt ist.

Initialisierung

Wir holen Referenzen auf die Whltaste und die Log-Ausgabefeldelemente und verwenden addEventListener(), um einen Ereignis-Listener zur Whltaste hinzuzufgen, so dass das Klicken darauf die connectAndDial()-Funktion aufruft, um den Verbindungsprozess zu starten.

js
const dialButton = document.querySelector("#dial");
const logElement = document.querySelector(".log");
dialButton.addEventListener("click", connectAndDial);

Starten des Verbindungsprozesses

Wenn auf die Whlen-Schaltflche geklickt wird, wird connectAndDial() aufgerufen. Dies beginnt mit dem Aufbau der WebRTC-Verbindung zur Vorbereitung auf das Senden der DTMF-Codes.

js
function connectAndDial() {
  callerPC = new RTCPeerConnection();

  hasAddTrack = callerPC.addTrack !== undefined;

  callerPC.onicecandidate = handleCallerIceEvent;
  callerPC.onnegotiationneeded = handleCallerNegotiationNeeded;
  callerPC.oniceconnectionstatechange = handleCallerIceConnectionStateChange;
  callerPC.onsignalingstatechange = handleCallerSignalingStateChangeEvent;
  callerPC.onicegatheringstatechange = handleCallerGatheringStateChangeEvent;

  receiverPC = new RTCPeerConnection();
  receiverPC.onicecandidate = handleReceiverIceEvent;

  if (hasAddTrack) {
    receiverPC.ontrack = handleReceiverTrackEvent;
  } else {
    receiverPC.onaddstream = handleReceiverAddStreamEvent;
  }

  navigator.mediaDevices
    .getUserMedia(mediaConstraints)
    .then(gotStream)
    .catch((err) => log(err.message));
}

Nachdem die RTCPeerConnection fr den Anrufer (callerPC) erstellt wurde, prfen wir, ob sie die addTrack()-Methode hat. Wenn ja, setzen wir hasAddTrack auf true; andernfalls setzen wir es auf false. Diese Variable lsst das Beispiel sogar auf Browsern arbeiten, die die neuere addTrack()-Methode noch nicht implementiert haben; wir werden dies tun, indem wir auf die ltere addStream()-Methode zurckfallen.

Als nchstes werden die Ereignis-Handler fr den Anrufer festgelegt. Wir werden diese spter im Detail behandeln.

Dann wird eine zweite RTCPeerConnection, die das empfangende Ende des Anrufs darstellt, erstellt und in receiverPC gespeichert; auch ihr onicecandidate-Ereignis-Handler wird eingerichtet.

Wenn addTrack() untersttzt wird, richten wir den ontrack-Ereignis-Handler des Empfngers ein; andernfalls richten wir onaddstream ein. Die track- und addstream-Ereignisse werden gesendet, wenn Medien zur Verbindung hinzugefgt werden.

Schlielich rufen wir getUserMedia() auf, um Zugriff auf das Mikrofon des Anrufers zu erhalten. Wenn dies erfolgreich ist, wird die Funktion gotStream() aufgerufen, andernfalls loggen wir den Fehler, weil der Anruf fehlgeschlagen ist.

Hinzufgen des Audios zur Verbindung

Wie oben erwhnt, wird gotStream() aufgerufen, wenn der Audioeingang vom Mikrofon erhalten wird. Ihre Aufgabe ist es, den Stream zu erstellen, der an den Empfnger gesendet wird, damit der tatschliche Prozess des Sendens beginnen kann. Sie erhlt auch Zugriff auf den RTCDTMFSender, den wir zum Ausgeben von DTMF auf der Verbindung verwenden werden.

js
function gotStream(stream) {
  log("Got access to the microphone.");

  let audioTracks = stream.getAudioTracks();

  if (hasAddTrack) {
    if (audioTracks.length > 0) {
      audioTracks.forEach((track) => callerPC.addTrack(track, stream));
    }
  } else {
    log(
      "Your browser doesn't support RTCPeerConnection.addTrack(). Falling " +
        "back to the <strong>deprecated</strong> addStream() method",
    );
    callerPC.addStream(stream);
  }

  if (callerPC.getSenders) {
    dtmfSender = callerPC.getSenders()[0].dtmf;
  } else {
    log(
      "Your browser doesn't support RTCPeerConnection.getSenders(), so " +
        "falling back to use <strong>deprecated</strong> createDTMFSender() " +
        "instead.",
    );
    dtmfSender = callerPC.createDTMFSender(audioTracks[0]);
  }

  dtmfSender.ontonechange = handleToneChangeEvent;
}

Nachdem audioTracks als Liste der Audio-Tracks des Streams vom Mikrofon des Benutzers festgelegt wurde, ist es Zeit, die Medien zur RTCPeerConnection des Anrufers hinzuzufgen. Wenn addTrack() auf der RTCPeerConnection verfgbar ist, fgen wir jeden der Audiotracks des Streams, einzeln, zur Verbindung hinzu, indem wir RTCPeerConnection.addTrack() verwenden. Andernfalls rufen wir RTCPeerConnection.addStream() auf, um den Stream als eine Einheit zum Anruf hinzuzufgen.

Als nchstes prfen wir, ob die Methode RTCPeerConnection.getSenders() implementiert ist. Wenn ja, rufen wir sie auf callerPC auf und holen den ersten Eintrag in der zurckgegebenen Liste der Sender; dies ist der RTCRtpSender, der fr das bertragen von Daten fr den ersten Audiotrack des Anrufs verantwortlich ist (was der Track ist, auf dem wir DTMF senden werden). Anschlieend holen wir die RTCRtpSender-Eigenschaft dtmf, die ein RTCDTMFSender-Objekt ist, das DTMF auf der Verbindung vom Anrufer zum Empfnger senden kann.

Wenn getSenders() nicht verfgbar ist, rufen wir stattdessen RTCPeerConnection.createDTMFSender() auf, um das RTCDTMFSender-Objekt zu erhalten. Obwohl diese Methode veraltet ist, untersttzt dieses Beispiel sie als Fallback, damit ltere Browser (und solche, die noch nicht aktualisiert sind, um die aktuelle WebRTC-DTMF-API zu untersttzen) das Beispiel ausfhren knnen.

Schlielich setzen wir den ontonechange-Ereignis-Handler des DTMF-Senders, damit wir jedes Mal benachrichtigt werden, wenn ein DTMF-Ton fertig gespielt wurde.

Sie finden die Log-Funktion am Ende der Dokumentation.

Wenn ein Ton fertig abgespielt ist

Jedes Mal, wenn ein DTMF-Ton fertig abgespielt wird, wird ein tonechange-Ereignis an callerPC geliefert. Der Ereignis-Listener fr diese ist als Funktion handleToneChangeEvent() implementiert.

js
function handleToneChangeEvent(event) {
  if (event.tone !== "") {
    log(`Tone played: ${event.tone}`);
  } else {
    log("All tones have played. Disconnecting.");
    callerPC.getLocalStreams().forEach((stream) => {
      stream.getTracks().forEach((track) => {
        track.stop();
      });
    });
    receiverPC.getLocalStreams().forEach((stream) => {
      stream.getTracks().forEach((track) => {
        track.stop();
      });
    });

    audio.pause();
    audio.srcObject = null;
    receiverPC.close();
    callerPC.close();
  }
}

Das tonechange-Ereignis wird sowohl verwendet, um anzuzeigen, wann ein einzelner Ton gespielt wurde, als auch wann alle Tne fertig gespielt wurden. Die tone-Eigenschaft des Ereignisses ist ein String, der angibt, welcher Ton gerade fertig gespielt wurde. Wenn alle Tne fertig gespielt wurden, ist tone ein leerer String; in diesem Fall ist RTCDTMFSender.toneBuffer leer.

In diesem Beispiel loggen wir auf dem Bildschirm, welcher Ton gerade fertig gespielt wurde. In einer fortgeschritteneren Anwendung knnten Sie die Benutzeroberflche aktualisieren, zum Beispiel, um anzuzeigen, welcher Ton aktuell gespielt wird.

Andererseits, wenn der Tonpuffer leer ist, ist unser Beispiel darauf ausgelegt, den Anruf zu trennen. Dies geschieht, indem wir jeden Stream sowohl beim Anrufer als auch beim Empfnger stoppen, indem wir ber jede Track-Liste von RTCPeerConnection iterieren (wie sie durch ihre getTracks()-Methode zurckgegeben wird) und jede Track's stop()-Methode aufrufen.

Sobald die Medien-Tracks sowohl des Anrufers als auch des Empfngers alle gestoppt sind, pausieren wir das <audio>-Element und setzen dessen srcObject auf null. Dies trennt den Audiostream vom <audio>-Element.

Dann schlielich wird jede RTCPeerConnection durch Aufrufen ihrer close()-Methode geschlossen.

Hinzufgen von Kandidaten zum Anrufer

Wenn die RTCPeerConnection-ICE-Schicht des Anrufers einen neuen Kandidaten zur Vorschlag hat, gibt sie ein icecandidate-Ereignis an callerPC aus. Der icecandidate-Ereignis-Handler ist dafr zustndig, den Kandidaten an den Empfnger zu bermitteln. In unserem Beispiel kontrollieren wir sowohl den Anrufer als auch den Empfnger direkt, so dass wir den Kandidaten einfach direkt an den Empfnger hinzufgen knnen, indem wir seine addIceCandidate()-Methode aufrufen. Das wird von handleCallerIceEvent() gehandhabt:

js
function handleCallerIceEvent(event) {
  if (event.candidate) {
    log(`Adding candidate to receiver: ${event.candidate.candidate}`);

    receiverPC
      .addIceCandidate(new RTCIceCandidate(event.candidate))
      .catch((err) => log(`Error adding candidate to receiver: ${err}`));
  } else {
    log("Caller is out of candidates.");
  }
}

Wenn das icecandidate-Ereignis eine nicht-null candidate-Eigenschaft hat, erstellen wir ein neues RTCIceCandidate-Objekt aus dem event.candidate-String und "bermitteln" es an den Empfnger, indem wir receiverPC.addIceCandidate() aufrufen und den neuen RTCIceCandidate als Eingabe bereitstellen. Wenn addIceCandidate() fehlschlgt, gibt die catch()-Klausel den Fehler in unser Log-Feld aus.

Wenn event.candidate null ist, bedeutet das, dass keine weiteren Kandidaten verfgbar sind, und wir loggen diese Information.

Whlen, sobald die Verbindung geffnet ist

Unser Design erfordert, dass beim Herstellen der Verbindung sofort der DTMF-String gesendet wird. Um dies zu erreichen, berwachen wir, dass der Anrufer ein iceconnectionstatechange-Ereignis erhlt. Dieses Ereignis wird gesendet, wenn eine der vielen nderungen am Zustand des ICE-Verbindungsprozesses auftritt, einschlielich der erfolgreichen Herstellung einer Verbindung.

js
function handleCallerIceConnectionStateChange() {
  log(`Caller's connection state changed to ${callerPC.iceConnectionState}`);
  if (callerPC.iceConnectionState === "connected") {
    log(`Sending DTMF: "${dialString}"`);
    dtmfSender.insertDTMF(dialString, 400, 50);
  }
}

Das iceconnectionstatechange-Ereignis enthlt nicht tatschlich den neuen Zustand, daher lesen wir den aktuellen Zustand des Verbindungsprozesses aus der RTCPeerConnection.iceConnectionState-Eigenschaft von callerPC. Nachdem wir den neuen Zustand geloggt haben, prfen wir, ob der Zustand "connected" ist. Wenn ja, loggen wir, dass wir kurz davor sind, den DTMF zu senden, und dann rufen wir dtmf.insertDTMF() auf, um den DTMF auf dem gleichen Track wie die Audiodaten zu senden, und die Methode auf dem RTCDTMFSender-Objekt, das wir zuvor gespeichert haben in dtmfSender.

Unser Aufruf von insertDTMF() gibt nicht nur den zu sendenden DTMF an (dialString), sondern auch die Lnge jedes Tons in Millisekunden (400 ms) und die Zeit zwischen den Tnen (50 ms).

Die Verbindung verhandeln

Wenn die anrufende RTCPeerConnection beginnt, Medien zu empfangen (nachdem der Stream des Mikrofons hinzugefgt wurde), erhlt der Anrufer ein negotiationneeded-Ereignis, das ihn darber informiert, dass es an der Zeit ist, die Verbindung mit dem Empfnger zu verhandeln. Wie zuvor erwhnt, ist unser Beispiel aufgrund der direkten Kontrolle sowohl des Anrufers als auch des Empfngers etwas vereinfacht, sodass handleCallerNegotiationNeeded() in der Lage ist, die Verbindung schnell zu konstruieren, indem es Methoden fr sowohl den Anrufer als auch den Empfnger aufruft, wie unten gezeigt.

js
// Offer to receive audio but not video
const constraints = { audio: true, video: false };

async function handleCallerNegotiationNeeded() {
  log("Negotiating");
  try {
    const stream = await navigator.mediaDevices.getUserMedia(constraints);
    for (const track of stream.getTracks()) {
      pc.addTrack(track, stream);
    }
    const offer = await callerPC.createOffer();
    log(`Setting caller's local description: ${offer.sdp}`);
    await callerPC.setLocalDescription(offer);
    log("Setting receiver's remote description to the same as caller's local");
    await receiverPC.setRemoteDescription(callerPC.localDescription);
    log("Creating answer");
    const answer = await receiverPC.createAnswer();
    log(`Setting receiver's local description to ${answer.sdp}`);
    await receiverPC.setLocalDescription(answer);
    log("Setting caller's remote description to match");
    await callerPC.setRemoteDescription(receiverPC.localDescription);
  } catch (err) {
    log(`Error during negotiation: ${err.message}`);
  }
}

Da die verschiedenen Methoden, die an der Verhandlung der Verbindung beteiligt sind, Promises zurckgeben, knnen wir sie so zusammenketteln:

  1. Rufen Sie callerPC.createOffer() auf, um ein Angebot zu erhalten.
  2. Dann nehmen Sie das Angebot und setzen Sie die lokale Beschreibung des Anrufers auf das Angebot, indem Sie callerPC.setLocalDescription() aufrufen.
  3. Dann "bermitteln" Sie das Angebot an den Empfnger, indem Sie receiverPC.setRemoteDescription() aufrufen. Dies konfiguriert den Empfnger, sodass er wei, wie der Anrufer konfiguriert ist.
  4. Dann erstellt der Empfnger eine Antwort, indem er receiverPC.createAnswer() aufruft.
  5. Dann setzt der Empfnger seine lokale Beschreibung auf die neu erstellte Antwort, indem er receiverPC.setLocalDescription() aufruft.
  6. Dann wird die Antwort an den Anrufer "bermittelt", indem callerPC.setRemoteDescription() aufgerufen wird. Dies lsst den Anrufer wissen, wie der Empfnger konfiguriert ist.
  7. Wenn zu irgendeinem Zeitpunkt ein Fehler auftritt, gibt die catch()-Klausel eine Fehlermeldung an das Log aus.

Verfolgen anderer Statusnderungen

Wir knnen auch nderungen am Signalisierungsstatus (durch Akzeptieren von signalingstatechange-Ereignissen) und dem ICE-Sammelstatus (durch Akzeptieren von icegatheringstatechange-Ereignissen) berwachen. Wir verwenden diese fr nichts, daher loggen wir sie einfach. Wir htten diese Ereignis-Listener berhaupt nicht einrichten mssen.

js
function handleCallerSignalingStateChangeEvent() {
  log(`Caller's signaling state changed to ${callerPC.signalingState}`);
}

function handleCallerGatheringStateChangeEvent() {
  log(`Caller's ICE gathering state changed to ${callerPC.iceGatheringState}`);
}

Hinzufgen von Kandidaten zum Empfnger

Wenn die RTCPeerConnection-ICE-Schicht des Empfngers einen neuen Kandidaten zur Vorschlag hat, gibt sie ein icecandidate-Ereignis an receiverPC aus. Der icecandidate-Ereignis-Handler ist dafr zustndig, den Kandidaten an den Anrufer zu bermitteln. In unserem Beispiel kontrollieren wir sowohl den Anrufer als auch den Empfnger direkt, so dass wir den Kandidaten einfach direkt an den Anrufer hinzufgen knnen, indem wir seine addIceCandidate()-Methode aufrufen. Das wird von handleReceiverIceEvent() gehandhabt.

Dieser Code ist analog zum icecandidate-Ereignis-Handler fr den Anrufer, wie im Abschnitt Hinzufgen von Kandidaten zum Anrufer gezeigt.

js
function handleReceiverIceEvent(event) {
  if (event.candidate) {
    log(`Adding candidate to caller: ${event.candidate.candidate}`);

    callerPC
      .addIceCandidate(new RTCIceCandidate(event.candidate))
      .catch((err) => log(`Error adding candidate to caller: ${err}`));
  } else {
    log("Receiver is out of candidates.");
  }
}

Wenn das icecandidate-Ereignis eine nicht-null candidate-Eigenschaft hat, erstellen wir ein neues RTCIceCandidate-Objekt aus dem event.candidate-String und liefern es an den Anrufer, indem wir es in callerPC.addIceCandidate() bergeben. Wenn addIceCandidate() fehlschlgt, gibt die catch()-Klausel den Fehler in das Logfeld aus.

Wenn event.candidate null ist, bedeutet das, dass keine weiteren Kandidaten verfgbar sind, und wir loggen diese Information.

Hinzufgen von Medien zum Empfnger

Wenn der Empfnger beginnt, Medien zu empfangen, wird ein Ereignis an die RTCPeerConnection des Empfngers, receiverPC, geliefert. Wie im Abschnitt Starten des Verbindungsprozesses erklrt, verwendet die aktuelle WebRTC-Spezifikation das track-Ereignis dafr. Da einige Browser noch nicht aktualisiert wurden, um dies zu untersttzen, mssen wir auch das addstream-Ereignis behandeln. Dies wird in den Methoden handleReceiverTrackEvent() und handleReceiverAddStreamEvent() unten gezeigt.

js
function handleReceiverTrackEvent(event) {
  audio.srcObject = event.streams[0];
}

function handleReceiverAddStreamEvent(event) {
  audio.srcObject = event.stream;
}

Das track-Ereignis enthlt eine streams-Eigenschaft, die ein Array der Streams enthlt, in denen sich der Track befindet (ein Track kann Teil vieler Streams sein). Wir nehmen den ersten Stream und hngen ihn an das <audio>-Element.

Das addstream-Ereignis enthlt eine stream-Eigenschaft, die einen einzelnen Stream angibt, der zum Track hinzugefgt wurde. Wir hngen ihn an das <audio>-Element.

Logging

Eine einfache log()-Funktion wird im gesamten Code verwendet, um Text an ein <div>-Feld anzuhngen, das Status und Fehler an den Benutzer anzeigt.

js
function log(msg) {
  logElement.innerText += `${msg}\n`;
}

Ergebnis

Sie knnen dieses Beispiel hier ausprobieren. Wenn Sie auf die "Whlen"-Schaltflche klicken, sollten Sie eine Reihe von Log-Nachrichten ausgeben sehen; dann beginnt das Whlen. Wenn Ihr Browser die Tne als Teil ihrer Benutzererfahrung hrbar abspielt, sollten Sie sie hren, whrend sie bertragen werden.

Sobald die bertragung der Tne abgeschlossen ist, wird die Verbindung geschlossen. Sie knnen erneut auf "Whlen" klicken, um die Verbindung wiederherzustellen und die Tne zu senden.

Siehe auch


Web Proxy Viewer  |  New URL  |  Original Page