1. Einführung
WebRTC ist ein Open-Source-Projekt, das die Echtzeitkommunikation von Audio, Video und Daten in Web- und nativen Apps ermöglicht.
WebRTC bietet mehrere JavaScript-APIs. Klicken Sie auf die Links, um Demos aufzurufen.
getUserMedia(): Audio und Video aufnehmen.MediaRecorder: Audio und Video aufnehmen.RTCPeerConnection: Audio- und Videodaten zwischen Nutzern streamen.RTCDataChannel: Daten zwischen Nutzern streamen.
Wo kann ich WebRTC verwenden?
In Firefox, Opera und in Chrome auf Computern und Android-Geräten. WebRTC ist auch für native Apps unter iOS und Android verfügbar.
Was ist Signaling?
WebRTC verwendet RTCPeerConnection, um Streamingdaten zwischen Browsern zu übertragen. Es ist aber auch ein Mechanismus erforderlich, um die Kommunikation zu koordinieren und Steuerungsmeldungen zu senden. Dieser Vorgang wird als Signalisierung bezeichnet. Signalisierungsmethoden und ‑protokolle werden nicht von WebRTC festgelegt. In diesem Codelab verwenden Sie Socket.IO für die Nachrichtenübermittlung. Es gibt jedoch viele Alternativen.
Was sind STUN und TURN?
WebRTC ist für die Peer-to-Peer-Kommunikation konzipiert, sodass Nutzer über den direktesten Weg verbunden werden können. WebRTC ist jedoch für die Vernetzung in der realen Welt konzipiert: Clientanwendungen müssen NAT-Gateways und Firewalls durchlaufen und Peer-to-Peer-Netzwerke benötigen Fallbacks, falls eine direkte Verbindung fehlschlägt. Im Rahmen dieses Prozesses verwenden die WebRTC-APIs STUN-Server, um die IP-Adresse Ihres Computers zu ermitteln, und TURN-Server, die als Relayserver fungieren, falls die Peer-to-Peer-Kommunikation fehlschlägt. Weitere Informationen finden Sie unter WebRTC in der realen Welt.
Ist WebRTC sicher?
Die Verschlüsselung ist für alle WebRTC-Komponenten obligatorisch und die JavaScript-APIs können nur von sicheren Quellen (HTTPS oder localhost) verwendet werden. Signalisierungsmechanismen sind nicht durch WebRTC-Standards definiert. Sie müssen also selbst dafür sorgen, dass Sie sichere Protokolle verwenden.
2. Übersicht
Entwickeln Sie eine App, mit der Sie Videos und Schnappschüsse mit Ihrer Webcam aufnehmen und per WebRTC Peer-to-Peer teilen können. Dabei lernen Sie, wie Sie die wichtigsten WebRTC-APIs verwenden und einen Messaging-Server mit Node.js einrichten.
Lerninhalte
- Video von Ihrer Webcam abrufen
- Video mit RTCPeerConnection streamen
- Daten mit RTCDataChannel streamen
- Signalisierungsdienst für den Nachrichtenaustausch einrichten
- Peer-Verbindung und ‑Signalisierung kombinieren
- Foto aufnehmen und über einen Datenkanal teilen
Voraussetzungen
- Chrome 47 oder höher
- Web Server for Chrome oder einen eigenen Webserver Ihrer Wahl.
- Der Beispielcode
- 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 ihn klonen:
git clone https://github.com/googlecodelabs/webrtc-web
Klicken Sie alternativ auf die folgende Schaltfläche, um eine ZIP-Datei des Codes herunterzuladen:
Öffnen Sie die heruntergeladene ZIP-Datei. Dadurch wird ein Projektordner (adaptive-web-media) entpackt, der für jeden Schritt dieses Codelabs einen Ordner sowie alle benötigten Ressourcen enthält.
Sie führen alle Programmierarbeiten im Verzeichnis work aus.
Die step-nn-Ordner enthalten eine fertige Version für jeden Schritt dieses Codelabs. Sie sind als Referenz verfügbar.
Webserver installieren und bestätigen
Sie können zwar Ihren eigenen Webserver verwenden, dieses Codelab ist jedoch für die Verwendung mit dem Chrome-Webserver optimiert. Wenn Sie die App noch nicht installiert haben, können Sie sie im Chrome Web Store installieren.

Klicken Sie nach der Installation der App Web Server for Chrome in der Lesezeichenleiste, auf der Seite „Neuer Tab“ oder im App Launcher auf die Verknüpfung zu Chrome-Apps:

Klicken Sie auf das Websymbol:

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

Klicken Sie auf die Schaltfläche ORDNER AUSWÄHLEN und wählen Sie den Ordner work aus, den Sie gerade erstellt haben. So können Sie Ihre laufende Arbeit in Chrome über die URL ansehen, die im Dialogfeld „Webserver“ im Bereich Webserver-URLs hervorgehoben ist.
Klicken Sie unter Optionen das Kästchen neben index.html automatisch anzeigen an, wie unten dargestellt:

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

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

Diese App macht natürlich noch nichts Interessantes – bisher ist sie nur ein minimales Gerüst, mit dem wir sicherstellen, dass Ihr Webserver ordnungsgemäß funktioniert. In den folgenden Schritten fügen Sie Funktionen und Layout-Features hinzu.
4. Videobilder von der Webcam streamen
Lerninhalte
In diesem Schritt erfahren Sie, wie Sie Folgendes tun:
- Videostream von Ihrer Webcam abrufen
- Streamwiedergabe bearbeiten
- Video mit CSS und SVG bearbeiten
Eine vollständige Version dieses Schritts finden Sie im Ordner step-01.
Ein bisschen HTML…
Fügen Sie der Datei index.html in Ihrem Verzeichnis work ein video-Element 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 eine Prise JavaScript
Fügen Sie in Ihrem js-Ordner Folgendes in main.js ein:
'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. Sie sollten nun etwas Ähnliches sehen (natürlich mit dem Bild Ihrer Webcam):

Funktionsweise
Nach dem getUserMedia()-Aufruf fordert der Browser den Nutzer auf, den Zugriff auf die Kamera zu erlauben (wenn der Kamerazugriff für den aktuellen Ursprung zum ersten Mal angefordert wird). Bei Erfolg wird ein MediaStream zurückgegeben, der von einem Media-Element ü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 sind alle möglichen Einschränkungstypen aufgeführt. Allerdings werden nicht alle Optionen von allen Browsern unterstützt. Wenn die angeforderte Auflösung von der aktuell ausgewählten Kamera nicht unterstützt wird, wird getUserMedia() mit OverconstrainedError abgelehnt und der Nutzer wird nicht aufgefordert, die Berechtigung für den Zugriff auf seine Kamera zu erteilen.
Wenn getUserMedia() erfolgreich ist, wird der Videostream der Webcam als Quelle des Videoelements festgelegt:
function gotLocalMediaStream(mediaStream) {
localVideo.srcObject = mediaStream;
}
Bonuspunkte
- Das
localStream-Objekt, das angetUserMedia()übergeben wird, befindet sich im globalen Bereich. Sie können es also über die Browserkonsole prüfen: Öffnen Sie die Konsole, geben Sie stream ein und drücken Sie die Eingabetaste. Wenn Sie die Konsole in Chrome aufrufen möchten, drücken Sie Strg + Umschalttaste + J oder Befehlstaste + Wahltaste + J, wenn Sie einen Mac verwenden. - Was gibt
localStream.getVideoTracks()zurück? - Rufen Sie
localStream.getVideoTracks()[0].stop()an. - Sehen Sie sich das constraints-Objekt an: Was passiert, wenn Sie es in
{audio: true, video: true}ändern? - Welche Größe hat das Videoelement? Wie kann man die natürliche Größe eines Videos in JavaScript abrufen, anstatt die Anzeigegröße? Verwenden Sie die Chrome-Entwicklertools, um das zu prüfen.
- Fügen Sie dem Videoelement CSS-Filter hinzu. Beispiel:
video {
filter: blur(4px) invert(1) opacity(0.5);
}
- Fügen Sie SVG-Filter hinzu. Beispiel:
video {
filter: hue-rotate(180deg) saturate(200%);
}
Das haben Sie gelernt
In diesem Schritt haben Sie Folgendes gelernt:
- Video von Ihrer Webcam abrufen
- Medieneinschränkungen festlegen
- Das Videoelement bearbeiten
Eine vollständige Version dieses Schritts finden Sie im Ordner step-01.
Tipps
- Vergessen Sie nicht das Attribut
autoplayfür das Elementvideo. Andernfalls wird nur ein einzelnes Bild angezeigt. - Es gibt viele weitere Optionen für
getUserMedia()-Beschränkungen. Eine Demo finden Sie unter webrtc.github.io/samples/src/content/peerconnection/constraints. Wie Sie sehen, gibt es auf dieser Website viele interessante WebRTC-Beispiele.
Best Practice
- Achten Sie darauf, dass das Videoelement nicht über den Container hinausragt. Wir haben
widthundmax-widthhinzugefügt, um eine bevorzugte und eine maximale Größe für das Video festzulegen. Der Browser berechnet die Höhe automatisch:
video {
max-width: 100%;
width: 320px;
}
Nächster Schritt
Sie haben ein Video, wissen aber nicht, wie Sie es streamen sollen? Das erfahren Sie im nächsten Schritt.
5. Video mit RTCPeerConnection streamen
Lerninhalte
In diesem Schritt erfahren Sie, wie Sie Folgendes tun:
- Browserunterschiede mit dem WebRTC-Shim adapter.js abstrahieren.
- Verwenden Sie die RTCPeerConnection API, um Videos zu streamen.
- Medienaufnahme und ‑streaming steuern
Eine vollständige Version dieses Schritts finden Sie im Ordner step-2.
Was ist RTCPeerConnection?
RTCPeerConnection ist eine API für WebRTC-Anrufe zum Streamen von Video und Audio und zum Austauschen von Daten.
In diesem Beispiel wird eine Verbindung zwischen zwei RTCPeerConnection-Objekten (Peers) auf derselben Seite eingerichtet.
Nicht sehr praktisch, aber gut, um die Funktionsweise von RTCPeerConnection zu verstehen.
Videoelemente und Steuerungsschaltflächen hinzufügen
Ersetzen Sie in 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>
In einem Videoelement wird der Stream von getUserMedia() angezeigt und im anderen dasselbe Video, das über RTCPeerconnection gestreamt wird. (In einer realen Anwendung würde in einem Videoelement der lokale Stream und im anderen der Remote-Stream angezeigt.)
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>
Die Datei 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 Video von Ihrer Webcam zu erhalten, und klicken Sie auf Anrufen, um die Peer-Verbindung herzustellen. In beiden Videoelementen sollte dasselbe Video (von Ihrer Webcam) zu sehen sein. In der Browserkonsole können Sie WebRTC-Logs ansehen.
Funktionsweise
In diesem Schritt passiert viel…
WebRTC verwendet die RTCPeerConnection API, um eine Verbindung für das Streamen von Videos zwischen WebRTC-Clients, sogenannten Peers, herzustellen.
In diesem Beispiel befinden sich die beiden RTCPeerConnection-Objekte auf derselben Seite: pc1 und pc2. Nicht sehr praktisch, aber gut, um die Funktionsweise der APIs zu demonstrieren.
Das Einrichten eines Anrufs zwischen WebRTC-Peers umfasst drei Aufgaben:
- Erstellen Sie für jedes Ende des Anrufs eine RTCPeerConnection und fügen Sie an jedem Ende den lokalen Stream aus
getUserMedia()hinzu. - Netzwerkinformationen abrufen und weitergeben: Potenzielle Verbindungsendpunkte werden als ICE-Kandidaten bezeichnet.
- Lokale und Remote-Beschreibungen abrufen und teilen: Metadaten zu lokalen Medien im SDP-Format.
Angenommen, Alice und Bob möchten RTCPeerConnection verwenden, um einen Videochat einzurichten.
Zuerst tauschen Alice und Bob Netzwerkinformationen aus. Der Ausdruck „Kandidaten finden“ bezieht sich auf den Prozess, bei dem Netzwerkschnittstellen und Ports mithilfe des ICE-Frameworks gefunden werden.
- Alice erstellt ein RTCPeerConnection-Objekt mit einem
onicecandidate (addEventListener('icecandidate'))-Handler. Das entspricht dem folgenden Code aus main.js:
let localPeerConnection;
localPeerConnection = new RTCPeerConnection(servers);
localPeerConnection.addEventListener('icecandidate', handleConnection);
localPeerConnection.addEventListener(
'iceconnectionstatechange', handleConnectionChange);
- Alice ruft
getUserMedia()auf und fügt den übergebenen Stream hinzu:
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.');
- Der
onicecandidate-Handler aus Schritt 1 wird aufgerufen, wenn Netzwerkkandidaten verfügbar werden. - Alice sendet serialisierte Kandidatendaten an Bob. In einer echten Anwendung erfolgt dieser Vorgang (als Signalisierung bezeichnet) über einen Messaging-Dienst. Wie das geht, erfahren Sie in einem späteren Schritt. In diesem Schritt befinden sich die beiden RTCPeerConnection-Objekte natürlich auf derselben Seite und können direkt kommunizieren, ohne dass externe Nachrichten erforderlich sind.
- Wenn Bob eine Kandidatenmeldung 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ösung und Codec-Funktionen ermitteln und austauschen. Der Austausch von Informationen zur Medienkonfiguration erfolgt durch den Austausch von Metadaten-Blobs, die als Angebot und Antwort bezeichnet werden. Dabei wird das Session Description Protocol-Format (SDP) verwendet:
- Alice führt die RTCPeerConnection-Methode
createOffer()aus. Das zurückgegebene Promise enthält eine RTCSessionDescription: die lokale Sitzungsbeschreibung von Alice:
trace('localPeerConnection createOffer start.');
localPeerConnection.createOffer(offerOptions)
.then(createdOffer).catch(setSessionDescriptionError);
- Bei Erfolg legt Alice die lokale Beschreibung mit
setLocalDescription()fest und sendet diese Sitzungsbeschreibung dann über den Signalisierungskanal an Bob. - Bob legt die Beschreibung, die Alice ihm gesendet hat, mit
setRemoteDescription()als Remote-Beschreibung fest. - 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. DascreateAnswer()-Promise übergibt eine RTCSessionDescription: Bob legt diese als lokale Beschreibung fest und sendet sie an Alice. - Wenn Alice die Sitzungsbeschreibung von Bob erhält, legt sie diese mit
setRemoteDescription()als Remote-Beschreibung 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);
}
- Ping!
Bonuspunkte
- Sehen Sie sich chrome://webrtc-internals an. Hier finden Sie WebRTC-Statistiken und Debugging-Daten. Eine vollständige Liste der Chrome-URLs finden Sie unter chrome://about.
- Seite mit CSS gestalten:
- Die Videos nebeneinander platzieren
- Die Schaltflächen sollten die gleiche Breite haben und der Text sollte größer sein.
- Das Layout muss auf Mobilgeräten funktionieren.
- Sehen Sie sich in der Konsole der Chrome-Entwicklertools
localStream,localPeerConnectionundremotePeerConnectionan. - Sehen Sie sich in der Console
localPeerConnectionpc1.localDescriptionan. Wie sieht das SDP-Format aus?
Das haben Sie gelernt
In diesem Schritt haben Sie Folgendes gelernt:
- Browserunterschiede mit dem WebRTC-Shim adapter.js abstrahieren.
- Verwenden Sie die RTCPeerConnection API, um Videos zu streamen.
- Medienaufnahme und ‑streaming steuern
- Media- und Netzwerkinformationen zwischen Peers teilen, um einen WebRTC-Anruf zu ermöglichen.
Eine vollständige Version dieses Schritts finden Sie im Ordner step-2.
Tipps
- In diesem Schritt gibt es viel zu lernen. Weitere Ressourcen, in denen RTCPeerConnection genauer erläutert wird, finden Sie unter webrtc.org. Auf dieser Seite finden Sie Vorschläge für JavaScript-Frameworks, wenn Sie WebRTC verwenden möchten, aber nicht mit den APIs arbeiten möchten.
- Weitere Informationen zum adapter.js-Shim finden Sie im adapter.js-GitHub-Repository.
- Möchten Sie sehen, wie die beste Videochat-App der Welt aussieht? Sehen Sie sich AppRTC an, die kanonische App des WebRTC-Projekts für WebRTC-Anrufe: App, Code. Die Anrufaufbauzeit beträgt weniger als 500 ms.
Best Practice
- Um Ihren Code zukunftssicher zu machen, verwenden Sie die neuen Promise-basierten APIs und aktivieren Sie die Kompatibilität mit Browsern, die sie nicht unterstützen, indem Sie adapter.js verwenden.
Nächster Schritt
In diesem Schritt wird gezeigt, wie Sie WebRTC verwenden, um Videos zwischen Peers zu streamen. In diesem Codelab geht es aber auch um Daten.
Im nächsten Schritt erfahren Sie, wie Sie beliebige Daten mit RTCDataChannel streamen.
6. RTCDataChannel zum Austausch von Daten verwenden
Lerninhalte
- So tauschen Sie Daten zwischen WebRTC-Endpunkten (Peers) aus.
Eine vollständige Version dieses Schritts finden Sie im Ordner step-03.
HTML aktualisieren
In diesem Schritt verwenden Sie WebRTC-Datenkanäle, um Text zwischen zwei textarea-Elementen auf derselben Seite zu senden. Das ist nicht sehr nützlich, zeigt aber, wie WebRTC verwendet werden kann, um Daten und Streamingvideos zu teilen.
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 Textfeld dient zur Eingabe von Text, im anderen wird der Text angezeigt, der zwischen den Teilnehmern gestreamt wird.
Die Datei 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, klicken Sie auf Start, um die Peer-Verbindung einzurichten, geben Sie links im textarea etwas Text ein und klicken Sie dann auf Senden, um den Text über WebRTC-Datenkanäle zu übertragen.
Funktionsweise
In diesem Code werden RTCPeerConnection und RTCDataChannel verwendet, um den Austausch von Textnachrichten zu ermöglichen.
Ein Großteil des Codes in diesem Schritt ist derselbe wie im Beispiel für RTCPeerConnection.
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 ist bewusst ähnlich wie bei WebSocket, mit einer send()-Methode und einem 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. die Priorisierung einer zuverlässigen Übermittlung gegenüber der Leistung. Weitere Informationen zu den Optionen finden Sie im Mozilla Developer Network.
Bonuspunkte
- Bei SCTP, dem von WebRTC-Datenkanälen verwendeten Protokoll, ist die zuverlässige und geordnete Datenübermittlung standardmäßig aktiviert. Wann muss RTCDataChannel eine zuverlässige Übermittlung von Daten gewährleisten und wann ist die Leistung wichtiger, auch wenn das bedeutet, dass einige Daten verloren gehen?
- Mit CSS können Sie das Seitenlayout verbessern und dem Textbereich „dataChannelReceive“ ein Platzhalterattribut hinzufügen.
- Testen Sie die Seite auf einem Mobilgerät.
Das haben Sie gelernt
In diesem Schritt haben Sie Folgendes gelernt:
- Stellen Sie eine Verbindung zwischen zwei WebRTC-Peers her.
- Textdaten zwischen den Peers austauschen.
Eine vollständige Version dieses Schritts finden Sie im Ordner step-03.
Weitere Informationen
- WebRTC-Datenkanäle (einige Jahre alt, aber immer noch lesenswert)
- Warum wurde SCTP für den Datenkanal von WebRTC ausgewählt?
Nächster Schritt
Sie haben gelernt, wie Sie Daten zwischen Peers auf derselben Seite austauschen. Wie funktioniert das aber zwischen verschiedenen Computern? Zuerst müssen Sie einen Signalisierungskanal einrichten, über den Metadaten-Nachrichten ausgetauscht werden. Wie das geht, erfahren Sie im nächsten Schritt.
7. Signalisierungsdienst für den Nachrichtenaustausch einrichten
Lerninhalte
In diesem Schritt erfahren Sie, wie Sie Folgendes tun:
- Verwenden Sie
npm, um Projektabhängigkeiten zu installieren, die in package.json angegeben sind. - Node.js-Server ausführen und node-static zum Bereitstellen statischer Dateien verwenden
- Richten Sie einen Messaging-Dienst in Node.js mit Socket.IO ein.
- Damit können Sie „Chatrooms“ erstellen und Nachrichten austauschen.
Eine vollständige Version dieses Schritts finden Sie im Ordner step-04.
Konzepte
Um einen WebRTC-Anruf einzurichten und aufrechtzuerhalten, müssen WebRTC-Clients (Peers) Metadaten austauschen:
- Informationen zu Kandidaten (Netzwerk).
- Offer- und answer-Nachrichten mit Informationen zu Medien, z. B. Auflösung und Codecs.
Mit anderen Worten: Bevor Audio, Video oder Daten per Peer-to-Peer-Streaming übertragen werden können, müssen Metadaten ausgetauscht werden. Dieser Vorgang wird als Signalisierung bezeichnet.
In den vorherigen Schritten befinden sich die RTCPeerConnection-Objekte des Absenders und Empfängers auf derselben Seite. Das Signalisieren besteht also einfach darin, Metadaten zwischen Objekten zu übergeben.
In einer realen Anwendung werden die RTCPeerConnections von Sender und Empfänger auf Webseiten auf verschiedenen Geräten ausgeführt. Sie benötigen eine Möglichkeit, Metadaten zu übertragen.
Dazu verwenden Sie einen Signalisierungsserver: einen Server, der Nachrichten zwischen WebRTC-Clients (Peers) weiterleiten kann. Die eigentlichen Nachrichten sind reiner Text: in Strings umgewandelte 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 einen Server auf localhost mit Node.js 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 (Ausführen von npm install) erforderlichen Abhängigkeiten importieren und einen kleinen Localhost-Server zum Ausführen des Codelabs (Ausführen von node index.js) starten. Diese Befehle werden später angegeben, wenn sie erforderlich sind.
Die App
WebRTC verwendet eine clientseitige JavaScript API, erfordert aber für die praktische Anwendung auch einen Signal- (Messaging-)Server sowie STUN- und TURN-Server. Weitere Informationen
In diesem Schritt erstellen Sie einen einfachen Node.js-Signalisierungsserver mit dem Socket.IO Node.js-Modul und der JavaScript-Bibliothek für Messaging. Erfahrung mit Node.js und Socket.IO ist hilfreich, aber nicht entscheidend, da die Messaging-Komponenten sehr einfach sind.
In diesem Beispiel wird 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 fungiert er als Nachrichtenrelais:
socket.on('message', function (message) {
log('Got message: ', message);
socket.broadcast.emit('message', message);
});
Zweitens verwaltet es WebRTC-Videochaträume:
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);
}
In unserer einfachen WebRTC-Anwendung können maximal zwei Peers einen Raum nutzen.
HTML und JavaScript
Aktualisieren Sie index.html so, dass sie so aussieht:
<!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 wird in diesem Schritt nichts angezeigt. Alle Protokollierungen erfolgen in der Browserkonsole. Wenn Sie die Konsole in Chrome aufrufen möchten, drücken Sie Strg + Umschalttaste + J oder Befehlstaste + Wahltaste + J, wenn Sie einen Mac verwenden.
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
In der HTML-Datei haben Sie möglicherweise gesehen, dass Sie eine Socket.IO-Datei verwenden:
<script src="/socket.io/socket.io.js"></script>
Erstellen Sie im Stammverzeichnis Ihres work-Verzeichnisses eine Datei mit dem Namen package.json mit 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 dem Node Package Manager (npm) mitteilt, welche Projektabhängigkeiten installiert werden sollen.
Um Abhängigkeiten wie /socket.io/socket.io.js zu installieren, führen Sie den folgenden Befehl im Befehlszeilenterminal in Ihrem work-Verzeichnis aus:
npm install
Sie sollten ein Installationslog sehen, das in etwa so endet:

Wie Sie sehen, hat npm die in package.json definierten Abhängigkeiten installiert.
Erstellen Sie eine neue Datei index.js auf der obersten Ebene des Verzeichnisses work (nicht im Verzeichnis js) 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 in der Befehlszeile des Terminals 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 Raum beitreten möchten, wählen Sie jedes Mal denselben Raumnamen aus, z. B. „foo“.
Öffnen Sie einen neuen Tab und rufen Sie localhost:8080 noch einmal auf. Wählen Sie denselben Raumnamen aus.
Öffnen Sie localhost:8080 auf einem dritten Tab oder in einem dritten Fenster. Wählen Sie noch einmal denselben Namen für den Raum aus.
Sehen Sie sich die Konsole auf den einzelnen Tabs an. Dort sollten die Protokolle aus dem JavaScript oben angezeigt werden.
Bonuspunkte
- Welche alternativen Messaging-Mechanismen sind möglich? Welche Probleme können bei der Verwendung von „reinem“ WebSocket auftreten?
- Welche Probleme könnten bei der Skalierung dieser Anwendung auftreten? Kannst du eine Methode zum Testen von Tausenden oder Millionen gleichzeitiger Raumanfragen entwickeln?
- In dieser App wird ein JavaScript-Prompt verwendet, um einen Raumnamen abzurufen. Ermitteln Sie, wie Sie den Raumnamen aus der URL abrufen können. Beispiel: localhost:8080/foo ergibt den Raumnamen
foo.
Das haben Sie gelernt
In diesem Schritt haben Sie Folgendes gelernt:
- Mit npm Projektabhängigkeiten installieren, die in package.json angegeben sind
- Einen Node.js-Server zum Bereitstellen statischer Dateien ausführen.
- Einrichten eines Messaging-Dienstes in Node.js mit socket.io
- Damit können Sie „Chatrooms“ erstellen und Nachrichten austauschen.
Eine vollständige Version dieses Schritts finden Sie im Ordner step-04.
Weitere Informationen
- Socket.io-Chatbeispiel-Repository
- WebRTC in der Praxis: STUN, TURN und Signalisierung
- Der Begriff „Signalisierung“ in WebRTC
Nächster Schritt
Hier erfahren Sie, wie Sie mithilfe von Signaling zwei Nutzern ermöglichen, eine Peer-Verbindung herzustellen.
8. Peer-Verbindung und ‑Signalisierung kombinieren
Lerninhalte
In diesem Schritt erfahren Sie, wie Sie Folgendes tun:
- WebRTC-Signalisierungsdienst mit Socket.IO unter Node.js ausführen
- Über diesen Dienst werden WebRTC-Metadaten zwischen Peers ausgetauscht.
Eine vollständige Version dieses Schritts finden Sie 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 den Inhalt von js/main.js durch den Inhalt von step-05/js/main.js.
Node.js-Server ausführen
Wenn Sie dieses Codelab nicht über Ihr Arbeitsverzeichnis ausführen, müssen Sie möglicherweise die Abhängigkeiten für den Ordner step-05 oder Ihr aktuelles Arbeitsverzeichnis 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, indem Sie den folgenden Befehl im Verzeichnis work aufrufen:
node index.js
Achten Sie darauf, dass Sie die Version von index.js aus dem vorherigen Schritt verwenden, in der Socket.IO implementiert ist. Weitere Informationen zu Node und Socket IO 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. In einem Videoelement wird der lokale Stream von getUserMedia() angezeigt und im anderen das „Remote“-Video, das über RTCPeerconnection gestreamt wird.
Logging in der Browserkonsole ansehen
Bonuspunkte
- Diese Anwendung unterstützt nur 1:1-Videochats. Wie könnten Sie das Design ändern, damit mehrere Personen denselben Video-Chatroom nutzen können?
- Im Beispiel ist der Raumname foo fest codiert. Wie können Sie am besten andere Raumnamen aktivieren?
- Wie würden Nutzer den Raumnamen teilen? Versuchen Sie, eine Alternative zum Teilen von Raumnamen zu entwickeln.
- Wie könnten Sie die App ändern?
Das haben Sie gelernt
In diesem Schritt haben Sie Folgendes gelernt:
- Einen WebRTC-Signalisierungsdienst mit Socket.IO ausführen, das auf Node.js ausgeführt wird.
- Über diesen Dienst werden WebRTC-Metadaten zwischen Peers ausgetauscht.
Eine vollständige Version dieses Schritts finden Sie im Ordner step-05.
Tipps
- WebRTC-Statistiken und Debugging-Daten sind unter chrome://webrtc-internals verfügbar.
- Mit test.webrtc.org können Sie Ihre lokale Umgebung prüfen und Ihre Kamera und Ihr Mikrofon testen.
- Wenn Sie ungewöhnliche Probleme mit dem Caching haben, versuchen Sie Folgendes:
- Führen Sie eine Aktualisierung ohne Cache 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ächster Schritt
Hier erfahren Sie, wie Sie ein Foto aufnehmen, die Bilddaten abrufen und diese zwischen Remote-Peers teilen.
9. Foto aufnehmen und über einen Datenkanal teilen
Lerninhalte
In diesem Schritt erfahren Sie, wie Sie
- Ein Foto aufnehmen und die Daten daraus mit dem Canvas-Element abrufen.
- Bilddaten mit einem Remote-Nutzer austauschen
Eine vollständige Version dieses Schritts finden Sie im Ordner step-06.
Funktionsweise
Zuvor haben Sie gelernt, wie Sie Textnachrichten über RTCDataChannel austauschen.
In diesem Schritt können Sie ganze Dateien freigeben, in diesem Beispiel Fotos, die mit getUserMedia() aufgenommen wurden.
Die wichtigsten Teile dieses Schritts sind:
- Datenkanal einrichten Beachten Sie, dass Sie der Peer-Verbindung in diesem Schritt keine Media-Streams hinzufügen.
- Webcam-Videostream des Nutzers mit
getUserMedia()aufnehmen:
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);
});
}
- Wenn der Nutzer auf die Schaltfläche Snap klickt, wird ein Snapshot (ein Videobild) 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);
}
- 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));
}
}
- Die Empfangsseite konvertiert die Datenkanal-Nachrichtenbytes zurück in ein Bild und zeigt das Bild dem 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 von step-06. Ihre Datei index.html im Ordner work 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 & 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 über Ihr Arbeitsverzeichnis ausführen, müssen Sie möglicherweise die Abhängigkeiten für den Ordner step-06 oder Ihr aktuelles Arbeitsverzeichnis installieren. Führen Sie 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, indem Sie den folgenden Befehl in Ihrem work-Verzeichnis aufrufen:
node index.js
Achten Sie darauf, dass Sie die Version von index.js verwenden, in der Socket.IO implementiert ist. Starten Sie außerdem Ihren Node.js-Server neu, wenn Sie Änderungen vornehmen. Weitere Informationen zu Node und Socket IO finden Sie im Abschnitt „Signalisierungsdienst zum Austausch von Nachrichten einrichten“.
Klicken Sie bei Bedarf auf die Schaltfläche Zulassen, um der App die Verwendung Ihrer Webcam zu erlauben.
Die App erstellt eine zufällige Raum-ID und fügt sie der URL hinzu. Öffnen Sie die URL aus der Adressleiste in einem neuen Browsertab oder -fenster.
Klicken Sie auf die Schaltfläche Snap & Send und sehen Sie sich dann im anderen Tab unten auf der Seite den Bereich „Eingehend“ an. Die App überträgt Fotos zwischen Tabs.
Auf dem Bildschirm sollte Folgendes zu sehen sein:

Bonuspunkte
- Wie können Sie den Code ändern, damit beliebige Dateitypen freigegeben werden können?
Weitere Informationen
- MediaStream Image Capture API: Eine API zum Aufnehmen von Fotos und Steuern von Kameras – bald in einem Browser in Ihrer Nähe!
- Die MediaRecorder API zum Aufzeichnen von Audio und Video: Demo, Dokumentation.
Das haben Sie gelernt
- So nehmen Sie ein Foto auf und rufen die Daten daraus mit dem Canvas-Element ab.
- So tauschen Sie diese Daten mit einem Remote-Nutzer aus.
Eine vollständige Version dieses Schritts finden Sie im Ordner step-06.
10. Glückwunsch
Sie haben eine App für Echtzeit-Videostreaming und Datenaustausch entwickelt.
Das haben Sie gelernt
In diesem Codelab haben Sie Folgendes gelernt:
- Video von Ihrer Webcam abrufen
- Videos mit RTCPeerConnection streamen.
- Daten mit RTCDataChannel streamen
- Richten Sie einen Signalisierungsdienst für den Nachrichtenaustausch ein.
- Kombinieren Sie Peer-Verbindung und ‑Signalisierung.
- Nehmen Sie ein Foto auf und teilen Sie es über einen Datenkanal.
Nächste Schritte
- Sehen Sie sich den Code und die Architektur der kanonischen WebRTC-Chatanwendung AppRTC an: app, code.
- Live-Demos von github.com/webrtc/samples ausprobieren
Weitere Informationen
- Auf webrtc.org finden Sie eine Reihe von Ressourcen, die den Einstieg in WebRTC erleichtern.