Echtzeitkommunikation mit WebRTC

1. Einführung

WebRTC ist ein Open-Source-Projekt zur Echtzeitkommunikation von Audio, Video und Daten in webbasierten und systemeigenen Apps.

WebRTC bietet mehrere JavaScript APIs. Klicken Sie auf die Links, um Demos anzusehen.

Wo kann ich WebRTC verwenden?

In Firefox, Opera und in Chrome auf Computern und Android-Geräten WebRTC ist auch für native Apps auf iOS und Android verfügbar.

Was ist Signalisierung?

WebRTC verwendet RTCPeerConnection für die Kommunikation von Streamingdaten zwischen Browsern, benötigt aber auch einen Mechanismus, um die Kommunikation zu koordinieren und Kontrollnachrichten zu senden. Dieser Prozess wird als Signalisierung bezeichnet. Signalisierungsmethoden und -protokolle werden nicht durch WebRTC angegeben. In diesem Codelab verwenden Sie Socket.IO für das Messaging. Es gibt jedoch viele Alternativen.

Was sind STUN und Turn?

WebRTC ist auf Peer-to-Peer-Verbindungen ausgelegt, sodass Nutzer auf möglichst direkter Route eine Verbindung herstellen können. WebRTC ist jedoch für reale Netzwerke konzipiert: Clientanwendungen müssen NAT-Gateways und Firewalls durchlaufen und Peer-to-Peer-Netzwerke benötigen Fallbacks, falls die direkte Verbindung fehlschlägt. Im Rahmen dieses Prozesses verwenden die WebRTC APIs STUN-Server, um die IP-Adresse Ihres Computers abzurufen, und Turn-Server, die als Relay-Server fungieren, falls die Peer-to-Peer-Kommunikation fehlschlägt. Weitere Informationen zu WebRTC in der realen Welt

Ist WebRTC sicher?

Die Verschlüsselung ist für alle WebRTC-Komponenten obligatorisch und die zugehörigen JavaScript APIs können nur von sicheren Quellen (HTTPS oder localhost) verwendet werden. Signalisierungsmechanismen werden nicht durch WebRTC-Standards definiert. Es liegt also an Ihnen, sichere Protokolle zu verwenden.

2. Übersicht

Erstellen Sie eine App, um Videos zu empfangen, Schnappschüsse mit Ihrer Webcam aufzunehmen und sie Peer-to-Peer über WebRTC zu teilen. Sie lernen dabei, die Core WebRTC APIs zu verwenden und einen Messaging-Server mit Node.js einzurichten.

Lerninhalte

  • Video von deiner Webcam aufnehmen
  • Video mit RTCPeerConnection streamen
  • Daten mit RTCDataChannel streamen
  • Signalisierungsdienst einrichten, um Nachrichten auszutauschen
  • Peer-Verbindung und Signalisierung kombinieren
  • Foto aufnehmen und über einen Datenkanal teilen

Voraussetzungen

  • Chrome 47 oder höher
  • Webserver für Chrome oder verwenden Sie einen eigenen Webserver.
  • Der Beispielcode
  • Ein Texteditor
  • Grundkenntnisse in HTML, CSS und JavaScript

3. Beispielcode abrufen

Code herunterladen

Wenn Sie mit Git vertraut sind, können Sie den Code für dieses Codelab von GitHub herunterladen, indem Sie es klonen:

git clone https://github.com/googlecodelabs/webrtc-web

Klicken Sie alternativ auf die folgende Schaltfläche, um eine ZIP-Datei mit dem Code herunterzuladen:

Öffnen Sie die heruntergeladene ZIP-Datei. Dadurch wird ein Projektordner (adaptive-web-media) entpackt, der für jeden Schritt dieses Codelab einen Ordner sowie alle benötigten Ressourcen enthält.

Sie programmieren das Verzeichnis work.

Die Ordner step-nn enthalten die fertige Version für jeden Schritt dieses Codelabs. Sie sind als Referenz verfügbar.

Webserver installieren und überprüfen

Sie können zwar Ihren eigenen Webserver verwenden, dieses Codelab wurde jedoch speziell für den Chrome-Webserver entwickelt. Wenn Sie die App noch nicht installiert haben, können Sie sie über den Chrome Web Store installieren.

6ddeb4aee53c0f0e.png

Klicken Sie nach der Installation der App Webserver für Chrome in der Lesezeichenleiste, auf einer "Neuer Tab"-Seite oder im App Launcher auf die Verknüpfung für Chrome-Apps:

1d2b4aa977ab7e24.png

Klicken Sie auf das Webserversymbol:

27fce4494f641883.png

Als Nächstes wird das folgende Dialogfeld angezeigt, in dem Sie Ihren lokalen Webserver konfigurieren können:

Screenshot 18.02.2016 um 11.48.14 Uhr.png

Klicken Sie auf die Schaltfläche ORDNER AUSWÄHLEN und wählen Sie den gerade erstellten Ordner Arbeit aus. So können Sie den Fortschritt Ihrer Arbeit in Chrome über die URL sehen, die im Dialogfeld „Webserver“ im Bereich Webserver-URL(s) markiert ist.

Klicken Sie unter Optionen das Kästchen neben Index.html automatisch anzeigen an:

Screenshot 18.02.2016 um 11.56.30 Uhr.png

Beenden Sie dann den Server und starten Sie ihn neu, indem Sie den Schalter Webserver: gestartet nach links und dann wieder nach rechts schieben.

Screen Shot 2016-02-18 at 12.22.18 PM.png

Rufen Sie nun Ihre geschäftliche Website in Ihrem Webbrowser auf, indem Sie auf die hervorgehobene Webserver-URL klicken. Sie sollten eine Seite sehen, die so aussieht und work/index.html entspricht:

18a705cb6ccc5181.png

Offensichtlich ist diese App noch nichts Interessantes. Bisher ist sie nur ein minimales Skelett, das wir verwenden, um sicherzustellen, dass Ihr Webserver ordnungsgemäß funktioniert. In den nachfolgenden Schritten fügen Sie Funktionalität und Layoutelemente hinzu.

4. Video von deiner Webcam streamen

Lerninhalte

In diesem Schritt erfahren Sie, wie Sie:

  • Über die Webcam kannst du einen Videostream streamen.
  • Streamwiedergabe bearbeiten
  • Verwenden Sie CSS und SVG, um Videos zu bearbeiten.

Die vollständige Version dieses Schritts befindet sich im Ordner step-01.

Ein Haufen HTML...

Fügen Sie der Datei index.html im Verzeichnis work ein video- und ein script-Element hinzu:

<!DOCTYPE html>
<html>

<head>

  <title>Realtime communication with WebRTC</title>

  <link rel="stylesheet" href="css/main.css" />

</head>

<body>

  <h1>Realtime communication with WebRTC</h1>

  <video autoplay playsinline></video>

  <script src="js/main.js"></script>

</body>

</html>

...und JavaScript

Fügen Sie der Datei main.js in Ihrem js-Ordner Folgendes hinzu:

'use strict';

// On this codelab, you will be streaming only video (video: true).
const mediaStreamConstraints = {
  video: true,
};

// Video element where stream will be placed.
const localVideo = document.querySelector('video');

// Local stream that will be reproduced on the video.
let localStream;

// Handles success by adding the MediaStream to the video element.
function gotLocalMediaStream(mediaStream) {
  localStream = mediaStream;
  localVideo.srcObject = mediaStream;
}

// Handles error by logging a message to the console with the error message.
function handleLocalMediaStreamError(error) {
  console.log('navigator.getUserMedia error: ', error);
}

// Initializes media stream.
navigator.mediaDevices.getUserMedia(mediaStreamConstraints)
  .then(gotLocalMediaStream).catch(handleLocalMediaStreamError);

Jetzt ausprobieren

Öffnen Sie index.html in Ihrem Browser. Es sollte in etwa Folgendes angezeigt werden (mit der Ansicht per Webcam):

9297048e43ed0f3d.png

Funktionsweise

Nach dem getUserMedia()-Aufruf fordert der Browser vom Nutzer die Berechtigung zum Zugriff auf seine Kamera an (wenn dies das erste Mal ist, dass der Kamerazugriff für den aktuellen Ursprung angefordert wird). Bei Erfolg wird ein MediaStream zurückgegeben, der von einem Medienelement über das Attribut srcObject verwendet werden kann:

navigator.mediaDevices.getUserMedia(mediaStreamConstraints)
  .then(gotLocalMediaStream).catch(handleLocalMediaStreamError);


}
function gotLocalMediaStream(mediaStream) {
  localVideo.srcObject = mediaStream;
}

Mit dem Argument constraints können Sie angeben, welche Medien abgerufen werden sollen. In diesem Beispiel nur Video, da Audio standardmäßig deaktiviert ist:

const mediaStreamConstraints = {
  video: true,
};

Sie können Einschränkungen für zusätzliche Anforderungen wie die Videoauflösung verwenden:

const hdConstraints = {
  video: {
    width: {
      min: 1280
    },
    height: {
      min: 720
    }
  }
}

In der MediaTrackConstraints-Spezifikation werden alle potenziellen Einschränkungstypen aufgeführt, obwohl nicht alle Optionen von allen Browsern unterstützt werden. Wenn die angeforderte Auflösung von der aktuell ausgewählten Kamera nicht unterstützt wird, wird „getUserMedia()“ mit einer OverconstrainedError abgelehnt und der Nutzer wird nicht aufgefordert, den Zugriff auf seine Kamera zu erlauben.

Wenn getUserMedia() erfolgreich ist, wird der Videostream der Webcam als Quelle des Videoelements festgelegt:

function gotLocalMediaStream(mediaStream) {
  localVideo.srcObject = mediaStream;
}

Bonuspunkte

  • Das an getUserMedia() übergebene Objekt localStream liegt global vor, sodass Sie es über die Browserkonsole überprüfen können. Öffnen Sie dazu die Konsole, geben Sie stream ein und drücken Sie die Eingabetaste. Um die Konsole in Chrome anzuzeigen, drücken Sie Strg+Umschalt+J bzw. Befehlstaste+Wahltaste+J auf einem Mac.
  • Was gibt localStream.getVideoTracks() zurück?
  • Versuchen Sie, localStream.getVideoTracks()[0].stop() anzurufen.
  • Sehen Sie sich das Einschränkungsobjekt an: Was passiert, wenn Sie es in {audio: true, video: true} ändern?
  • Wie groß ist das Videoelement? Wie ermitteln Sie die natürliche Größe eines Videos aus JavaScript statt der Anzeigegröße? Prüfen Sie das mithilfe der Chrome-Entwicklertools.
  • Versuchen Sie, dem Videoelement CSS-Filter hinzuzufügen. Beispiel:
video {
  filter: blur(4px) invert(1) opacity(0.5);
}
  • Versuchen Sie es mit SVG-Filtern. Beispiel:
video {
   filter: hue-rotate(180deg) saturate(200%);
 }

Das haben Sie gelernt

In diesem Schritt haben Sie Folgendes gelernt:

  • Nimm ein Video von deiner Webcam auf.
  • Medienbeschränkungen festlegen
  • Probleme mit dem Videoelement

Die vollständige Version dieses Schritts befindet sich im Ordner step-01.

Tipps

  • Vergiss nicht das Attribut autoplay für das Element video. Andernfalls sehen Sie nur einen einzigen Frame!
  • Es gibt viele weitere Optionen für getUserMedia()-Einschränkungen. Sehen Sie sich die Demo unter webrtc.github.io/samples/src/content/peerconnection/constraints an. Sie werden feststellen, dass es auf dieser Website viele interessante WebRTC-Beispiele gibt.

Best Practice

  • Achten Sie darauf, dass der Container des Videoelements nicht überläuft. Wir haben width und max-width hinzugefügt, um eine bevorzugte Größe und eine maximale Größe für das Video festzulegen. Der Browser berechnet die Höhe automatisch:
video {
  max-width: 100%;
  width: 320px;
}

Nächstes Video

Du hast Videos, aber wie streamt man sie? Das erfahren Sie im nächsten Schritt.

5. Video mit RTCPeerConnection streamen

Lerninhalte

In diesem Schritt erfahren Sie, wie Sie:

  • Mit dem WebRTC-Shim, adapter.js, sollten Sie Browserunterschiede außer Acht lassen.
  • Verwenden Sie die RTCPeerConnection API zum Streamen von Videos.
  • Medienaufnahme und -streaming steuern

Eine vollständige Version dieses Schritts befindet sich im Ordner step-2.

Was ist RTCPeerConnection?

RTCPeerConnection ist eine API für WebRTC-Aufrufe, um Video- und Audioinhalte zu streamen und Daten auszutauschen.

In diesem Beispiel wird eine Verbindung zwischen zwei RTCPeerConnection-Objekten (sogenannte Peers) auf derselben Seite eingerichtet.

Nicht viel praktisch, aber gut, um zu verstehen, wie RTCPeerConnection funktioniert.

Videoelemente und Steuerungsschaltflächen hinzufügen

Ersetzen Sie in der Datei index.html das einzelne Videoelement durch zwei Videoelemente und drei Schaltflächen:

<video id="localVideo" autoplay playsinline></video>
<video id="remoteVideo" autoplay playsinline></video>


<div>
  <button id="startButton">Start</button>
  <button id="callButton">Call</button>
  <button id="hangupButton">Hang Up</button>
</div>

Ein Videoelement zeigt den Stream von getUserMedia() und das andere zeigt dasselbe über RTCPeerconnection gestreamte Videostream. In einer realen Anwendung würde ein Videoelement den lokalen Stream und das andere den Remote-Stream anzeigen.

Adapter.js-Shim hinzufügen

Fügen Sie über dem Link zu main.js einen Link zur aktuellen Version von adapter.js ein:

<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>

Index.html sollte jetzt so aussehen:

<!DOCTYPE html>
<html>

<head>
  <title>Realtime communication with WebRTC</title>
  <link rel="stylesheet" href="css/main.css" />
</head>

<body>
  <h1>Realtime communication with WebRTC</h1>

  <video id="localVideo" autoplay playsinline></video>
  <video id="remoteVideo" autoplay playsinline></video>

  <div>
    <button id="startButton">Start</button>
    <button id="callButton">Call</button>
    <button id="hangupButton">Hang Up</button>
  </div>

  <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
  <script src="js/main.js"></script>
</body>
</html>

RTCPeerConnection-Code installieren

Ersetzen Sie main.js durch die Version im Ordner step-02.

Anrufen

Öffnen Sie index.html, klicken Sie auf die Schaltfläche Start, um ein Video von Ihrer Webcam zu empfangen, und klicken Sie auf Anrufen, um die Peer-Verbindung herzustellen. Du solltest in beiden Videoelementen dasselbe Video (von deiner Webcam) sehen. Sehen Sie sich in der Browserkonsole die WebRTC-Protokollierung an.

Funktionsweise

Dieser Schritt ist sehr nützlich...

WebRTC verwendet die RTCPeerConnection API, um eine Verbindung zum Streamen von Videos zwischen WebRTC-Clients, den sogenannten Peers, einzurichten.

In diesem Beispiel befinden sich die beiden RTCPeerConnection-Objekte auf derselben Seite: pc1 und pc2. Nicht viel praktisch, aber gut, um zu zeigen, wie die APIs funktionieren.

Das Einrichten eines Anrufs zwischen WebRTC-Peers umfasst drei Aufgaben:

  • Erstellen Sie an beiden Enden des Aufrufs eine RTCPeerConnection und fügen Sie an beiden Enden den lokalen Stream von getUserMedia() hinzu.
  • Netzwerkinformationen abrufen und teilen: Potenzielle Verbindungsendpunkte werden als ICE bezeichnet.
  • Lokale und Remote-Beschreibungen abrufen und teilen: Metadaten zu lokalen Medien im SDP.

Stellen Sie sich vor, Alice und Bob möchten RTCPeerConnection verwenden, um einen Video-Chat einzurichten.

Als Erstes tauschen Alice und Bob Netzwerkinformationen aus. Der Ausdruck „Kandidaten finden“ bezieht sich auf die Suche nach Netzwerkschnittstellen und Ports mit dem ICE.

  1. Alice erstellt ein RTCPeerConnection-Objekt mit einem onicecandidate (addEventListener('icecandidate'))-Handler. Dies entspricht dem folgenden Code aus main.js:
let localPeerConnection;
localPeerConnection = new RTCPeerConnection(servers);
localPeerConnection.addEventListener('icecandidate', handleConnection);
localPeerConnection.addEventListener(
    'iceconnectionstatechange', handleConnectionChange);
  1. Alice ruft getUserMedia() auf und fügt den Stream hinzu, der an diesen übergeben wird:
navigator.mediaDevices.getUserMedia(mediaStreamConstraints).
  then(gotLocalMediaStream).
  catch(handleLocalMediaStreamError);
function gotLocalMediaStream(mediaStream) {
  localVideo.srcObject = mediaStream;
  localStream = mediaStream;
  trace('Received local stream.');
  callButton.disabled = false;  // Enable call button.
}
localPeerConnection.addStream(localStream);
trace('Added local stream to localPeerConnection.');
  1. Der onicecandidate-Handler aus Schritt 1 wird aufgerufen, wenn Netzwerkkandidaten verfügbar sind.
  2. Alice sendet serialisierte Kandidatendaten an Bob. In einer echten Anwendung erfolgt dieser Vorgang (auch als Signalisierung bezeichnet) über einen Messaging-Dienst. Wie Sie dazu vorgehen, erfahren Sie in einem späteren Schritt. In diesem Schritt befinden sich die beiden RTCPeerConnection-Objekte auf derselben Seite und können ohne externe Nachrichten direkt kommunizieren.
  3. Wenn Bob eine Kandidatennachricht von Alice erhält, ruft er addIceCandidate() auf, um den Kandidaten der Beschreibung des Remote-Peers hinzuzufügen:
function handleConnection(event) {
  const peerConnection = event.target;
  const iceCandidate = event.candidate;

  if (iceCandidate) {
    const newIceCandidate = new RTCIceCandidate(iceCandidate);
    const otherPeer = getOtherPeer(peerConnection);

    otherPeer.addIceCandidate(newIceCandidate)
      .then(() => {
        handleConnectionSuccess(peerConnection);
      }).catch((error) => {
        handleConnectionFailure(peerConnection, error);
      });

    trace(`${getPeerName(peerConnection)} ICE candidate:\n` +
          `${event.candidate.candidate}.`);
  }
}

WebRTC-Peers müssen außerdem lokale und Remote-Audio- und Videomedieninformationen wie Auflösungs- und Codec-Funktionen ermitteln und austauschen. Die Signalisierung zum Austausch von Konfigurationsinformationen für Medien erfolgt durch Austausch von Metadaten-Blobs (als Angebot bezeichnet) und einer Antwort. Dabei wird das Sitzungsbeschreibungsprotokoll-Format (SDP) verwendet:

  1. Alice führt die RTCPeerConnection-Methode createOffer() aus. Das zurückgegebene Promise enthält eine RTCSessionDescription: die Beschreibung der lokalen Sitzung von Alice:
trace('localPeerConnection createOffer start.');
localPeerConnection.createOffer(offerOptions)
  .then(createdOffer).catch(setSessionDescriptionError);
  1. Wenn der Vorgang erfolgreich war, legt Alice die lokale Beschreibung mit setLocalDescription() fest und sendet sie dann über den Signalisierungskanal an Bob.
  2. Max legt die Beschreibung, die Alice gesendet hat, mit setRemoteDescription() als Remote-Beschreibung fest.
  3. Bob führt die RTCPeerConnection-Methode createAnswer() aus und übergibt ihr die Remote-Beschreibung, die er von Alice erhalten hat. So kann eine lokale Sitzung generiert werden, die mit ihrer kompatibel ist. Das Promise createAnswer() übergibt eine RTCSessionDescription: Bob legt dies als lokale Beschreibung fest und sendet sie an Alice.
  4. Wenn Alice Roberts Sitzungsbeschreibung erhält, legt sie diese als Remote-Beschreibung mit setRemoteDescription() fest.
// Logs offer creation and sets peer connection session descriptions.
function createdOffer(description) {
  trace(`Offer from localPeerConnection:\n${description.sdp}`);

  trace('localPeerConnection setLocalDescription start.');
  localPeerConnection.setLocalDescription(description)
    .then(() => {
      setLocalDescriptionSuccess(localPeerConnection);
    }).catch(setSessionDescriptionError);

  trace('remotePeerConnection setRemoteDescription start.');
  remotePeerConnection.setRemoteDescription(description)
    .then(() => {
      setRemoteDescriptionSuccess(remotePeerConnection);
    }).catch(setSessionDescriptionError);

  trace('remotePeerConnection createAnswer start.');
  remotePeerConnection.createAnswer()
    .then(createdAnswer)
    .catch(setSessionDescriptionError);
}

// Logs answer to offer creation and sets peer connection session descriptions.
function createdAnswer(description) {
  trace(`Answer from remotePeerConnection:\n${description.sdp}.`);

  trace('remotePeerConnection setLocalDescription start.');
  remotePeerConnection.setLocalDescription(description)
    .then(() => {
      setLocalDescriptionSuccess(remotePeerConnection);
    }).catch(setSessionDescriptionError);

  trace('localPeerConnection setRemoteDescription start.');
  localPeerConnection.setRemoteDescription(description)
    .then(() => {
      setRemoteDescriptionSuccess(localPeerConnection);
    }).catch(setSessionDescriptionError);
}
  1. Ping!

Bonuspunkte

  1. Öffnen Sie chrome://webrtc-internals. Dadurch werden WebRTC-Statistiken und Debugging-Daten bereitgestellt. Eine vollständige Liste der Chrome-URLs finden Sie unter chrome://about.
  2. Gestalten Sie die Seite mit CSS:
  • Stelle die Videos direkt nebeneinander.
  • Die Schaltflächen sollten dieselbe Breite haben und größerer Text haben.
  • Prüfen Sie, ob das Layout auf Mobilgeräten funktioniert.
  1. Sehen Sie sich in der Konsole der Chrome-Entwicklertools localStream, localPeerConnection und remotePeerConnection an.
  2. Sehen Sie sich in der Konsole localPeerConnectionpc1.localDescription an. Wie sieht das SDP-Format aus?

Das haben Sie gelernt

In diesem Schritt haben Sie Folgendes gelernt:

  • Mit dem WebRTC-Shim, adapter.js, sollten Sie Browserunterschiede außer Acht lassen.
  • Verwenden Sie die RTCPeerConnection API zum Streamen von Videos.
  • Medienaufnahme und -streaming steuern
  • Teilen Sie Medien- und Netzwerkinformationen zwischen Peers, um einen WebRTC-Anruf zu ermöglichen.

Eine vollständige Version dieses Schritts befindet sich im Ordner step-2.

Tipps

  • Bei diesem Schritt gibt es viel zu lernen! Weitere Ressourcen, in denen RTCPeerConnection näher erläutert wird, finden Sie unter webrtc.org. Auf dieser Seite finden Sie Vorschläge für JavaScript-Frameworks, wenn Sie WebRTC verwenden, aber keine Codierung Ihrer APIs wünschen.
  • Weitere Informationen zum adapter.js-Shim finden Sie im GitHub-Repository für adapter.js.
  • Möchten Sie sehen, wie die weltbeste App für Videoanrufe aussieht? Sehen wir uns AppRTC an, die kanonische App des WebRTC-Projekts für WebRTC-Aufrufe: app, code. Die Einrichtungszeit für einen Anruf beträgt weniger als 500 ms.

Best Practice

  • Wenn Sie Ihren Code zukunftssicher machen möchten, sollten Sie die neuen Promise-basierten APIs verwenden und adapter.js verwenden, um die Kompatibilität mit Browsern zu ermöglichen, die diese nicht unterstützen.

Nächstes Video

In diesem Schritt erfahren Sie, wie Sie WebRTC zum Streamen von Videos zwischen Kollegen verwenden – aber in diesem Codelab geht es auch um Daten!

Im nächsten Schritt erfahren Sie, wie Sie beliebige Daten mit RTCDataChannel streamen können.

6. RTCDataChannel zum Austausch von Daten verwenden

Lerninhalte

  • Informationen zum Austausch von Daten zwischen WebRTC-Endpunkten (Peers).

Die vollständige Version dieses Schritts befindet sich im Ordner step-03.

HTML aktualisieren

Für diesen Schritt verwenden Sie WebRTC-Datenkanäle, um Text zwischen zwei textarea-Elementen auf derselben Seite zu senden. Das ist zwar nicht sehr nützlich, zeigt aber, wie WebRTC verwendet werden kann, um Daten zu teilen und Videos zu streamen.

Entfernen Sie die Video- und Schaltflächenelemente aus index.html und ersetzen Sie sie durch den folgenden HTML-Code:

<textarea id="dataChannelSend" disabled
    placeholder="Press Start, enter some text, then press Send."></textarea>
<textarea id="dataChannelReceive" disabled></textarea>

<div id="buttons">
  <button id="startButton">Start</button>
  <button id="sendButton">Send</button>
  <button id="closeButton">Stop</button>
</div>

Ein Textbereich dient zum Eingeben von Text, der andere zeigt den Text als gestreamter Text zwischen den Peers an.

index.html sollte jetzt so aussehen:

<!DOCTYPE html>
<html>

<head>

  <title>Realtime communication with WebRTC</title>

  <link rel="stylesheet" href="css/main.css" />

</head>

<body>

  <h1>Realtime communication with WebRTC</h1>

  <textarea id="dataChannelSend" disabled
    placeholder="Press Start, enter some text, then press Send."></textarea>
  <textarea id="dataChannelReceive" disabled></textarea>

  <div id="buttons">
    <button id="startButton">Start</button>
    <button id="sendButton">Send</button>
    <button id="closeButton">Stop</button>
  </div>

  <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
  <script src="js/main.js"></script>

</body>

</html>

JavaScript aktualisieren

Ersetzen Sie main.js durch den Inhalt von step-03/js/main.js.

Testen Sie das Streamen von Daten zwischen Peers: Öffnen Sie index.html, drücken Sie Start, um die Peer-Verbindung einzurichten, geben Sie einen Text in das textarea auf der linken Seite ein und klicken Sie dann auf Senden, um den Text mithilfe von WebRTC-Datenkanälen zu übertragen.

Funktionsweise

Dieser Code nutzt RTCPeerConnection und RTCDataChannel, um den Austausch von Textnachrichten zu ermöglichen.

Der Großteil des Codes in diesem Schritt ist mit dem im RTCPeerConnection-Beispiel identisch.

Die Funktionen sendData() und createConnection() enthalten den größten Teil des neuen Codes:

function createConnection() {
  dataChannelSend.placeholder = '';
  var servers = null;
  pcConstraint = null;
  dataConstraint = null;
  trace('Using SCTP based data channels');
  // For SCTP, reliable and ordered delivery is true by default.
  // Add localConnection to global scope to make it visible
  // from the browser console.
  window.localConnection = localConnection =
      new RTCPeerConnection(servers, pcConstraint);
  trace('Created local peer connection object localConnection');

  sendChannel = localConnection.createDataChannel('sendDataChannel',
      dataConstraint);
  trace('Created send data channel');

  localConnection.onicecandidate = iceCallback1;
  sendChannel.onopen = onSendChannelStateChange;
  sendChannel.onclose = onSendChannelStateChange;

  // Add remoteConnection to global scope to make it visible
  // from the browser console.
  window.remoteConnection = remoteConnection =
      new RTCPeerConnection(servers, pcConstraint);
  trace('Created remote peer connection object remoteConnection');

  remoteConnection.onicecandidate = iceCallback2;
  remoteConnection.ondatachannel = receiveChannelCallback;

  localConnection.createOffer().then(
    gotDescription1,
    onCreateSessionDescriptionError
  );
  startButton.disabled = true;
  closeButton.disabled = false;
}

function sendData() {
  var data = dataChannelSend.value;
  sendChannel.send(data);
  trace('Sent Data: ' + data);
}

Die Syntax von RTCDataChannel ähnelt absichtlich der Syntax von WebSocket, enthält eine send()-Methode und ein message-Ereignis.

Beachten Sie die Verwendung von dataConstraint. Datenkanäle können so konfiguriert werden, dass verschiedene Arten der Datenfreigabe möglich sind, z. B. wenn eine zuverlässige Bereitstellung Vorrang vor der Leistung hat. Weitere Informationen zu den Optionen finden Sie unter Mozilla Developer Network.

Bonuspunkte

  1. Beim SCTP, dem Protokoll, das von WebRTC-Datenkanälen verwendet wird, ist die zuverlässige und geordnete Datenübermittlung standardmäßig aktiviert. In welchen Fällen muss RTCDataChannel für eine zuverlässige Datenübermittlung sorgen und in welchen Fällen ist die Leistung wichtiger – auch wenn dadurch Daten verloren gehen?
  2. Verwenden Sie CSS, um das Seitenlayout zu verbessern, und fügen Sie ein Platzhalterattribut zu "dataChannelReceive" hinzu. Textbereich.
  3. Testen Sie die Seite auf einem Mobilgerät.

Das haben Sie gelernt

In diesem Schritt haben Sie Folgendes gelernt:

  • Eine Verbindung zwischen zwei WebRTC-Peers herstellen.
  • Tauschen Sie Textdaten zwischen den Peers aus.

Die vollständige Version dieses Schritts befindet sich im Ordner step-03.

Weitere Informationen

Nächstes Video

Sie haben gelernt, wie Sie Daten zwischen Peers auf derselben Seite austauschen, aber wie machen Sie das zwischen verschiedenen Rechnern? Zuerst müssen Sie einen Signalisierungskanal einrichten, um Metadatennachrichten auszutauschen. Wie das geht, erfährst du im nächsten Schritt.

7. Signalisierungsdienst einrichten, um Nachrichten auszutauschen

Lerninhalte

In diesem Schritt finden Sie Anleitungen für folgende Aktionen:

  • Verwenden Sie npm, um Projektabhängigkeiten wie in package.json angegeben zu installieren
  • Führen Sie einen Node.js-Server aus und verwenden Sie node-static, um statische Dateien bereitzustellen.
  • Richten Sie mithilfe von Socket.IO einen Messaging-Dienst in Node.js ein.
  • Damit kannst du Räume erstellen und Nachrichten austauschen.

Die vollständige Version dieses Schritts befindet sich im Ordner step-04.

Konzepte

Für die Einrichtung und Aufrechterhaltung eines WebRTC-Anrufs müssen WebRTC-Clients (Peers) Metadaten austauschen:

  • Informationen zum Kandidaten (Netzwerk).
  • Offer- und answer-Nachrichten mit Informationen zu Medien, z. B. Auflösung und Codecs.

Mit anderen Worten: Bevor Peer-to-Peer-Streaming von Audio, Video oder Daten stattfinden kann, müssen Metadaten ausgetauscht werden. Dieser Vorgang wird als Signalisierung bezeichnet.

In den vorherigen Schritten befinden sich die RTCPeerConnection-Objekte für Sender und Empfänger auf derselben Seite. geht es lediglich um die Übergabe von Metadaten zwischen Objekten.

In einer realen Anwendung werden die RTCPeerConnections des Absenders und des Empfängers auf Webseiten auf verschiedenen Geräten ausgeführt. Sie benötigen eine Möglichkeit, um Metadaten zu kommunizieren.

Dazu verwenden Sie einen Signalisierungsserver, also einen Server, der Nachrichten zwischen WebRTC-Clients (Peers) weiterleiten kann. Die eigentlichen Nachrichten bestehen im Nur-Text-Format: String-Strings für JavaScript-Objekte.

Voraussetzung: Node.js installieren

Damit Sie die nächsten Schritte dieses Codelabs (Ordner step-04 bis step-06) ausführen können, müssen Sie mit Node.js einen Server auf localhost ausführen.

Sie können Node.js über diesen Link oder über Ihren bevorzugten Paketmanager herunterladen und installieren.

Nach der Installation können Sie die für die nächsten Schritte erforderlichen Abhängigkeiten importieren (npm install ausführen) und einen kleinen localhost-Server ausführen, um das Codelab auszuführen (mit node index.js). Diese Befehle werden bei Bedarf später angegeben.

Die App

{/6} Weitere Informationen

In diesem Schritt erstellen Sie einen einfachen Node.js-Signalisierungsserver und verwenden das Socket.IO Node.js-Modul und die JavaScript-Bibliothek für das Messaging. Erfahrung mit Node.js und Socket.IO ist hilfreich, aber nicht entscheidend. Die Messaging-Komponenten sind sehr einfach.

In diesem Beispiel ist der Server (die Node.js-Anwendung) in index.js und der darauf ausgeführte Client (die Webanwendung) in index.html implementiert.

Die Node.js-Anwendung in diesem Schritt hat zwei Aufgaben.

Erstens dient er als Nachrichtenweiterleitung:

socket.on('message', function (message) {
  log('Got message: ', message);
  socket.broadcast.emit('message', message);
});

Zweitens verwaltet es die „Räume“ von WebRTC-Videochats:

if (numClients === 0) {
  socket.join(room);
  socket.emit('created', room, socket.id);
} else if (numClients === 1) {
  socket.join(room);
  socket.emit('joined', room, socket.id);
  io.sockets.in(room).emit('ready');
} else { // max two clients
  socket.emit('full', room);
}

Mit unserer einfachen WebRTC-Anwendung können sich maximal zwei Peers einen Raum teilen.

HTML und JavaScript

Aktualisieren Sie die Datei index.html so:

<!DOCTYPE html>
<html>

<head>

  <title>Realtime communication with WebRTC</title>

  <link rel="stylesheet" href="css/main.css" />

</head>

<body>

  <h1>Realtime communication with WebRTC</h1>

  <script src="/socket.io/socket.io.js"></script>
  <script src="js/main.js"></script>
  
</body>

</html>

Auf der Seite in diesem Schritt ist nichts zu sehen: Die gesamte Protokollierung erfolgt in der Browserkonsole. Um die Konsole in Chrome anzuzeigen, drücken Sie Strg+Umschalt+J bzw. Befehlstaste+Wahltaste+J auf einem Mac.

Ersetzen Sie js/main.js durch Folgendes:

'use strict';

var isInitiator;

window.room = prompt("Enter room name:");

var socket = io.connect();

if (room !== "") {
  console.log('Message from client: Asking to join room ' + room);
  socket.emit('create or join', room);
}

socket.on('created', function(room, clientId) {
  isInitiator = true;
});

socket.on('full', function(room) {
  console.log('Message from client: Room ' + room + ' is full :^(');
});

socket.on('ipaddr', function(ipaddr) {
  console.log('Message from client: Server IP address is ' + ipaddr);
});

socket.on('joined', function(room, clientId) {
  isInitiator = false;
});

socket.on('log', function(array) {
  console.log.apply(console, array);
});

Socket.IO für die Ausführung auf Node.js einrichten

Wie Sie vielleicht gesehen haben, verwenden Sie in der HTML-Datei eine Socket.IO-Datei:

<script src="/socket.io/socket.io.js"></script>

Erstellen Sie auf der obersten Ebene des work-Verzeichnisses eine Datei mit dem Namen package.json und folgendem Inhalt:

{
  "name": "webrtc-codelab",
  "version": "0.0.1",
  "description": "WebRTC codelab",
  "dependencies": {
    "node-static": "^0.7.10",
    "socket.io": "^1.2.0"
  }
}

Dies ist ein App-Manifest, das Node Package Manager (npm) mitteilt, welche Projektabhängigkeiten installiert werden sollen.

Um Abhängigkeiten (z. B. /socket.io/socket.io.js) zu installieren, führen Sie im Befehlszeilenterminal folgenden Befehl in Ihrem work-Verzeichnis aus:

npm install

Es sollte ein Installationsprotokoll angezeigt werden, das in etwa so endet:

8ab06b7bcc7664b9.png

Wie Sie sehen, hat npm die in package.json definierten Abhängigkeiten installiert.

Erstellen Sie eine neue Datei index.js auf oberster Ebene des work-Verzeichnisses (nicht im js-Verzeichnis) und fügen Sie den folgenden Code ein:

'use strict';

var os = require('os');
var nodeStatic = require('node-static');
var http = require('http');
var socketIO = require('socket.io');

var fileServer = new(nodeStatic.Server)();
var app = http.createServer(function(req, res) {
  fileServer.serve(req, res);
}).listen(8080);

var io = socketIO.listen(app);
io.sockets.on('connection', function(socket) {

  // convenience function to log server messages on the client
  function log() {
    var array = ['Message from server:'];
    array.push.apply(array, arguments);
    socket.emit('log', array);
  }

  socket.on('message', function(message) {
    log('Client said: ', message);
    // for a real app, would be room-only (not broadcast)
    socket.broadcast.emit('message', message);
  });

  socket.on('create or join', function(room) {
    log('Received request to create or join room ' + room);

    var clientsInRoom = io.sockets.adapter.rooms[room];
    var numClients = clientsInRoom ? Object.keys(clientsInRoom.sockets).length : 0;

    log('Room ' + room + ' now has ' + numClients + ' client(s)');

    if (numClients === 0) {
      socket.join(room);
      log('Client ID ' + socket.id + ' created room ' + room);
      socket.emit('created', room, socket.id);

    } else if (numClients === 1) {
      log('Client ID ' + socket.id + ' joined room ' + room);
      io.sockets.in(room).emit('join', room);
      socket.join(room);
      socket.emit('joined', room, socket.id);
      io.sockets.in(room).emit('ready');
    } else { // max two clients
      socket.emit('full', room);
    }
  });

  socket.on('ipaddr', function() {
    var ifaces = os.networkInterfaces();
    for (var dev in ifaces) {
      ifaces[dev].forEach(function(details) {
        if (details.family === 'IPv4' && details.address !== '127.0.0.1') {
          socket.emit('ipaddr', details.address);
        }
      });
    }
  });

});

Führen Sie im Befehlszeilenterminal den folgenden Befehl im Verzeichnis work aus:

node index.js

Öffnen Sie in Ihrem Browser localhost:8080.

Jedes Mal, wenn Sie diese URL öffnen, werden Sie aufgefordert, einen Raumnamen einzugeben. Wenn Sie demselben Chatroom beitreten möchten, wählen Sie jedes Mal denselben Raumnamen, z. B. „foo“.

Öffnen Sie eine "Neuer Tab"-Seite und öffnen Sie localhost:8080 noch einmal. Wählen Sie denselben Raumnamen aus.

Öffnen Sie localhost:8080 in einem dritten Tab oder Fenster. Wählen Sie noch einmal denselben Raumnamen aus.

Überprüfen Sie die Konsole auf jedem der Tabs: Sie sollten die Protokollierung des JavaScript-Codes oben sehen.

Bonuspunkte

  1. Welche alternativen Messaging-Mechanismen könnten möglich sein? Auf welche Probleme können Sie bei der Verwendung von „reine“ WebSocket?
  2. Welche Probleme könnten mit der Skalierung dieser Anwendung verbunden sein? Lässt sich eine Methode entwickeln, um Tausende oder Millionen von gleichzeitigen Raumanfragen zu testen?
  3. Diese App verwendet eine JavaScript-Aufforderung, um einen Raumnamen abzurufen. Finden Sie eine Möglichkeit, den Raumnamen aus der URL zu ermitteln. Beispiel: localhost:8080/foo würde den Raumnamen foo geben.

Das haben Sie gelernt

In diesem Schritt haben Sie Folgendes gelernt:

  • Verwenden Sie npm, um Projektabhängigkeiten wie in der Datei „package.json“ angegeben zu installieren
  • Führen Sie einen Node.js-Server für statische Dateien vom Server aus.
  • Richten Sie einen Messaging-Dienst in Node.js mit socket.io ein.
  • Damit kannst du Räume erstellen und Nachrichten austauschen.

Die vollständige Version dieses Schritts befindet sich im Ordner step-04.

Weitere Informationen

Nächstes Video

Hier erfahren Sie, wie Sie zwei Nutzer mithilfe von Signalisierung eine Peer-Verbindung herstellen können.

8. Peer-Verbindung und Signalisierung kombinieren

Lerninhalte

In diesem Schritt erfahren Sie, wie Sie:

  • WebRTC-Signalisierungsdienst mit Socket.IO, das auf Node.js ausgeführt wird
  • Verwenden Sie diesen Dienst, um WebRTC-Metadaten zwischen Peers auszutauschen.

Die vollständige Version dieses Schritts befindet sich im Ordner step-05.

HTML und JavaScript ersetzen

Ersetzen Sie den Inhalt von index.html durch Folgendes:

<!DOCTYPE html>
<html>

<head>

  <title>Realtime communication with WebRTC</title>

  <link rel="stylesheet" href="/css/main.css" />

</head>

<body>

  <h1>Realtime communication with WebRTC</h1>

  <div id="videos">
    <video id="localVideo" autoplay muted></video>
    <video id="remoteVideo" autoplay></video>
  </div>

  <script src="/socket.io/socket.io.js"></script>
  <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
  <script src="js/main.js"></script>
  
</body>

</html>

Ersetzen Sie js/main.js durch den Inhalt von step-05/js/main.js.

Node.js-Server ausführen

Wenn Sie dieses Codelab nicht im Verzeichnis work ausführen, müssen Sie möglicherweise die Abhängigkeiten für den Ordner step-05 oder Ihren aktuellen Arbeitsordner installieren. Führen Sie den folgenden Befehl in Ihrem Arbeitsverzeichnis aus:

npm install

Wenn Ihr Node.js-Server nach der Installation nicht ausgeführt wird, starten Sie ihn mit dem folgenden Befehl im work-Verzeichnis:

node index.js

Sie müssen die Version von index.js aus dem vorherigen Schritt verwenden, in der Socket.IO implementiert wurde. Weitere Informationen zu Node und Socket E/A finden Sie im Abschnitt „Signalisierungsdienst zum Austausch von Nachrichten einrichten“.

Öffnen Sie in Ihrem Browser localhost:8080.

Öffnen Sie localhost:8080 noch einmal in einem neuen Tab oder Fenster. Ein Videoelement zeigt den lokalen Stream von getUserMedia() und das andere den lokalen Stream von getUserMedia(). über RTCPeerconnection gestreamt werden.

Sehen Sie sich die Protokollierung in der Browserkonsole an.

Bonuspunkte

  1. Diese Anwendung unterstützt nur 1:1-Videochats. Wie könnten Sie das Design verändern, damit sich mehrere Personen im selben Video-Chatroom befinden können?
  2. In diesem Beispiel ist der Raumname foo hartcodiert. Wie können Sie am besten andere Raumnamen aktivieren?
  3. Wie würden Nutzer den Raumnamen teilen? Versuchen Sie, eine Alternative zur gemeinsamen Nutzung von Raumnamen zu schaffen.
  4. Wie könntest du die App ändern?

Das haben Sie gelernt

In diesem Schritt haben Sie Folgendes gelernt:

  • WebRTC-Signalisierungsdienst mit Socket.IO auf Node.js ausführen
  • Verwenden Sie diesen Dienst, um WebRTC-Metadaten zwischen Peers auszutauschen.

Die vollständige Version dieses Schritts befindet sich im Ordner step-05.

Tipps

  • WebRTC-Statistiken und Debug-Daten sind unter chrome://webrtc-internals verfügbar.
  • Mit test.webrtc.org können Sie Ihre lokale Umgebung überprüfen und Ihre Kamera und Ihr Mikrofon testen.
  • Wenn beim Caching merkwürdige Probleme auftreten, versuchen Sie Folgendes:
  • Führen Sie eine Aktualisierung durch, indem Sie die Strg-Taste gedrückt halten und auf die Schaltfläche Aktualisieren klicken.
  • Browser neu starten
  • Führen Sie npm cache clean über die Befehlszeile aus.

Nächstes Video

Hier erfahren Sie, wie Sie Fotos aufnehmen, Bilddaten abrufen und diese mit anderen Kollegen teilen.

9. Foto aufnehmen und über einen Datenkanal teilen

Lerninhalte

In diesem Schritt erfahren Sie, wie Sie:

  • Nehmen Sie ein Foto auf und rufen Sie die Daten daraus über das Canvas-Element ab.
  • Bilddaten mit einem Remote-Nutzer austauschen

Die vollständige Version dieses Schritts befindet sich im Ordner step-06.

Funktionsweise

Sie haben bereits gelernt, wie Textnachrichten mit RTCDataChannel ausgetauscht werden.

Dadurch können ganze Dateien geteilt werden – in diesem Beispiel mit getUserMedia() aufgenommene Fotos.

Dieser Schritt umfasst die folgenden Hauptbestandteile:

  1. Richten Sie einen Datenkanal ein. Beachten Sie, dass Sie der Peer-Verbindung in diesem Schritt keine Mediastreams hinzufügen.
  2. Nimm mit getUserMedia() den Webcam-Videostream des Nutzers auf:
var video = document.getElementById('video');

function grabWebCamVideo() {
  console.log('Getting user media (video) ...');
  navigator.mediaDevices.getUserMedia({
    video: true
  })
  .then(gotStream)
  .catch(function(e) {
    alert('getUserMedia() error: ' + e.name);
  });
}
  1. Wenn der Nutzer auf die Schaltfläche Andocken klickt, wird eine Momentaufnahme (ein Videoframe) aus dem Videostream abgerufen und in einem canvas-Element angezeigt:
var photo = document.getElementById('photo');
var photoContext = photo.getContext('2d');

function snapPhoto() {
  photoContext.drawImage(video, 0, 0, photo.width, photo.height);
  show(photo, sendBtn);
}
  1. Wenn der Nutzer auf die Schaltfläche Senden klickt, wandeln Sie das Bild in Byte um und senden Sie es über einen Datenkanal:
function sendPhoto() {
  // Split data channel message in chunks of this byte length.
  var CHUNK_LEN = 64000;
  var img = photoContext.getImageData(0, 0, photoContextW, photoContextH),
    len = img.data.byteLength,
    n = len / CHUNK_LEN | 0;

  console.log('Sending a total of ' + len + ' byte(s)');
  dataChannel.send(len);

  // split the photo and send in chunks of about 64KB
  for (var i = 0; i < n; i++) {
    var start = i * CHUNK_LEN,
      end = (i + 1) * CHUNK_LEN;
    console.log(start + ' - ' + (end - 1));
    dataChannel.send(img.data.subarray(start, end));
  }

  // send the reminder, if any
  if (len % CHUNK_LEN) {
    console.log('last ' + len % CHUNK_LEN + ' byte(s)');
    dataChannel.send(img.data.subarray(n * CHUNK_LEN));
  }
}
  1. Die Empfängerseite wandelt Datenkanal-Nachrichtenbyte zurück in ein Bild um und zeigt das Bild für den Nutzer an:
function receiveDataChromeFactory() {
  var buf, count;

  return function onmessage(event) {
    if (typeof event.data === 'string') {
      buf = window.buf = new Uint8ClampedArray(parseInt(event.data));
      count = 0;
      console.log('Expecting a total of ' + buf.byteLength + ' bytes');
      return;
    }

    var data = new Uint8ClampedArray(event.data);
    buf.set(data, count);

    count += data.byteLength;
    console.log('count: ' + count);

    if (count === buf.byteLength) {
      // we're done: all data chunks have been received
      console.log('Done. Rendering photo.');
      renderPhoto(buf);
    }
  };
}

function renderPhoto(data) {
  var canvas = document.createElement('canvas');
  canvas.width = photoContextW;
  canvas.height = photoContextH;
  canvas.classList.add('incomingPhoto');
  // trail is the element holding the incoming images
  trail.insertBefore(canvas, trail.firstChild);

  var context = canvas.getContext('2d');
  var img = context.createImageData(photoContextW, photoContextH);
  img.data.set(data);
  context.putImageData(img, 0, 0);
}

Code abrufen

Ersetzen Sie den Inhalt Ihres Ordners work durch den Inhalt aus Schritt-06. Ihre Datei index.html in Arbeit sollte jetzt so aussehen**:**

<!DOCTYPE html>
<html>

<head>

  <title>Realtime communication with WebRTC</title>

  <link rel="stylesheet" href="/css/main.css" />

</head>

<body>

  <h1>Realtime communication with WebRTC</h1>

  <h2>
    <span>Room URL: </span><span id="url">...</span>
  </h2>

  <div id="videoCanvas">
    <video id="camera" autoplay></video>
    <canvas id="photo"></canvas>
  </div>

  <div id="buttons">
    <button id="snap">Snap</button><span> then </span><button id="send">Send</button>
    <span> or </span>
    <button id="snapAndSend">Snap &amp; Send</button>
  </div>

  <div id="incoming">
    <h2>Incoming photos</h2>
    <div id="trail"></div>
  </div>

  <script src="/socket.io/socket.io.js"></script>
  <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
  <script src="js/main.js"></script>

</body>

</html>

Wenn Sie dieses Codelab nicht im Verzeichnis work ausführen, müssen Sie möglicherweise die Abhängigkeiten für den Ordner step-06 oder Ihren aktuellen Arbeitsordner installieren. Führen Sie dazu einfach den folgenden Befehl in Ihrem Arbeitsverzeichnis aus:

npm install

Wenn Ihr Node.js-Server nach der Installation nicht ausgeführt wird, starten Sie ihn mit dem folgenden Befehl aus dem work-Verzeichnis:

node index.js

Achten Sie darauf, dass Sie die Version von index.js verwenden, in der Socket.IO implementiert, und denken Sie daran, Ihren Node.js-Server neu zu starten, wenn Sie Änderungen vornehmen. Weitere Informationen zu Node und Socket E/A finden Sie im Abschnitt „Signalisierungsdienst zum Austausch von Nachrichten einrichten“.

Klicken Sie bei Bedarf auf die Schaltfläche Zulassen, damit die App Ihre Webcam verwenden kann.

Die App erstellt eine zufällige Raum-ID und fügt diese ID der URL hinzu. Öffnen Sie die URL über die Adressleiste in einem neuen Browsertab oder ‐fenster.

Klicken Sie auf die Schaltfläche Snap & Senden und sehen Sie sich dann auf dem anderen Tab unten auf der Seite den Bereich "Neu hinzugekommen" an. Die App überträgt Fotos zwischen Tabs.

Auf dem Bildschirm sollte Folgendes zu sehen sein:

911b40f36ba6ba8.png

Bonuspunkte

  1. Wie können Sie den Code ändern, damit beliebige Dateitypen freigegeben werden können?

Weitere Informationen

Das haben Sie gelernt

  • Wie Sie ein Foto aufnehmen und mithilfe des Canvas-Elements Daten daraus abrufen.
  • Informationen zum Austausch dieser Daten mit einem Remote-Nutzer

Die vollständige Version dieses Schritts befindet sich im Ordner step-06.

10. Glückwunsch

Sie haben eine App für Videostreaming und Datenaustausch in Echtzeit entwickelt.

Das haben Sie gelernt

In diesem Codelab haben Sie gelernt, wie Sie:

  • Nimm ein Video von deiner Webcam auf.
  • Streamen Sie Videos mit RTCPeerConnection.
  • Streamen Sie Daten mit RTCDataChannel.
  • Richten Sie einen Signalisierungsdienst ein, um Nachrichten auszutauschen.
  • Kombinieren Sie Peer-Verbindungen und Signalisierung.
  • Machen Sie ein Foto und teilen Sie es über einen Datenkanal.

Nächste Schritte

Weitere Informationen

  • Auf webrtc.org finden Sie verschiedene Ressourcen für den Einstieg in WebRTC.