
Teilen Sie:
Hui Jing ist Developer Advocate bei Nexmo. Sie hat eine übermäßige Liebe zu CSS und Typografie und ist allgemein leidenschaftlich über alle Dinge im Web.
Broadcast Video Chat mit Javascript und Vonage
Lesedauer: 8 Minuten
In dieser Reihe von Tutorials werden wir die Vonage Video API (ehemals TokBox OpenTok) und was Sie damit bauen können. Die Video API ist sehr robust und in hohem Maße anpassbar. In jedem Beitrag zeigen wir, wie Sie eine bestimmte Funktion mithilfe der API implementieren können. Dieses Mal werden wir uns ansehen, wie Sie Ihren Video-Chat an viele Zuschauer online übertragen können.
Da diese Anwendung etwas serverseitigen Code erfordert, werden wir Glitch um die Einrichtung zu erleichtern. Sie können den Code auch von diesem Glitch-Projekt herunterladen und auf dem Server oder der Hosting-Plattform Ihrer Wahl bereitstellen (je nach den Anforderungen Ihrer Plattform müssen Sie möglicherweise einige Konfigurationsänderungen vornehmen).
In dieser Reihe werden wir keine Front-End-Frameworks verwenden, sondern nur Vanilla Javascript, um den Fokus auf die Video API selbst zu legen. Am Ende dieses Tutorials sollten Sie in der Lage sein, Ihren Video-Chat mit HTTP-Live-Streaming (HLS) oder einem RTMP-Stream live an ein großes Publikum zu übertragen.

Den endgültigen Code für diese Anwendung finden Sie in diesem GitHub-Repository oder neu gemischt auf Glitch.
Voraussetzungen
Bevor wir loslegen, benötigen Sie einen Vonage Video API Account, den Sie kostenlos erstellen können hier. Sie benötigen außerdem Node.js installiert haben (wenn Sie nicht Glitch verwenden).
Dieses Tutorial baut auf dem ersten einführenden Beitrag der Serie auf: Aufbau eines einfachen Video-Chats. Wenn Sie die Video API zum ersten Mal verwenden, empfehlen wir Ihnen dringend, diesen Beitrag durchzuarbeiten, da er die folgenden grundlegenden Einstellungen abdeckt:
Erstellen eines Vonage Video API-Projekts
Einrichten auf Glitch
Grundlegende Projektstruktur
Initialisierung einer Sitzung
Verbinden mit der Sitzung, Abonnieren und Veröffentlichen
Grundlegende Layout-Stile für einen Video-Chat
Übertragungen mit der Vonage Video API
Die Plattform unterstützt zwei Arten von Übertragungen, Interaktive Live-Video-Übertragungen und Live-Streaming-Übertragungen. Für beide Arten von Übertragungen müssen Sie eine geroutete Sitzung verwenden (eine Sitzung, die den Vonage Video API Media Router). Dieses Thema wird im nächsten Abschnitt ausführlicher behandelt.
Interaktive Live-Video-Übertragungen ermöglichen es vielen Clients, Audio- und Videostreams der anderen in Echtzeit zu veröffentlichen und zu abonnieren. Geroutete Sitzungen können interaktive Live-Videoübertragungen für bis zu 3.000 Streams zwischen Clients unterstützen.
Live-Streaming-Übertragungen können Sie einen HTTP-Live-Streaming-Stream (HLS) oder einen RTMP-Stream mit einer großen Anzahl von Zuschauern teilen. Der HLS- oder RTMP-Stream ist ein einzelnes Video, das sich aus den einzelnen in der Sitzung veröffentlichten Streams zusammensetzt. In diesem Lernprogramm werden wir diese Art der Übertragung verwenden.
HTTP-Live-Streaming (HLS) ist ein Medien-Streaming-Protokoll, das darauf abzielt, kontinuierliche und lange Videos zuverlässig über das Internet zu übertragen. Es wurde von Apple entwickelt und im Jahr 2009 veröffentlicht.
HLS verwendet CDN für die Bereitstellung und ist eine traditionelle Übertragung mit hoher Latenz (15-20 Sekunden) und ohne Interaktion. Ein HLS-Zuschauer empfängt den Inhalt mit einer Latenz von 15-20 Sekunden, so dass es sich nicht direkt für interaktive Anwendungsfälle eignet.
Echtzeit-Messaging-Protokoll (RTMP) ist ein TCP-basiertes Protokoll, das für die Übertragung von Audio, Video und Daten entwickelt wurde. Ursprünglich als proprietäres Protokoll von Macromedia entwickelt, ist es jetzt eine offene Spezifikation, die von Adobe veröffentlicht wurde.
RTMP hat zwar eine geringere Latenz (etwa 5 Sekunden) als HLS, eignet sich aber auch nicht für Anwendungsfälle, die Interaktivität erfordern. Sie würden RTMP verwenden, um mit der Vonage Video API erstellte Inhalte an Social-Media-Videoplattformen wie Facebook oder YouTube Live zu übertragen.
Erstmalige Einrichtung
Da wir auf einen grundlegenden Video-Chat aufbauen, beginnen Sie damit, das Projekt für den grundlegenden Video-Chat aus dem vorherigen Tutorial zu remixen. Klicken Sie dazu auf die große Schaltfläche Remix unten. 👇

Ihre Ordnerstruktur sollte in etwa so aussehen:

Wie eingangs erwähnt, ist TokBox OpenTok jetzt Vonage Video API. Wir haben keine Änderungen an unseren Paketnamen vorgenommen, so dass Sie in Ihrem Code weiterhin auf OpenTok verweisen werden.
Wenn Sie das Glitch-Projekt neu gemischt haben, sollte Ihre server.js Datei bereits wie folgt aussehen:
const express = require("express");
const app = express();
const OpenTok = require("opentok");
const OT = new OpenTok(process.env.API_KEY, process.env.API_SECRET);
let sessions = {};
app.use(express.static("public"));
app.get("/", (request, response) => {
response.sendFile(__dirname + "/views/landing.html");
});
app.get("/session/:room", (request, response) => {
response.sendFile(__dirname + "/views/index.html");
});
app.post("/session/:room", (request, response) => {
const roomName = request.params.room;
// Check if the session already exists
if (sessions[roomName]) {
// Generate the token
generateToken(roomName, response);
} else {
// If the session does not exist, create one
OT.createSession((error, session) => {
if (error) {
console.log("Error creating session:", error);
} else {
// Store the session in the sessions object
sessions[roomName] = session.sessionId;
// Generate the token
generateToken(roomName, response);
}
});
}
});
function generateToken(roomName, response) {
// Configure token options
const tokenOptions = {
role: "publisher",
data: `roomname=${roomName}`
};
// Generate token with the Video API Client SDK
let token = OT.generateToken(
sessions[roomName],
tokenOptions
);
// Send the required credentials back to to the client
// as a response from the fetch request
response.status(200);
response.send({
sessionId: sessions[roomName],
token: token,
apiKey: process.env.API_KEY
});
}
const listener = app.listen(process.env.PORT, () => {
console.log("Your app is listening on port " + listener.address().port);
});
Um den Video-Chat zum Laufen zu bringen, gehen Sie zur .env und geben Sie den API-Schlüssel und das Geheimnis für Ihr Projekt ein, die Sie im Dashboard finden können. Sobald das erledigt ist, werden wir am clientseitigen Code arbeiten, um den Text-Chat zum Laufen zu bringen, bevor wir uns die server.js Datei wieder besuchen.
Fügen Sie das erforderliche Markup hinzu
Unsere Anwendung wird aus drei Seiten bestehen: einer Landing Page, auf der Nutzer eine Sitzung erstellen oder ihr beitreten können, einer Video-Chat-Seite für die Teilnehmer des Video-Chats und einer Seite, die den Broadcast-Stream anzeigt.
Wir müssen eine zusätzliche Seite für die Sendung erstellen. Fügen wir eine broadcast.html Datei in den Ordner views Ordner eine Datei hinzu, indem wir auf die Schaltfläche Neue Datei in der linken Seitenleiste klicken. Benennen Sie die Datei views/broadcast.html und fügen Sie das folgende Markup in die Seite ein.

<!DOCTYPE html>
<html lang="en">
<head>
<title>Broadcast Video Chat</title>
<meta
name="description"
content="Broadcast your video chat to a large audience with Vonage Video API in Node.js"
/>
<link
id="favicon"
rel="icon"
href="https://tokbox.com/developer/favicon.ico"
type="image/x-icon"
/>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="/style.css" />
</head>
<body>
<header>
<h1>Video broadcast</h1>
</header>
<main>
<video id="video" class="broadcast-video"></video>
</main>
<footer>
<p>
<small
>Built on <a href="https://glitch.com">Glitch</a> with the
<a href="https://tokbox.com/developer/">Vonage Video API</a>.</small
>
</p>
</footer>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script src="/broadcast.js"></script>
</body>
</html>
Hier gibt es nicht viel zu tun, der wichtigste Teil ist das video Element, in dem der HLS-Stream untergebracht wird, wenn die Übertragung beginnt.
Wir werden auch einige sendebezogene Markierungen auf der index.html Seite hinzufügen, wie z. B. die Schaltflächen zum Starten und Stoppen der Sendung sowie zur Erzeugung eines teilbaren HLS-Links.
<main>
<div id="subscriber" class="subscriber"></div>
<div id="publisher" class="publisher"></div>
<!-- Add the broadcast controls -->
<div class="broadcast">
<button id="startBroadcast">Start Broadcast</button>
<button id="stopBroadcast" class="hidden">Stop Broadcast</button>
</div>
</main> Gestaltung der Sendekontrollen
Als nächstes fügen wir einige Stile für das neu hinzugefügte Markup ein. Nichts allzu Ausgefallenes hier, nur einige Positionierungen und auch Schaltflächenzustände, über die wir sprechen werden, wenn wir mit der Arbeit am Starten/Stoppen der Sendung beginnen.
/* To position the controls in the bottom-right corner */
.broadcast {
position: absolute;
right: 0;
bottom: 0;
display: flex;
flex-direction: column;
align-items: flex-end;
}
.broadcast a,
.broadcast button {
margin-bottom: 1em;
}
/* This is to centre the broadcast video */
.broadcast-video {
margin: auto;
}Wenn Sie nun die Sitzung starten, sollte Ihre Schnittstelle etwa so aussehen:

Dies ist nicht das endgültige Styling, aber für den Moment, in dem wir die Sendefunktionalität der Anwendung ausbauen, ist es ausreichend.
Starten/Stoppen einer Sendung
Der Schlüssel zur Übertragung mit der Vonage Video API ist die startBroadcast() Methode und die stopBroadcast() Methode. Diese Methoden werden aus der server.js Datei aufgerufen. Die Methode startBroadcast() Methode nimmt drei Parameter entgegen: die Sitzungs-ID für die Sitzung, Optionen für die Übertragung und eine Callback-Funktion. Wir erhalten die Sitzungs-ID von der Client-Seite über eine POST Anfrage. Lassen Sie uns die Route dafür einrichten.
// Required to read the body of a POST request
app.use(express.json());
// Declare an object to store the broadcast information returned by the SDK
let broadcastData = {};
app.post("/broadcast/start", (request, response) => {
const sessionId = request.body.sessionId;
const broadcastOptions = {
outputs: {
hls: {},
},
};
OT.startBroadcast(sessionId, broadcastOptions, (error, broadcast) => {
if (error) {
console.log(error);
response.status(503);
response.send({ error });
}
// Assign the response from the SDK to the broadcastData object
broadcastData = broadcast;
response.status(200);
response.send({ broadcast: broadcast });
});
});
Es gibt noch weitere optionale Eigenschaften, die Sie als Broadcast-Optionen einfügen könnten, wie z. B. Auflösung, Layout usw., aber im Moment werden wir die Standardwerte verwenden. Siehe auch die API-Referenz für nähere Informationen.
Richten wir auch die Route ein, um eine Sendung zu stoppen. Die stopBroadcast() Methode benötigt die Broadcast-ID, die wir ebenfalls von der Client-Seite erhalten.
app.post("/broadcast/stop", (request, response) => {
const broadcastId = request.body.broadcastId;
OT.stopBroadcast(broadcastId, (error, broadcast) => {
if (error) console.log(error);
response.status(200);
response.send({
status: broadcast.status
});
});
});
Es sind einige Anpassungen an der client.js Datei vorgenommen werden, um dieser neuen Funktionalität gerecht zu werden. In der Datei client.js Datei, machen Sie session eine globale Variable.
+ let session;
function initializeSession(apiKey, sessionId, token) {
- const session = OT.initSession(apiKey, sessionId);
+ session = OT.initSession(apiKey, sessionId);
// more code below
}Wir müssen auch den Medienmodus der Sitzung auf eine geroutet anstelle des Standardmodus "Relayed" ändern.
Vorher:
app.post("/session/:room", (request, response) => {
const roomName = request.params.room;
// Check if the session already exists
if (sessions[roomName]) {
// Generate the token
generateToken(roomName, response);
} else {
// If the session does not exist, create one
- OT.createSession((error, session) => {
+ // Set the media mode to routed here
+ OT.createSession({ mediaMode: "routed" }, (error, session) => {
if (error) {
console.log("Error creating session:", error);
} else {
// Store the session in the sessions object
sessions[roomName] = session.sessionId;
// Generate the token
generateToken(roomName, response);
}
});
}
});
Wir müssen auch eine Variable deklarieren broadcast Variable deklarieren, um Informationen über die Sendung zu speichern, die auch zum Beenden der Sendung verwendet wird. Lassen Sie uns zunächst die Antworten auf der Konsole protokollieren, damit wir verifizieren können, dass die Dinge wie erwartet funktionieren.
let broadcast;
const startBroadcastBtn = document.getElementById("startBroadcast");
startBroadcastBtn.addEventListener("click", startBroadCast, false);
function startBroadCast() {
fetch("/broadcast/start", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ sessionId: session.sessionId })
})
.then(res => {
return res.json();
})
.then(res => {
broadcast = res.broadcast;
console.log(res);
})
.catch(handleCallback);
}
const stopBroadcastBtn = document.getElementById("stopBroadcast");
stopBroadcastBtn.addEventListener("click", stopBroadCast, false);
function stopBroadCast() {
fetch("/broadcast/stop", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ broadcastId: broadcast.id })
})
.then(res => {
return res.json();
})
.then(res => {
console.log(res);
})
.catch(handleCallback);
}
Wenn Sie Ihre Konsole beim Starten und Stoppen der Übertragung öffnen, sollten Sie folgendes sehen:

Theoretisch könnten wir hier aufhören, denn wir haben jetzt Zugang zu einem HLS-Link, um den Videochat an einen Player zu streamen, der dieses Format unterstützt. Wenn Sie bereits über ein Gerät verfügen, das HLS-Streams verarbeiten kann, können Sie die Dinge auf Ihre Weise erledigen. Der Rest dieses Tutorials befasst sich mit einer grundlegenden Implementierung, so dass Sie einen Blick darauf werfen können, wie der Broadcast-Stream aussieht.
Zustände der Handle-Tasten
Doch zunächst einige zusätzliche Styling-Elemente für die Schaltflächenzustände. Wie Sie bemerkt haben, gibt es eine gewisse Zeitspanne zwischen dem Drücken der Schaltfläche Sendung starten Schaltfläche und der Antwort, die in der Konsole protokolliert wird. Um die Benutzerfreundlichkeit zu verbessern, möchten wir dem Benutzer anzeigen, dass seine Anfrage an den Server gesendet wurde.
Der Ablauf würde in etwa so funktionieren:

Anstatt sowohl die Start- als auch die Stopp-Schaltfläche anzuzeigen, zeigen wir jeweils nur eine relevante Schaltfläche an. Außerdem wollen wir nicht, dass die Benutzer nach dem Anklicken einer Schaltfläche mehrmals darauf klicken, während die Verarbeitung fortgesetzt wird. Fügen wir einige CSS-Klassen hinzu, um mit den ausgeblendeten und deaktivierten Zuständen umzugehen.
/* These are for the button states */
.hidden {
display: none;
}
.disabled {
cursor: not-allowed;
opacity: 0.5;
pointer-events: none;
}Da "Start" und "Stop" den gleichen Ablauf haben, würden die erforderlichen CSS-Klassen für Zustandsänderungen für beide Schaltflächen gleich sein, nur eben abwechselnd angewendet. Wir können diese Änderungen in eine Funktion abstrahieren, die die Zeichenfolge "start" oder "stop" aufnimmt und die entsprechende Schaltfläche ansteuert.
// Button state while awaiting response from server
function pendingBtnState(statusString) {
const btn = document.getElementById(statusString + "Broadcast");
btn.classList.add("disabled");
btn.setAttribute("data-original", btn.textContent);
btn.textContent = "Processing…";
}
// Switch button state once server responds
function activeBtnState(statusString) {
const activeBtn =
statusString === "start"
? document.getElementById("startBroadcast")
: document.getElementById("stopBroadcast");
const inactiveBtn =
statusString === "stop"
? document.getElementById("startBroadcast")
: document.getElementById("stopBroadcast");
inactiveBtn.classList.remove("disabled");
inactiveBtn.textContent = inactiveBtn.getAttribute("data-original");
inactiveBtn.removeAttribute("data-original");
inactiveBtn.classList.add("hidden");
activeBtn.classList.remove("hidden");
}Lassen Sie uns diese Funktionen in unsere Fetch-Anfragen zum Starten und Stoppen der Übertragung einbauen.
function startBroadCast() {
// To put the Start button into the pending state
pendingBtnState("start");
fetch("/broadcast/start", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ sessionId: session.sessionId })
})
.then(res => {
return res.json();
})
.then(res => {
broadcast = res.broadcast;
// To hide the Start button and show the Stop button
activeBtnState("stop");
})
.catch(handleCallback);
}
function stopBroadCast() {
// To put the Stop button into the pending state
pendingBtnState("stop");
fetch("/broadcast/stop", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ broadcastId: broadcast.id })
})
.then(res => {
return res.json();
})
.then(res => {
// To hide the Stop button and show the Start button
activeBtnState("start");
})
.catch(handleCallback);
}
Freizugebenden HLS-Link erstellen
Das vom SDK zurückgegebene Broadcast-Objekt enthält eine HLS-Broadcast-URL, die von allen Video-Playern, die HLS unterstützen, genutzt werden kann. Machen wir uns dies zunutze, um einen Link zu einer Broadcast-Seite zu erstellen. Wir haben bereits eine broadcast.html Datei erstellt, also leiten wir unseren Broadcast in diese Seite ein. Richten wir dafür eine Route in der server.js Datei eine Route dafür.
app.get("/broadcast/:room", (request, response) => {
response.sendFile(__dirname + "/views/broadcast.html");
});
Wir fügen eine weitere Route hinzu, die überprüft, ob die zu übertragende Sitzung existiert. Wenn dies der Fall ist, wird die Erfolgsantwort die URL für die Übertragung und ihren Status weitergeben.
app.get("/broadcast/hls/:room", (request, response) => {
const roomName = request.params.room;
if (sessions[roomName]) {
response.status(200);
response.send({
hls: broadcastData.broadcastUrls.hls,
status: broadcastData.status
});
} else {
response.status(204);
}
});
Auf unserer index.html Seite fügen Sie Folgendes zu den Broadcast-Steuerelementen hinzu div:
<div class="broadcast">
<!-- Add link to the Broadcast page and a means to copy to clipboard -->
<a class="hidden" id="hlsLink" target="_blank" rel="noopener noreferrer"
>Open Broadcast page</a
>
<p class="invisible" id="hlsCopyTarget"></p>
<button class="hidden" id="copyLink">Copy HLS link</button>
<button id="startBroadcast">Start Broadcast</button>
<button id="stopBroadcast" class="hidden">Stop Broadcast</button>
</div>
Und einige zusätzliche CSS zu styles.css:
.invisible {
position: absolute;
opacity: 0;
z-index: -1;
}Das Ergebnis dieser Änderungen ist ein Link, der die Broadcast-Seite in einem separaten Tab oder Fenster öffnet. Es wird eine Schaltfläche angezeigt, die, wenn sie angeklickt wird, den Link auf die Broadcast-Seite kopiert, damit die Leute ihn weitergeben können. Wir müssen die HLS-URL aus der Broadcast-Antwort sowie den Raumnamen (aus der URL) übernehmen, um den Link für die Broadcast-Seite zusammenzustellen.
const url = new URL(window.location.href);
const roomName = url.pathname.split("/")[2];
// To show/hide the HLS links when the broadcast starts/stops
function hlsLinkState(statusString) {
if (statusString === "start") {
document.getElementById("hlsLink").classList.remove("hidden");
document.getElementById("copyLink").classList.remove("hidden");
} else {
document.getElementById("hlsLink").classList.add("hidden");
document.getElementById("copyLink").classList.add("hidden");
}
}
// Create the link to the broadcast page
function composeHlsLink(link) {
hlsLinkState("start");
const hlsLinkUrl =
"https://" + location.host + "/broadcast/" + roomName + "?hls=" + link;
const hlsLink = document.getElementById("hlsLink");
const hlsCopyTarget = document.getElementById("hlsCopyTarget");
hlsLink.href = hlsLinkUrl;
hlsCopyTarget.innerHTML = hlsLinkUrl;
}Fügen wir diese neuen Funktionen auch den Abrufaufträgen zum Starten und Stoppen der Übertragung hinzu:
function startBroadCast() {
pendingBtnState("start");
fetch("/broadcast/start", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ sessionId: session.sessionId })
})
.then(res => {
return res.json();
})
.then(res => {
broadcast = res.broadcast;
activeBtnState("stop");
// Compose the link to the broadcast page
composeHlsLink(res.broadcast.broadcastUrls.hls);
})
.catch(handleCallback);
}
function stopBroadCast() {
pendingBtnState("stop");
fetch("/broadcast/stop", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ broadcastId: broadcast.id })
})
.then(res => {
return res.json();
})
.then(res => {
activeBtnState("start");
// Hide the links when the broadcast has stopped
hlsLinkState("stop");
})
.catch(handleCallback);
}
Es gibt zahlreiche Videoplayer, die HLS-Streams verarbeiten können und verschiedene Anpassungsmöglichkeiten für die Playeroberfläche bieten, aber um die Dinge einfach zu halten, lädt dieses Tutorial hls.js zur Wiedergabe des Streams. Erstellen Sie eine broadcast.js Datei im Ordner public Ordner.
const url = new URL(window.location.href);
const roomName = url.pathname.split("/")[2];
const hlsLink = url.searchParams.get("hls");
fetch("/broadcast/hls/" + roomName)
.then(res => {
return res.json();
})
.then(res => {
playStream(hlsLink);
})
.catch(error => console.error(error));
// Refer to hls.js documentation for more options
function playStream(hlsLink) {
const video = document.getElementById("video");
const videoSrc = hlsLink;
if (Hls.isSupported()) {
const hls = new Hls();
hls.loadSource(videoSrc);
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, function() {
video.play();
});
} else if (video.canPlayType("application/vnd.apple.mpegurl")) {
video.src = videoSrc;
video.addEventListener("loadedmetadata", function() {
video.play();
});
}
}
Der letzte Teil dieses Tutorials ist eine native Implementierung von Kopieren in die Zwischenablage. Sie können auch eine Bibliothek wie clipboard.js für eine einfachere API.
const copyLinkBtn = document.getElementById("copyLink");
copyLinkBtn.addEventListener("click", copyHlsLink, false);
function copyHlsLink() {
const hlsCopyTarget = document.getElementById("hlsCopyTarget");
const range = document.createRange();
range.selectNode(hlsCopyTarget);
window.getSelection().addRange(range);
try {
const successful = document.execCommand("copy");
const msg = successful ? "successful" : "unsuccessful";
console.log("Copy command was " + msg);
} catch (err) {
console.log("Oops, unable to copy");
}
window.getSelection().removeAllRanges();
}Danach sollten Sie für die Video-Chat-Seite und die Broadcast-Seite etwa so aussehen:


Was kommt als Nächstes?
Der endgültige Code für Glitch und GitHub enthält alles, was wir in diesem langen Beitrag behandelt haben, aber neu organisiert, so dass der Code sauberer und besser wartbar ist. Fühlen Sie sich frei, den Code zu remixen oder zu klonen und selbst mit ihm herumzuspielen.
Es gibt noch weitere Funktionen, die wir mit der Video API von Vonage erstellen können. Diese werden in zukünftigen Tutorials behandelt, aber in der Zwischenzeit können Sie mehr auf unserer umfassenden Dokumentationsseite. Wenn Sie auf Probleme stoßen oder Fragen haben, wenden Sie sich an uns auf unserem Gemeinschaft Slack. Vielen Dank fürs Lesen!