
Teilen Sie:
Javier studied Industrial Engineering back in Madrid where he's from. He is now one of our Solution Engineers, so if you get into trouble using our APIs he may be the one that gives you a hand. Out of work he loves playing football and travelling as much as he can.
So verwenden Sie mediaStreams mit der Vonage Video API
Lesedauer: 4 Minuten
Die Vonage Video API macht es Entwicklern leicht, Video in ihre Applikationen einzubinden. Wenn Sie keine besonderen Anforderungen an Ihre Videokonferenzanwendung haben oder eine einfache Kontrolle über die Videoelemente benötigen, können Sie die Standard-Benutzeroberfläche der Vonage Video API verwenden und so die Komplexität für Ihr Entwicklungsteam reduzieren. Wenn Sie jedoch an die Arbeit mit mediaStreams zu arbeiten und Ihre Videoelemente zu handhaben, oder weil es besser zu den Designprinzipien Ihrer Videoanwendung passt, haben wir für Sie das Richtige.
Voraussetzungen
Ein Vonage Video API Account. Klicken Sie auf . Anmelden um ein Konto zu erstellen, falls Sie noch keins haben.
In diesem Blogbeitrag wird davon ausgegangen, dass Sie mit der Video API von Vonage vertraut sind. Daher konzentrieren wir uns nur auf die spezifischen Anforderungen für die Veröffentlichung und das Abonnieren Ihrer Videoelemente.
Benutzerdefinierte Video-Elemente
Um Entwicklern die Verwendung der Vonage Video API zu erleichtern, erstellt das Client SDK standardmäßig ein Videoelement, das Sie an das DOM anhängen können. Sie können jedoch auch ein eigenes HTML-Videoelement bereitstellen, wenn Sie mehr Kontrolle wünschen. In diesem Blog-Beitrag beziehen wir uns auf diese React-Anwendung als Beispiel dafür, wie Sie auf den mediaStream zugreifen und ihn als srcObject für Ihr eigenes Video-Element verwenden. Sie können sie gerne klonen und ausprobieren.
Herausgeber
Zuallererst müssen wir in unseren Publisher-Eigenschaften die Standard-Benutzeroberfläche deaktivieren, wie wir in der Entwicklerdokumentation erwähnen. Die Veröffentlichungsfunktion ist in dem Verleger-Haken
//hooks/publisher.jsx
async function publish(name, extraData) {
try {
if (!mSession.session) throw new Error('You are not connected to session');
const options = {
insertMode: 'append',
name: name,
resolution: '1280x720',
publishAudio: user.defaultSettings.publishAudio,
publishVideo: user.defaultSettings.publishVideo,
audioSource: user.defaultSettings.audioSource,
videoSource: user.defaultSettings.videoSource,
insertDefaultUI: false,
audioFallback: {
publisher: true,
},
};
const finalOptions = Object.assign({}, options, extraData);
setPublisherOptions(finalOptions);
console.log(finalOptions);
const newPublisher = OT.initPublisher(null, finalOptions);
publishAttempt(newPublisher, 1);
publisher.current = newPublisher;
} catch (err) {
console.log(err.stack);
}
}Die Logik für die Veröffentlichung in der Sitzung ist in der Funktion publishAttempt definiert. Der Einfachheit halber werden wir jedoch einen einzigen Wiederholungsversuch hardcodieren. Beachten Sie, dass wir kein Zielelement an die Veröffentlichungsfunktion übergeben, da wir auf den zugrunde liegenden mediaStream zugreifen und ihn mit unserem Videoelement verwenden möchten.
async function publishAttempt(publisher, attempt = 1, noRetry = true) {
console.log(`Attempting to publish in ${attempt} try`);
publisher.on('destroyed', handleDestroyed);
publisher.on('streamDestroyed', handleStreamDestroyed);
publisher.on('videoElementCreated', handleVideoElementCreated);
const { retry, error } = await new Promise((resolve, reject) => {
mSession.session.publish(publisher, (err) => {
if (err && noRetry) {
resolve({ retry: undefined, error: err });
}
if (err && attempt < 3) {
resolve({ retry: true, error: err });
}
if (err && attempt >= 3) {
resolve({ retry: false, error: err });
} else {
resolve({ retry: false, error: undefined });
}
});
});
if (retry) {
// Wait for 2 seconds before attempting to publish again
await delay(2000 * attempt);
await publishAttempt(publisher.current, attempt + 1);
} else if (error) {
if (noRetry) return;
alert("Publish error");
mSession.disconnect();
setIsPublishing(false);
publisher.current = null;
} else {
setIsPublishing(true);
publisher.current = publisher;
}
}Jetzt müssen wir auf das videoElementCreated Ereignis das in diesem Fall vom Herausgeber ausgelöst wird. Anstatt das Video-Element zu verwenden, das durch das videoElementCreated Ereignis gesendet wird, greifen wir auf dessen mediaStream zu, um ihn in unser eigenes Video-Element einzuspeisen. Überprüfen Sie die Implementierung der CustomPublisher-Komponente.
//Components/CustomPublisher
import React, { useEffect, useMemo, useState, useRef } from 'react';
function CustomPublisher({ mediaStream }) {
const videoRef = useRef(null);
useEffect(() => {
if (mediaStream) {
videoRef.current.srcObject = mediaStream;
}
}, [mediaStream]);
return <video width="100%" ref={videoRef} autoPlay playsInline muted></video>;
}
export default CustomPublisher;Wir fügen das autoplay Attribut hinzu, das bewirkt, dass neue Streams, die dem Element zugewiesen sind, automatisch abgespielt werden. Das playsinline Attribut ermöglicht die Inline-Wiedergabe von Videos, anstatt nur im Vollbildmodus. Wir fügen auch das Attribut "stumm" hinzu, um ein Echo zu vermeiden, da die Vonage Video API Audio über das erstellte, aber nicht im DOM gerenderte Video-Element wiedergibt.
Alles, was wir mit unserem Video-Element tun, ist, das srcObject mit dem mediaStream zu füllen, der durch das videoElementCreated Ereignis bereitgestellt wird. Der folgende Code zeigt, wie Sie den mediaStream vom Ereignis-Listener abrufen.
//hooks/publisher.jsx
publisher.on('videoElementCreated', handleVideoElementCreated);
//hooks/publisher
function handleVideoElementCreated({ element }) {
const stream = element.srcObject;
setPubStream(stream);
}Dann in unserer Zimmer-Seitekönnen wir einfach unsere CustomPublisher-Komponente rendern mit dem mediaStream als Requisite rendern. Beachten Sie, dass mPublisher nur der Import des publisher() Hook, und pubStream ist der Teil des Zustands, der unseren mediaStream enthält
//Pages/Room.index.js
{mPublisher.pubStream && <CustomPublisher mediaStream={mPublisher.pubStream}></CustomPublisher>} Abonnent
Der Ansatz, den wir zum Rendern der Abonnenten wählen, ist ähnlich, allerdings mit einer Einschränkung. Zum Zeitpunkt des Schreibens dieses Blogbeitrags für Kunden, die JS-Versionen > 2.24.7 verwenden, müssen Sie, wenn Sie mit mediaStreams auf der Abonnentenseite arbeiten, die Schritte befolgen, die in diesem Support-Artikel.
Zunächst müssen wir die Standard-Benutzeroberfläche deaktivieren, wie wir es für den Publisher getan haben. Dann, in diesem Fall, werden wir 1 Stück des Zustandes setzen. Wir werden das von Vonage erstellte Video-Element speichern, damit wir auf den zugrunde liegenden MediaStream zugreifen können. Sie werden gleich sehen, was wir mit dem Video-Element machen. Diese Logik ist definiert in dem Sitzungskontext
async function subscribe(stream, session, options = {}) {
console.log('request to subscribe');
if (session) {
console.log(session);
const finalOptions = Object.assign({}, options, {
insertMode: 'append',
width: '100%',
height: '100%',
insertDefaultUI: false,
});
const subscriber = session.current.subscribe(stream, null, finalOptions);
subscriber.on('videoElementCreated', function (event) {
const element = event.element;
element.setAttribute('id', event.target.streamId);
setSubscriberElements((prevStreams) => [...prevStreams, { element, subscriber }]);
});
addSubscribers({ subscriber });
}
}In der CustomSubscriber Komponentestellen wir unser Video-Element bereit und fügen dem von Vonage erstellten Video-Element einen Ereignis-Listener hinzu, damit wir unseren MediaStream aktualisieren können, wenn er sich ändert, wie im Artikel beschrieben.
import React, { useEffect, useRef } from 'react';
function CustomSubscriber({ element }) {
const videoRef = useRef(null);
const mediaStream = element.srcObject;
useEffect(() => {
if (mediaStream && videoRef.current) {
videoRef.current.srcObject = mediaStream;
videoRef.current.setAttribute('id', element.id);
const handleStreamChange = () => {
if (mediaStream !== element.srcObject) {
videoRef.current.srcObject = element.srcObject;
}
};
element.addEventListener('play', handleStreamChange);
return () => {
element.removeEventListener('play', handleStreamChange);
};
}
}, [element, mediaStream]);
return <video width="100%" ref={videoRef} autoPlay playsInline muted></video>;
}
export default CustomSubscriber;Wie im Fall des Publishers holen wir den mediaStream aus dem Video-Element und fügen ihn unserem Video-Element hinzu. Der Unterschied besteht darin, dass wir jetzt einen Ereignis-Listener hinzufügen müssen, um zu verstehen, wann sich der MediaStream ändert und unser Video-Element mit dem neuen MediaStream zu aktualisieren, wenn er sich ändert.
An dieser Stelle können wir die Teilnehmer auf unserer Raumseite darstellen.
{mSession.subscriberElements.length > 0 &&
mSession.subscriberElements.map((element, index) => <CustomSubscriber key={index} element={element}></CustomSubscriber>)}Beachten Sie, dass Sie das Subscriber-Objekt auch an die CustomSubscriber Komponente übergeben können, um Ihre Benutzeroberfläche basierend auf dem Status zu aktualisieren. Sie können zum Beispiel ein Overlay-Symbol für das Ein- und Ausschalten des Mikrofons anzeigen, das von der subscriber.stream.hasAudio Eigenschaft anzeigen. Auf diese Weise müssen Sie das DOM nicht manipulieren, indem Sie HTML-Elemente über dem von der Vonage Video API erstellten Video-Element einfügen/entfernen. Stattdessen werden Sie verschiedene Zustände auf der Grundlage der verschiedenen Abonnenteneigenschaften basierend auf Ihrer Anwendungslogik darstellen.
Wichtig zu beachten
Beachten Sie, dass Sie, wenn Sie diesen Ansatz verfolgen und Ihre eigenen Videoelemente anstelle der vom SDK erstellten Videoelemente verwenden, einige Funktionen, die an das Videoelement des SDK gebunden sind, nicht nutzen können. Sie werden nicht profitieren von Herausgeber-Initialen und backgroundImageUri nicht nutzen, da die Logik für diese Funktionen auf dem von Vonage erstellten Video-Element aufbaut.
Schlussfolgerung
Zusammenfassend lässt sich sagen, dass Vonage bei der Entwicklung von Video Conferencing Applications sehr flexibel ist. Standardmäßig erstellt Vonage ein Video-Element, das Sie an das DOM anhängen können. Wir unterstützen jedoch auch Anwendungsfälle, in denen Sie Ihr Videoelement bereitstellen müssen, indem Sie auf die mediaStreams der Videoelemente zugreifen, die die Vonage Video API für Sie erstellt.
Um die neuesten Nachrichten zu erhalten, verbinden Sie sich mit uns in unserer Developer Gemeinschaft Slack, auf X, früher bekannt als Twitterund bei Veranstaltungen.