
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.
Teilen Sie Ihren Bildschirm mit der Vonage Video API
Lesedauer: 4 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, und in jedem Beitrag zeigen wir, wie man eine bestimmte Funktion mit der API implementiert. Diesmal sehen wir uns an, wie Sie Ihren einfachen Audio-Video-Chat um die Bildschirmfreigabe erweitern 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 Serie werden wir keine Front-End-Frameworks verwenden, sondern nur Vanilla Javascript, um den Schwerpunkt auf die Video API selbst zu legen. Am Ende dieses Tutorials sollten Sie in der Lage sein, Ihren Bildschirm mit der Person in Ihrem Video-Chat zu teilen.

Den endgültigen Code für diese Anwendung finden Sie in diesem GitHub-Repository oder neu gemischt auf Glitch.
Voraussetzungen
Bevor Sie loslegen, benötigen Sie einen Vonage Video API Account, den Sie kostenlos erstellen können hier. Sie benötigen außerdem Node.js installiert sein (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 OpenTok-Sitzung
Verbinden mit der Sitzung, Abonnieren und Veröffentlichen
Grundlegende Layout-Stile für einen Video-Chat
Vorbereiten auf mehrere veröffentlichte Streams
In der vorherigen Anwendung hat sich Ihr Browser mit der Sitzung verbunden und einen einzigen Stream (Ihre Kamera) veröffentlicht. Mit der zusätzlichen Bildschirmfreigabe können Sie jedoch zwei Streams in derselben Sitzung veröffentlichen. Um dies zu ermöglichen, müssen Sie in public/client.jsdie Variable session in eine globale Variable.
Vorher:
function initializeSession(apiKey, sessionId, token) {
const session = OT.initSession(apiKey, sessionId);
// more code below
}Danach:
let session;
function initializeSession(apiKey, sessionId, token) {
session = OT.initSession(apiKey, sessionId);
// more code below
}In views/index.htmlmüssen Sie ein Platzhalterelement für das anzuzeigende Screen-Sharing-Video und eine Schaltfläche zum Auslösen der Freigabe bereitstellen. Erstellen Sie auch eine Schaltfläche zum Beenden der Bildschirmfreigabe, die später verwendet wird:
<main>
<!-- This element is new -->
<div id="screen" class="screen"></div>
<!-- These two elements already exist from the first tutorial -->
<div id="subscriber" class="subscriber"></div>
<div id="publisher" class="publisher"></div>
<!-- These are both new too -->
<button id="startScreenShare" class="screen-share">Share Screen</button>
<button id="stopScreenShare" class="screen-share hidden">Stop Sharing Screen</button>
</main> Screen-Sharing-Funktionen prüfen
Wenn die Schaltfläche "Teilen" gedrückt wird, sollte die Anwendung zunächst prüfen, ob sie den Bildschirm teilen kann. Fügen Sie diesen Code am Ende von client.js:
const startShareBtn = document.getElementById("startScreenShare");
startShareBtn.addEventListener("click", event => {
OT.checkScreenSharingCapability(response => {
if (!response.supported || response.extensionRegistered === false) {
alert("Screen sharing not supported");
} else if (response.extensionInstalled === false) {
alert("Browser requires extension");
} else {
// Share screen code
}
});
});
Die Methode OT.checkScreenSharingCapability() Methode gibt Informationen über die Fähigkeiten des aktuellen Browsers zurück. Auf dieser Grundlage können Sie feststellen, ob der Browser die Funktion nicht unterstützt, eine Erweiterung in älteren Browsern erforderlich ist oder eine gemeinsame Nutzung über native APIs möglich ist.
In Chrome 71 und früher, Firefox 51 und früher und Opera 58 und früher muss der Benutzer eine Erweiterung installieren, um seinen Bildschirm zu teilen. Dieser Beitrag befasst sich nicht mit Erweiterungen, aber Sie können mehr in der Dokumentation.
Teilen Sie Ihren Bildschirm
Fügen Sie den folgenden Code in den else Anweisungsblock oben ein:
const screenSharePublisher = OT.initPublisher(
"screen",
{
insertMode: "append",
width: "100%",
height: "100%",
videoSource: "screen",
publishAudio: true
},
handleCallback
);
session.publish(screenSharePublisher, handleCallback);Der erste Parameter ist der id des HTML-Elements, in das das Video des Herausgebers eingefügt wird. Die Freigabe eines Bildschirms ist bei modernen Browsern ähnlich wie die Freigabe einer Kamera. Durch Hinzufügen von videoSource: "screen" zu Ihren Publisher-Optionen hinzufügt, wird der Browser die richtigen Berechtigungen in Ihrem Namen anfordern. publishAudio ist optional.
Sobald Sie den neuen Verlag erstellt haben, können Sie ihn in unserer Sitzung veröffentlichen.

Es funktioniert, aber wie Sie vielleicht bemerkt haben, ist das Video zur Bildschirmfreigabe an den Rand des Fensters gedrängt, und die Schaltflächen befinden sich an einer merkwürdigen Stelle. Fügen Sie Folgendes zu Ihrer public/style.css Datei hinzu:
.screen {
width: 100%;
height: 100%;
display: flex;
}
.screen-share {
position: absolute;
bottom: 0;
right: 0;
}
.hidden {
display: none;
} Keine gemeinsame Nutzung des Bildschirms
Um die Freigabe eines veröffentlichten Streams zu beenden, benötigen Sie Zugriff auf die Variable, der er zugewiesen ist. Erstellen Sie oberhalb des Ereignis-Listeners eine leere screenSharePublisher Variable:
let screenSharePublisher;Weisen Sie im Ereignis-Listener OT.initPublisher(...) der neuen Variablen zu, indem Sie das const Schlüsselwort.
Am unteren Rand von client.js fügen Sie einen Ereignis-Listener für die Schaltfläche "Teilen beenden" hinzu:
const stopShareBtn = document.getElementById("stopScreenShare");
stopShareBtn.addEventListener("click", event => {
screenSharePublisher.destroy();
});
Beheben Sie die verbleibenden Layout-Probleme
Mittlerweile sieht Ihre Anwendung etwa so aus:

Es ist etwas besser als am Anfang, sieht aber immer noch kaputt aus. Lassen Sie uns das mit etwas CSS und Javascript (zum Umschalten der erforderlichen CSS-Klassen) in Ordnung bringen.
Entfernen wir die ursprünglichen .screen Stile aus style.css:
/* We don't need these any more */
.screen {
width: 100%;
height: 100%;
display: flex;
}Ändern Sie die .subscriber Klassenstile in der style.css wie folgt:
.subscriber,
.screen.pub-active,
.screen.sub-active {
width: 100%;
height: 100%;
display: flex;
}
.screen.sub-active ~ .subscriber,
.screen.pub-active ~ .subscriber {
position: absolute;
width: 25vmin;
height: 25vmin;
min-width: 8em;
min-height: 8em;
align-self: flex-end;
right: 0;
}Das Element, in dem sich der Screen-Sharing-Stream befindet, nimmt die gesamte Fläche des Ansichtsfensters ein, wenn es aktiv ist, während der Stream für die Kameraübertragung in der rechten unteren Ecke des Ansichtsfensters untergebracht wird.
Als nächstes müssen wir sicherstellen, dass die richtigen Klassen zu den entsprechenden Elementen hinzugefügt werden, wenn die Bildschirmfreigabe beginnt:
screenSharePublisher = OT.initPublisher(
"screen",
{
insertMode: "append",
width: "100%",
height: "100%",
videoSource: "screen",
publishAudio: true
},
handleCallback
);
session.publish(screenSharePublisher, handleCallback);
// CSS classes when screen-sharing starts
startShareBtn.classList.toggle("hidden");
stopShareBtn.classList.toggle("hidden");
document.getElementById("screen").classList.add("pub-active");Das Gegenteil muss der Fall sein, wenn die gemeinsame Nutzung von Bildschirmen aufhört:
stopShareBtn.addEventListener("click", event => {
screenSharePublisher.destroy();
// CSS classes when screen-sharing stops
startShareBtn.classList.toggle("hidden");
stopShareBtn.classList.toggle("hidden");
document.getElementById("screen").classList.remove("pub-active");
});
Jetzt sieht alles gut aus, wenn Sie die Bildschirmfreigabe starten. Aber für die Person am anderen Ende des Anrufs ist das Layout immer noch irgendwie kaputt.

Um das zu beheben, ändern wir den streamCreated Ereignis-Listener, der alle neu erstellten Streams abonniert. Wir prüfen, ob der erstellte Stream ein Kamera-Stream oder ein Bildschirmfreigabe-Stream ist. Wenn es sich um eine Bildschirmfreigabe handelt, fügen wir die sub-active CSS-Klasse hinzu.
Vorher:
session.connect(token, error => {
// Other code not included for brevity
// Subscribe to a newly created stream
session.on("streamCreated", event => {
session.subscribe(
event.stream,
"subscriber",
{
insertMode: "append",
width: "100%",
height: "100%"
},
handleCallback
);
});
});
Danach:
// Subscribe to a newly created stream
session.on("streamCreated", event => {
const streamContainer =
event.stream.videoType === "screen" ? "screen" : "subscriber";
session.subscribe(
event.stream,
streamContainer,
{
insertMode: "append",
width: "100%",
height: "100%"
},
handleScreenShare(event.stream.videoType)
);
});
// Function to handle screen share layout
function handleScreenShare(streamType, error) {
if (error) {
console.log("error: " + error.message);
} else {
if (streamType === "screen") {
document.getElementById("screen").classList.add("sub-active");
}
}
}
Außerdem müssen wir einen Ereignis-Listener hinzufügen, wenn die Bildschirmfreigabe gestoppt wird:
session.on("streamDestroyed", event => {
document.getElementById("screen").classList.remove("sub-active");
});
Für die Person, die die Bildschirmfreigabe empfängt, sollte das Ergebnis in etwa so aussehen:

Nach all dem würde Ihre client.js Datei wie folgt aussehen:
let session;
fetch(location.pathname, { method: "POST" })
.then(res => {
return res.json();
})
.then(res => {
const apiKey = res.apiKey;
const sessionId = res.sessionId;
const token = res.token;
initializeSession(apiKey, sessionId, token);
})
.catch(handleCallback);
function initializeSession(apiKey, sessionId, token) {
// Create a session object with the sessionId
session = OT.initSession(apiKey, sessionId);
// Create a publisher
const publisher = OT.initPublisher(
"publisher",
{
insertMode: "append",
width: "100%",
height: "100%"
},
handleCallback
);
// Connect to the session
session.connect(token, error => {
// If the connection is successful, initialize the publisher and publish to the session
if (error) {
handleCallback(error);
} else {
session.publish(publisher, handleCallback);
}
});
// Subscribe to a newly created stream
session.on("streamCreated", event => {
const streamContainer =
event.stream.videoType === "screen" ? "screen" : "subscriber";
session.subscribe(
event.stream,
streamContainer,
{
insertMode: "append",
width: "100%",
height: "100%"
},
handleScreenShare(event.stream.videoType)
);
});
session.on("streamDestroyed", event => {
document.getElementById("screen").classList.remove("sub-active");
});
}
// Function to handle screenshare layout
function handleScreenShare(streamType, error) {
if (error) {
console.log("error: " + error.message);
} else {
if (streamType === "screen") {
document.getElementById("screen").classList.add("sub-active");
}
}
}
// Callback handler
function handleCallback(error) {
if (error) {
console.log("error: " + error.message);
} else {
console.log("callback success");
}
}
let screenSharePublisher;
const startShareBtn = document.getElementById("startScreenShare");
startShareBtn.addEventListener("click", event => {
OT.checkScreenSharingCapability(response => {
if (!response.supported || response.extensionRegistered === false) {
alert("Screen sharing not supported");
} else if (response.extensionInstalled === false) {
alert("Browser requires extension");
} else {
screenSharePublisher = OT.initPublisher(
"screen",
{
insertMode: "append",
width: "100%",
height: "100%",
videoSource: "screen",
publishAudio: true
},
handleCallback
);
session.publish(screenSharePublisher, handleCallback);
startShareBtn.classList.toggle("hidden");
stopShareBtn.classList.toggle("hidden");
document.getElementById("screen").classList.add("pub-active");
}
});
});
const stopShareBtn = document.getElementById("stopScreenShare");
stopShareBtn.addEventListener("click", event => {
screenSharePublisher.destroy();
startShareBtn.classList.toggle("hidden");
stopShareBtn.classList.toggle("hidden");
document.getElementById("screen").classList.remove("pub-active");
});
Was kommt als Nächstes?
Der endgültige Code für Glitch und GitHub enthält alles, was wir in diesem ziemlich 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 damit 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!