Wie man eine Live- und Video-Streaming-App mit WebRTC erstellt
Published: 2024-02-08 05:32:04

Was ist WebRTC-Videostreaming?
------------------------------

WebRTC-Videostreaming ist ein kostenloses und quelloffenes Projekt, das es Webbrowsern und Mobilgeräten wie iOS und Android ermöglicht, Echtzeitkommunikation zu ermöglichen. Mit dieser Funktionalität können App-Funktionen wie Peer-to-Peer-Videokonferenzen einfach in eine Webseite integriert werden. Mit WebRTC-Videostreaming kann ein browserbasierter Videochat schnell mit HTML und JavaScript entwickelt werden, ohne dass Back-End-Code erforderlich ist. Dies ist eine Schlüsselkomponente für die [Einbindung von Live-Publikum](https://www.pubnub.com/solutions/live-audience-engagement/) und Lösungen für [die Zusammenarbeit mit mehreren Nutzern](https://www.pubnub.com/solutions/multiuser-collaboration/), die das Benutzererlebnis auf Plattformen wie sozialen Medien, Live-Video-Streaming-Anwendungen und Content-Delivery-Netzwerken verbessern. Die Anpassungsfähigkeit von WebRTC macht es zu einem unverzichtbaren Tool für die App-Entwicklung, das für eine Vielzahl von Anwendungen geeignet ist - von Amazons Cloud-Diensten über Netflix' Video-on-Demand, Twitchs Streaming-Plattform und Facebook Live bis hin zu interaktiven Funktionen auf Hulu, Spotify und Apple-Geräten.

![](https://www.pubnub.com/cdn/3prze68gbwl1/3zeNU3Nn3bvFIa3CxPAK0H/ac3b96f11d8b13ae8157150e39a4b910/webrtc-video-call-chatengine.jpg)

Wie funktioniert das WebRTC-Videostreaming?
-------------------------------------------

WebRTC ermöglicht es Nutzern, Peer-to-Peer-Audio- und Videostreaming in modernen Webbrowsern durchzuführen. Diese Funktion wird von den neuesten Versionen von Chrome, FireFox, Edge, Safari und Opera auf dem Desktop sowie von nativen iOS- und Android-Webbrowsern unterstützt. Dies ist die Grundlage der von PubNub angebotenen [Datenstreaming-Lösungen](https://www.pubnub.com/solutions/data-streaming/).

Um das Gerät eines Benutzers zu einem WebRTC-Client zu machen, muss lediglich ein neues `RTCPeerConnection()-Objekt` im Front-End-JavaScript initialisiert werden.

WebRTC-Live-Streaming-Architektur
---------------------------------

Der Video-Chat wird über das WebRTC-Protokoll auf zwei oder mehr Client-Geräten aufgebaut. Die Verbindung kann in einem von zwei Modi hergestellt werden. Der erste Modus ist Peer-to-Peer, d. h. Audio- und Videopakete werden direkt von Client zu Client mit [RTC-Konfiguration](https://developer.mozilla.org/en-US/docs/Web/API/RTCConfiguration) gestreamt. Dies funktioniert, solange beide Rechner eine IP-Adresse haben, die über das öffentliche Internet zugänglich ist.

Für Browser-Videochats und -Konferenzen ist es jedoch nicht ratsam, sich auf Peer-to-Peer-Verbindungen zu verlassen, wenn es um Produktionsanwendungen geht. Es kommt häufig vor, dass das ICE-Framework (Interactive Connectivity Establishment) keine Verbindung zwischen zwei Benutzern herstellen kann, wenn sich einer oder beide hinter einem erweiterten LAN-Sicherheitssystem befinden.

Um dies zu vermeiden, können Sie Ihre RTCConfiguration so einstellen, dass zunächst eine Peer-to-Peer-Verbindung versucht wird und dann auf eine Relayed-Verbindung zurückgegriffen wird, wenn Peer-to-Peer fehlschlägt.

![](https://www.pubnub.com/cdn/3prze68gbwl1/asset-17suaysk1qa1jcu/afcb88a1d7f5aaaaebe8c91413347091/webrtc-p2p-stun-pubnub.png)

Wenn öffentlich zugängliche IP-Adressen keine Option sind, muss eine WebRTC-Verbindung über einen TURN-Server hergestellt werden. Das ICE-Framework entscheidet, ob dies notwendig ist, während die Benutzer versuchen, eine Verbindung herzustellen.

Bauen Sie keinen WebRTC-Signalisierungsserver für Ihr Live-Streaming - verwenden Sie PubNub
-------------------------------------------------------------------------------------------

WebRTC lässt eine sehr wichtige Komponente des Video-Chat-Streamings aus. Ein Client muss einen Signalisierungsdienst verwenden, um Nachrichten mit seinem Peer oder seinen Peers zu kommunizieren. PubNub ermöglicht es Entwicklern, Funktionen wie einen WebRTC-Signalisierungsdienst vollständig und kostengünstig zu implementieren. Dies wird durch die ausführliche [Dokumentation](https://www.pubnub.com/docs) von PubNub zum Einrichten Ihres Kontos und zum Senden/Empfangen von Nachrichten erleichtert.

### Beispiele für Video-Chat-Streaming mit WebRTC

Diese Nachrichten sind für Ereignisse wie:

-   Ich, Benutzer A, möchte Sie, Benutzer B, anrufen
    
-   Benutzer A versucht gerade, Sie anzurufen, Benutzer B
    
-   Ich, Benutzer B, nehme deinen Anruf an, Benutzer A
    
-   Ich, Benutzer B, lehne deinen Anruf ab Benutzer A
    
-   Ich, Benutzer B, möchte unser Gespräch beenden Benutzer A
    
-   Ich, Benutzer A, möchte unser Gespräch beenden Benutzer B
    
-   Text-Sofortnachrichten wie in Slack, Google Hangouts, Skype, Facebook Messenger, usw.
    
-   Session Audio/Video Codec und Daten zur Benutzerverbindung.
    

Diese Nachrichten sind Teil des **Signalisierungs-Transaktionsflusses**, der in der [Dokumentation des Mozilla Developer Network für WebRTC](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Signaling_and_video_calling) beschrieben ist. Der WebRTC-Signalisierungsserver ist ein abstraktes Konzept. Viele Dienste können zu diesem "Signalisierungsserver" werden, wie WebSockets, Socket.IO oder PubNub. Wenn Sie mit der Erstellung einer Lösung für diese Aufgabe betraut sind, werden Sie sich am Ende fragen: Sollen wir bauen oder sollen wir kaufen?

### Warum PubNub: Logische Erweiterungen wie One-to-Many-WebRTC-Videostreaming

PubNub ermöglicht es einem Entwickler wie Ihnen, einen WebRTC-Signalisierungsdienst vollständig und kostengünstig zu implementieren. Eine [Open Source WebRTC-Bibliothek, die PubNub verwendet](https://github.com/stephenlb/webrtc-sdk), ist auf GitHub verfügbar. Die folgende PubNub-Datenstreaming-Lösung ist jedoch noch schneller als die Entwicklung mit dem WebRTC-SDK, da unsere Plattform es Ihnen ermöglicht, schnell und einfach eine Anwendung zu entwickeln, die One-to-Many-Streaming in beliebigem Umfang unterstützt.

Community-gestütztes Paket für WebRTC-Videogespräche
----------------------------------------------------

PubNub ist wie ein globales CDN für Echtzeitdaten. Entwickler können sein [IaaS](https://www.pubnub.com/learn/glossary/what-is-infrastructure-as-a-service-iaas/) für die Erstellung hochwertiger Echtzeit-Streaming-Plattformen, mobiler Anwendungen und vieles mehr nutzen. Es gibt PubNub SDKs für jede Programmiersprache und jedes Gerät, die zuverlässige Pub/Sub-Verbindungen, Datenübertragung und die Steuerung des Netzwerks ermöglichen - und das alles mit nur wenigen Zeilen Code.

WebRTC Video Streaming App Tutorial mit Javascript, HTML, CSS
-------------------------------------------------------------

In diesem Tutorial werden wir JavaScript, HTML und CSS verwenden, um unsere Video-Chat-App zu erstellen. Wenn Sie jedoch ein modernes Front-End-Framework wie Vue, [React](https://www.pubnub.com/docs/chat/sdks/messages/sending-messages) oder Angular verwenden möchten, können Sie sich die aktualisierte [PubNub-Tutorials-Seite](https://www.pubnub.com/blog/category/build/) oder das [PubNub Chat Resource Center](https://www.pubnub.com/docs/chat/overview) ansehen. Wir haben auch ein umfangreiches Entwicklungsteam, das Sie beraten kann.

Für den Anfang können Sie das [HTML](https://github.com/ajb413/pubnub-js-webrtc/blob/master/example/index.html) und [CSS](https://github.com/ajb413/pubnub-js-webrtc/blob/master/example/style.css) in meinem Projektbeispiel verwenden. Diese Dateien stellen eine sehr generische Benutzeroberfläche für eine Video-Chat-Anwendung dar. Die Beispielanwendung hat nur einen globalen Chat und keine privaten 1:1-Chats, obwohl diese leicht zu implementieren sind.

WebRTC-Video-Streaming-Anwendung HTML
-------------------------------------

Öffnen Sie **index.html** mit Ihrem bevorzugten Texteditor. **Ersetzen** Sie die Skript-Tags unter dem Body-Tag Ihrer HTML-Datei durch diese 2 CDN-Skripte. Lassen Sie den 3. Skript-Tag, der auf **app.js** verweist, stehen. Wir werden diese Datei zusammen schreiben.

```js
<script type="text/javascript" src="https://cdn.pubnub.com/sdk/javascript/pubnub.4.32.0.js"></script>
<script src="https://cdn.jsdelivr.net/npm/pubnub-js-webrtc@latest/dist/pubnub-js-webrtc.js"></script>
```

Im nächsten Schritt erstellen Sie Ihre eigene app.js-Datei im gleichen Verzeichnis wie Ihre index.html-Datei. Der Grund, warum wir eine neue app.js-Datei erstellen müssen, ist, dass das Skript in meinem Beispiel [Xirsys](https://xirsys.com/) verwendet. Mein privates Konto ist mit meinem Functions-Server verbunden. Wenn Sie einen TURN-Anbieter wie Xirsys verwenden möchten, müssen Sie Ihren eigenen Back-End-Server und Ihr eigenes Konto einrichten. Mein nächster Blog-Beitrag wird ein Tutorial für die Erstellung von WebRTC-Anwendungen mit TURN enthalten.

Das app.js-Skript, das wir gemeinsam schreiben werden, wird nur kostenlose Peer-to-Peer-WebRTC-Verbindungen verwenden. Wenn Sie versuchen, einen Live-Videoanruf mit 2 Geräten im selben LAN zu führen, wird Ihre App funktionieren. Es ist nicht sicher, dass eine Videoanrufverbindung mit Clients in getrennten Netzwerken hergestellt werden kann (aufgrund von NAT-Sicherheit). Aus diesem Grund ist es wichtig, die Streaming-Protokolle zu verstehen.

### WebRTC-Videostreaming-Anwendung javascript

Zunächst werden wir Verweise auf alle DOM-Elemente aus der Datei index.html erstellen. Sobald wir in unserem JavaScript-Code auf sie verweisen können, können wir sie programmatisch manipulieren.

```js
const chatInterface = document.getElementById('chat-interface');
const myVideoSample = document.getElementById('my-video-sample');
const myVideo = document.getElementById('my-video');
const remoteVideo = document.getElementById('remote-video');
const videoModal = document.getElementById('video-modal');
const closeVideoButton = document.getElementById('close-video');
const brokenMyVideo = document.getElementById('broken-my-video');
const brokenSampleVideo = document.getElementById('broken-sample-video');
const usernameModal = document.getElementById('username-input-modal');
const usernameInput = document.getElementById('username-input');
const joinButton = document.getElementById('join-button');
const callConfirmModal = document.getElementById('call-confirm-modal');
const callConfirmUsername = document.getElementById('call-confirm-username');
const yesCallButton = document.getElementById('yes-call');
const noCallButton = document.getElementById('no-call');
const incomingCallModal = document.getElementById('incoming-call-modal');
const callFromSpan = document.getElementById('call-from');
const acceptCallButton = document.getElementById('accept-call');
const rejectCallButton = document.getElementById('reject-call');
const onlineList = document.getElementById('online-list');
const chat = document.getElementById('chat');
const log = document.getElementById('log');
const messageInput = document.getElementById('message-input');
const submit = document.getElementById('submit');
```

Als Nächstes fügen wir einige Variablen hinzu, die einen CSS-Klassennamen, globale Anwendungsinformationen und WebRTC-Konfigurationsinformationen enthalten. Im Wörterbuch RTCConfiguration fügen wir STUN- und TURN-Serverinformationen für WebRTC-Aufrufe hinzu. Dies ist ein wichtiger Schritt für hochwertige Videoinhalte in Ihrem Streaming-Dienst.

```js
const hide = 'hide';
// PubNub Channel for sending/receiving global chat messages
//     also used for user presence with Presence
const globalChannel = 'global-channel';
let webRtcPhone;
let pubnub;
// An RTCConfiguration dictionary from the browser WebRTC API
// Add STUN and TURN server information here for WebRTC calling
const rtcConfig = {};
let username; // User's name in the app
let myAudioVideoStream; // Local audio and video stream
let noVideoTimeout; // Used to check if a video connection succeeded
const noVideoTimeoutMS = 5000; // Error alert if the video fails to connect
```

Nun werden wir uns mit dem zwingend erforderlichen Client-Code für die WebRTC-Paketfunktionalität befassen. Hier kommt der Echtzeit-Aspekt Ihrer Video-Streaming-Plattform ins Spiel.

```js
// Init the audio and video stream on this client
getLocalStream().then((localMediaStream) => {
    myAudioVideoStream = localMediaStream;
    myVideoSample.srcObject = myAudioVideoStream;
    myVideo.srcObject = myAudioVideoStream;
}).catch(() => {
    myVideo.classList.add(hide);
    myVideoSample.classList.add(hide);
    brokenMyVideo.classList.remove(hide);
    brokenSampleVideo.classList.remove(hide);
});
// Prompt the user for a username input
getLocalUserName().then((myUsername) => {
    username = myUsername;
    usernameModal.classList.add(hide);
    initWebRtcApp();
});
// Send a chat message when Enter key is pressed
messageInput.addEventListener('keydown', (event) => {
    if (event.keyCode === 13 && !event.shiftKey) {
        event.preventDefault();
        sendMessage();
        return;
    }
});
// Send a chat message when the submit button is clicked
submit.addEventListener('click', sendMessage);
const closeVideoEventHandler = (event) => {
    videoModal.classList.add(hide);
    chatInterface.classList.remove(hide);
    clearTimeout(noVideoTimeout);
    webRtcPhone.disconnect(); // disconnects the current phone call
}
// Register a disconnect event handler when the close video button is clicked
closeVideoButton.addEventListener('click', closeVideoEventHandler);
```

Der neue Code, den wir gerade hinzugefügt haben:

-   Fragt den Browser, ob er auf die Webcam und das Mikrofon des Computers zugreifen kann, und speichert das Stream-Objekt in einer globalen Variablen.
    
-   Fordert den Benutzer zur Eingabe eines In-App-Benutzernamens auf, bevor wir den WebRTC-Teil der Anwendung initialisieren.
    
-   Registriert Event-Handler für Chat-Nachrichten, z. B. wenn ein Benutzer auf die Schaltfläche "Submit" klickt oder die Eingabetaste drückt.
    
-   Erstellt einen weiteren Event-Handler für den Fall, dass der Benutzer den Video-Chat schließt.
    

Als Nächstes werden wir den Initialisierungscode für den WebRTC-Teil der Webanwendung hinzufügen. In diesem Teil initialisieren wir unsere PubNub-Instanz mit der neuesten SDK-Version 4.32.0.

```js
const initWebRtcApp = () => {
    // WebRTC phone object event for when the remote peer's video becomes available.
    const onPeerStream = (webRTCTrackEvent) => {
        console.log('Peer audio/video stream now available');
        const peerStream = webRTCTrackEvent.streams[0];
        window.peerStream = peerStream;
        remoteVideo.srcObject = peerStream;
    };
    // WebRTC phone object event for when a remote peer attempts to call you.
    const onIncomingCall = (fromUuid, callResponseCallback) => {
        let username = document.getElementById(fromUuid).children[1].innerText;
        incomingCall(username).then((acceptedCall) => {
            if (acceptedCall) {
                // End an already open call before opening a new one
                webRtcPhone.disconnect();
                videoModal.classList.remove(hide);
                chatInterface.classList.add(hide);
                noVideoTimeout = setTimeout(noVideo, noVideoTimeoutMS);
            }
            callResponseCallback({ acceptedCall });
        });
    };
    // WebRTC phone object event for when the remote peer responds to your call request.
    const onCallResponse = (acceptedCall) => {
        console.log('Call response: ', acceptedCall ? 'accepted' : 'rejected');
        if (acceptedCall) {
            videoModal.classList.remove(hide);
            chatInterface.classList.add(hide);
            noVideoTimeout = setTimeout(noVideo, noVideoTimeoutMS);
        }
    };
    // WebRTC phone object event for when a call disconnects or timeouts.
    const onDisconnect = () => {
        console.log('Call disconnected');
        videoModal.classList.add(hide);
        chatInterface.classList.remove(hide);
        clearTimeout(noVideoTimeout);
    };
    // Lists the online users in the UI and registers a call method to the click event
    //     When a user clicks a peer's name in the online list, the app calls that user.
    const addToOnlineUserList = (occupant) => {
        const userId = occupant.uuid;
        const name = occupant.state ? occupant.state.name : null;
        if (!name) return;
        const userListDomElement = createUserListItem(userId, name);
        const alreadyInList = document.getElementById(userId);
        const isMe = pubnub.getUUID() === userId;
        if (alreadyInList) {
            removeFromOnlineUserList(occupant.uuid);
        } 
        if (isMe) {
            return;
        }
        onlineList.appendChild(userListDomElement);
        userListDomElement.addEventListener('click', (event) => {
            const userToCall = userId;
            confirmCall(name).then((yesDoCall) => {
                if (yesDoCall) {
                    webRtcPhone.callUser(userToCall, {
                        myStream: myAudioVideoStream
                    });
                }
            });
        });
    }
    const removeFromOnlineUserList = (uuid) => {
        const div = document.getElementById(uuid);
        if (div) div.remove();
    };
    pubnub = new PubNub({
        publishKey : '_YOUR_PUBNUB_PUBLISH_API_KEY_HERE_',
        subscribeKey : '_YOUR_PUBNUB_SUBSCRIBE_API_KEY_HERE_'
    });
    // This PubNub listener powers the text chat and online user list population.
    pubnub.addListener({
        message: function(event) {
            // Render a global chat message in the UI
            if (event.channel === globalChannel) {
                renderMessage(event);
            }
        },
        status: function(statusEvent) {
            if (statusEvent.category === "PNConnectedCategory") {
                pubnub.setState({
                    state: {
                        name: username
                    },
                    channels: [globalChannel],
                    uuid: pubnub.getUUID()
                });
                pubnub.hereNow({
                    channels: [globalChannel],
                    includeUUIDs: true,
                    includeState: true
                },
                (status, response) => {
                    response.channels[globalChannel].occupants
                        .forEach(addToOnlineUserList);
                });
            }
        },
        presence: (status, response) => {
            if (status.error) {
                console.error(status.error);
            } else if (status.channel === globalChannel) {
                if (status.action === "join") {
                    addToOnlineUserList(status, response);
                } else if (status.action === "state-change") {
                    addToOnlineUserList(status, response);
                } else if (status.action === "leave") {
                    removeFromOnlineUserList(status.uuid);
                } else if (status.action === "timeout") {
                    removeFromOnlineUserList(response.uuid);
                }
            }
        }
    });
    pubnub.subscribe({
        channels: [globalChannel],
        withPresence: true
    });
    window.ismyuuid = pubnub.getUUID();
    // Disconnect PubNub before a user navigates away from the page
    window.onbeforeunload = (event) => {
        pubnub.unsubscribe({
            channels: [globalChannel]
        });
    };
    // WebRTC phone object configuration.
    let config = {
        rtcConfig,
        ignoreNonTurn: false,
        myStream: myAudioVideoStream,
        onPeerStream,   // is required
        onIncomingCall, // is required
        onCallResponse, // is required
        onDisconnect,   // is required
        pubnub          // is required
    };
    webRtcPhone = new WebRtcPhone(config);
};
```

Im Initialisierungscode für den WebRTC-Teil der Webanwendung haben wir einige Aktualisierungen vorgenommen, um die neuesten von PubNub angebotenen Funktionalitäten zu berücksichtigen. Dies ist wichtig, um sicherzustellen, dass Ihre Videostreaming-Anwendung mit den neuesten Technologietrends kompatibel ist.

Der Code, den wir gerade zu app.js hinzugefügt haben, wird ausgeführt, nachdem der Benutzer seinen "Benutzernamen" eingegeben hat, und er:

-   Deklariert alle Plugin-Ereignishandler für WebRTC-Anrufereignisse
    
-   fügt Elemente der Online-Liste hinzu und entfernt sie wieder, wenn Benutzer in der App ein- und ausgeschaltet werden
    
-   Registriert einen Event-Handler, um einen neuen Videoanruf an einen Benutzer zu tätigen, sobald sein Name in der Benutzerliste angeklickt wird
    
-   Registriert einen Event-Handler, um neue Chat-Nachrichten zu rendern, sobald eine an den globalen Chat gesendet wird, in Echtzeit
    
-   Richtet PubNub ein, um Echtzeitnachrichten mit dem [Pub/Sub-Nachrichtenmuster](https://www.pubnub.com/products/pubnub-platform/) zu senden und zu empfangen
    
-   Initialisiert das WebRTC-Paket und übergibt das Konfigurationsobjekt an die Instanz
    

Bevor wir fortfahren, ist es wichtig zu beachten, dass wir unsere freien PubNub-API-Schlüssel in diese Funktion einfügen müssen. Wir können einige kostenlose Schlüssel erhalten, indem wir das Anmeldeformular unten verwenden. Diese Schlüssel sind bis zu 1 Million Transaktionen pro Monat kostenlos, was für Hobbyisten oder professionelle Proof-of-Concept-Anwendungen ideal ist.

Sie können Ihre Client-Pub/Sub-API-Schlüssel in die app.js-Datei in das PubNub-Initialisierungsobjekt einfügen, wie Sie im vorherigen Codeschnipsel sehen können.

```js
pubnub = new PubNub({
    publishKey : 'PUBLISH_KEY',
    subscribeKey : 'SUBSCRIBE_KEY',
    uuid: "UUID"
});
```

Wir müssen die **Presence-Funktion** im PubNub Admin Dashboard aktivieren. Wenn Sie einen PubNub-Schlüsselsatz erstellen, ist die Anwesenheitsfunktion für diesen Schlüssel standardmäßig deaktiviert. Wir können sie für den Key aktivieren, indem wir zum [PubNub Admin Dashboard](https://dashboard.pubnub.com/) gehen und den Kippschalter anklicken. Um mehr über die Präsenzfunktion und ihre Möglichkeiten zu erfahren, lesen Sie unsere [Dokumentation](https://www.pubnub.com/docs/general/presence/overview).

Die Beispielapplikation verwendet [Präsenz](https://www.pubnub.com/docs/general/presence/overview), um zu zeigen, welche Benutzer in der App online sind. Wir verwenden die PubNub-Benutzer-UUID, um eindeutige Verweise auf jeden Benutzer in der App zu erhalten. Wenn wir einen WebRTC-Videogesprächsvorgang durchführen, verwenden wir die UUID, damit beide Benutzer den entsprechenden Benutzernamen in ihrer Benutzeroberfläche anzeigen können.

Als Nächstes benötigen wir einige Dienstprogrammmethoden, um UI-spezifische Funktionen auszuführen. Diese sind nicht für alle WebRTC-Anwendungen spezifisch, sondern nur für die Ausführung dieser speziellen, von mir entworfenen Benutzeroberfläche. Fügen Sie diesen Code am Ende der app.js-Datei hinzu.

```js
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// UI Render Functions
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
function renderMessage(message) {
    const messageDomNode = createMessageHTML(message);
    log.append(messageDomNode);
    // Sort messages in chat log based on their timetoken (value of DOM id)
    sortNodeChildren(log, 'id');
    chat.scrollTop = chat.scrollHeight;
}
function incomingCall(name) {
    return new Promise((resolve) => {
        acceptCallButton.onclick = function() {
            incomingCallModal.classList.add(hide);
            resolve(true);
        }
        rejectCallButton.onclick = function() {
            incomingCallModal.classList.add(hide);
            resolve(false);
        }
        callFromSpan.innerHTML = name;
        incomingCallModal.classList.remove(hide);
    });
}
function confirmCall(name) {
    return new Promise((resolve) => {
        yesCallButton.onclick = function() {
            callConfirmModal.classList.add(hide);
            resolve(true);
        }
        noCallButton.onclick = function() {
            callConfirmModal.classList.add(hide);
            resolve(false);
        }
        callConfirmUsername.innerHTML = name;
        callConfirmModal.classList.remove(hide);
    });
}
function getLocalUserName() {
    return new Promise((resolve) => {
        usernameInput.focus();
        usernameInput.value = '';
        usernameInput.addEventListener('keyup', (event) => {
            const nameLength = usernameInput.value.length;
            if (nameLength > 0) {
                joinButton.classList.remove('disabled');
            } else {
                joinButton.classList.add('disabled');
            }
            if (event.keyCode === 13 && nameLength > 0) {
                resolve(usernameInput.value);
            }
        });
        joinButton.addEventListener('click', (event) => {
            const nameLength = usernameInput.value.length;
            if (nameLength > 0) {
                resolve(usernameInput.value);
            }
        });
    });
}
function getLocalStream() {
    return new Promise((resolve, reject) => {
        navigator.mediaDevices
        .getUserMedia({
            audio: true,
            video: true
        })
        .then((avStream) => {
            resolve(avStream);
        })
        .catch((err) => {
            alert('Cannot access local camera or microphone.');
            console.error(err);
            reject();
        });
    });
}
function createUserListItem(userId, name) {
    const div = document.createElement('div');
    div.id = userId;
    const img = document.createElement('img');
    img.src = './phone.png';
    const span = document.createElement('span');
    span.innerHTML = name;
    div.appendChild(img);
    div.appendChild(span);
    return div;
}
function createMessageHTML(messageEvent) {
    const text = messageEvent.message.text;
    const jsTime = parseInt(messageEvent.timetoken.substring(0,13));
    const dateString = new Date(jsTime).toLocaleString();
    const senderUuid = messageEvent.publisher;
    const senderName = senderUuid === pubnub.getUUID()
        ? username
        : document.getElementById(senderUuid).children[1].innerText;
    const div = document.createElement('div');
    const b = document.createElement('b');
    div.id = messageEvent.timetoken;
    b.innerHTML = `${senderName} (${dateString}): `;
    div.appendChild(b);
    div.innerHTML += text;
    return div;
}
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Utility Functions
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
function sendMessage() {
    const messageToSend = messageInput.value.replace(/?
|/g, '');
    const trimmed = messageToSend.replace(/(\s)/g, '');
    if (trimmed.length > 0) {
        pubnub.publish({
            channel: globalChannel,
            message: {
                text: messageToSend
            }
        });
    }
    messageInput.value = '';
}
// Sorts sibling HTML elements based on an attribute value
function sortNodeChildren(parent, attribute) {
    const length = parent.children.length;
    for (let i = 0; i < length-1; i++) {
        if (parent.children[i+1][attribute] < parent.children[i][attribute]) {
            parent.children[i+1].parentNode
                .insertBefore(parent.children[i+1], parent.children[i]);
            i = -1;
        }
    }
}
function noVideo() {
    const message = 'No peer connection made.
' +
        'Try adding a TURN server to the WebRTC configuration.';
    if (remoteVideo.paused) {
        alert(message);
        closeVideoEventHandler();
    }
}
```

### **CSS für WebRTC-Videostreaming-Anwendungen**

Wir brauchen CSS-Stile in unserer App für eine hübsche und ansprechende Benutzeroberfläche. Die Datei index.html enthält bereits einen Verweis auf die Datei style.css, fügen Sie sie also in denselben Ordner ein. Die [style.css-Datei](https://github.com/ajb413/pubnub-js-webrtc/blob/master/example/style.css) für diese WebRTC-Anwendung ist im GitHub-Repository verfügbar.

Geschafft! Jetzt können Sie Ihre statischen Front-End-Webdateien auf einer Webhosting-Plattform wie WordPress oder [GitHub-Seiten](https://pages.github.com/) bereitstellen. Ihre WebRTC-Chat-App wird für jeden auf der Welt verfügbar sein. Der Code ist mobilkompatibel, d. h. die neuesten Webbrowser auf iOS und Android können die App für Face-to-Face-Video ausführen!

**WebRTC-Streaming-Paket FAQ**
------------------------------

### **Ist das WebRTC-Paket offiziell ein Teil von PubNub?**

Nein. Es handelt sich um ein Open-Source-Projekt, das von der Community unterstützt wird. Wenn Sie Fragen haben oder Hilfe benötigen, wenden Sie sich an [devrel@pubnub.com.](mailto:devrel@pubnub.com) Wenn Sie einen Fehler melden möchten, tun Sie dies auf der [GitHub Issues-Seite](https://github.com/ajb413/pubnub-js-webrtc/issues).

### **Streamt PubNub Audio- oder Videodaten mit WebRTC?**

Nein. PubNub arbeitet sehr gut mit WebRTC als Signalisierungsdienst zusammen. Das bedeutet, dass PubNub Ereignisse von Client zu Client mittels Pub/Sub-Messaging signalisiert. Diese Ereignisse umfassen:

-   Ich, Benutzer A, möchte Sie, Benutzer B, anrufen
    
-   Benutzer A versucht gerade, dich anzurufen, Benutzer B
    
-   Ich, Benutzer B, nehme Ihren Anruf an, Benutzer A
    
-   Ich, Benutzer B, lehne Ihren Anruf ab Benutzer A
    
-   Ich, Benutzer B, möchte unser Gespräch beenden Benutzer A
    
-   Ich, Benutzer A, möchte unser Gespräch beenden Benutzer B
    
-   Text-Instant-Messaging wie in Slack, Google Hangouts, Skype, Facebook Messenger, usw.
    

### **Kann ich mit WebRTC und PubNub einen Gruppenanruf mit mehr als 2 Teilnehmern führen?**

Gruppenanrufe können mit WebRTC und PubNub entwickelt werden, allerdings kann das aktuelle PubNub JS WebRTC-Paket nur 2 Benutzer in einem privaten Anruf verbinden, und nicht einen WebRTC-unterstützten Simulcast von mehr als 2 Benutzern. Die Community könnte diese Funktion in der Zukunft entwickeln, aber bis jetzt gibt es keine Pläne für die Entwicklung.

**Erste Schritte mit PubNub für Ihre WebRTC-Anwendung**
-------------------------------------------------------

Softwareentwicklung mit PubNub für Ihre Live-Streaming-Anwendung. Sichern Sie sich niedrige Latenzzeiten und Entwicklungskosten, indem Sie sich einfach für ein kostenloses Konto anmelden und unsere APIs in Ihre WebRTC-Anwendung integrieren. So haben Sie schnell einen MVP Ihrer Chat-Anwendung. Mit PubNub haben Sie Zugang zu [viele Tools und Ressourcen](https://www.pubnub.com/docs) die Ihnen helfen, eine robuste und skalierbare Chat-Anwendung zu entwickeln.

Um loszulegen, befolgen Sie diese Schritt-für-Schritt-Anleitung:

-   [Melden Sie sich für ein kostenloses PubNub-Konto an.](https://admin.pubnub.com/#/register)
    
-   [Folgen Sie](https://www.pubnub.com/tutorials/) eine Schritt-für-Schritt-Anleitung, um eine Chat-Anwendung mit dem PubNub SDK einzurichten und zu erstellen.
    
-   [Fügen Sie Funktionen wie mobile Push-Benachrichtigungen](https://www.pubnub.com/tutorials/) zu Ihren iOS- oder Android-Chatanwendungen hinzu, indem Sie ein [detaillierten Anleitung](https://www.pubnub.com/tutorials/).
    

[Besuchen Sie unsere Docs, um mehr zu erfahren über](https://www.pubnub.com/docs) Erstellung Ihrer Echtzeit-Chat-Webanwendung.

Wie kann PubNub Ihnen helfen?
=============================

Dieser Artikel wurde ursprünglich auf [PubNub.com](https://www.pubnub.com/blog/integrating-video-calling-in-chat-with-webrtc-and-pubnub/) veröffentlicht.

Unsere Plattform unterstützt Entwickler bei der Erstellung, Bereitstellung und Verwaltung von Echtzeit-Interaktivität für Webanwendungen, mobile Anwendungen und IoT-Geräte.

Die Grundlage unserer Plattform ist das größte und am besten skalierbare Echtzeit-Edge-Messaging-Netzwerk der Branche. Mit über 15 Points-of-Presence weltweit, die 800 Millionen monatlich aktive Nutzer unterstützen, und einer Zuverlässigkeit von 99,999 % müssen Sie sich keine Sorgen über Ausfälle, Gleichzeitigkeitsgrenzen oder Latenzprobleme aufgrund von Verkehrsspitzen machen.

PubNub erleben
--------------

Sehen Sie sich die [Live Tour](https://www.pubnub.com/tour/introduction/) an, um in weniger als 5 Minuten die grundlegenden Konzepte hinter jeder PubNub-gestützten App zu verstehen

Einrichten
----------

Melden Sie sich für einen [PubNub-Account](https://admin.pubnub.com/signup/) an und erhalten Sie sofort kostenlosen Zugang zu den PubNub-Schlüsseln

Beginnen Sie
------------

Mit den [PubNub-Dokumenten](https://www.pubnub.com/docs) können Sie sofort loslegen, unabhängig von Ihrem Anwendungsfall oder [SDK](https://www.pubnub.com/docs)