Retransmisiones en directo con la Video API de Vonage
La Video API de Vonage te permite crear casi cualquier experiencia de video que desees. Un caso de uso común que tienen los desarrolladores es la necesidad de situaciones en las que una o pocas personas transmiten a una audiencia más grande que solo escucha, como los asistentes que ven una transmisión en vivo de una conferencia.
En este tutorial
La Video API de Vonage te permite armar rápidamente una sala para permitir que una sola persona transmita y que otros se unan y miren. Repasaremos cómo poner en marcha una demostración con nuestras demostraciones existentes para que no tengas que escribir ningún código, pero también explicaremos qué hace el código en segundo plano.
- Ver la demostración - Echa un vistazo a la demo sin escribir código
- Cómo funciona la demostración - El lado del cliente - Qué hace el código del lado del cliente
- Cómo funciona la demostración - El lado del servidor - Qué hace el código del lado del servidor
Requisitos previos
Para completar el tutorial, necesitas:
- A Account de Vonage - para tu clave y tu secreto de API
Ver la demostración
Si quieres echar un vistazo a la demo antes de escribir ningún código, tenemos un servidor web de muestra y código JavaScript para probar cómo es una videollamada básica. Todo el código es de código abierto y está disponible públicamente, así que puedes probar la demo y luego usar el código para hacer tus propias modificaciones.
Iniciar el servidor Node.js
El vídeo de demostración requiere un servidor backend para manejar cosas como la creación de tokens de cliente para la autorización y la gestión general de la sesión. Mientras que usted puede construir esto en cualquier idioma que desee, tenemos un servidor pre-construido que puede utilizar para empezar en el Servidor de aprendizaje por vídeo de Vonage (Node.js) en Code Hub. De la Documentación para desarrolladores, haz clic en «Code Hub» en la barra de navegación superior y, a continuación, desplázate hacia abajo hasta encontrar la ficha «Vonage Video Learning Server (Node.js)». Haz clic en ella para abrirla.
Obtendrás una descripción de lo que hace este proyecto. Por ahora, hagamos clic en "Obtener código" para que podamos cargarlo en el editor en línea Code Hub. Haz click en "Crear un nuevo entorno de desarrollo". Nombra el espacio de trabajo "Vonage Video Demo" ya que podemos usar este backend para múltiples demos. Esta demostración requiere que se le asigne un número, ya que el servidor de aprendizaje admite llamadas telefónicas a través de SIP. Aunque no lo utilizaremos en esta demostración, haz clic en "Asignar un número" para asignar un número existente de Vonage o compra uno nuevo para utilizarlo en demostraciones posteriores.

Code Hub creará automáticamente una aplicación para ti, incluida la configuración de las claves públicas y privadas que utilizará nuestra aplicación. Una vez creado el espacio de trabajo, se te redirigirá al editor de código, que es una versión en línea de Visual Studio Code. No dudes en seguir las siguientes partes de esta demostración para ver el código, y podrás editarlo según sea necesario para tus propios proyectos.

Para ejecutar la aplicación, haz clic en «Ver» en la parte superior del editor y, a continuación, en «Terminal». Se abrirá una línea de comandos en la que podremos ejecutar comandos. Solo tenemos que escribir vcr deploy y el código se implementará. Esto tardará unos instantes, ya que el sistema empaqueta el código y lo ejecuta en los servidores de Vonage Code Hub. Debemos tomar nota de la «dirección del host de la instancia» que aparece hacia el final.

Si todo funciona correctamente, debería poder visitar la "dirección del host de instancia" y aparecerá la siguiente página:

Probar el Front End
El servidor backend funciona directamente con todas nuestras demos preconstruidas, incluida esta demo individual. Vaya a https://github.com/Vonage-Community/video-api-web-samples/tree/main/Live-Broadcastque es el código fuente de la parte de front-end de esta demo. Esta muestra permite que dos usuarios con la URL se unan a la demo.
La forma más sencilla de ejecutar esta demo es hacer clic en el botón "Abrir en Stackblitz" del README.

Esto abrirá el proyecto en Stackblitz. Al igual que con el servidor backend, aquí puedes consultar el código y modificarlo si lo deseas. Para esta demostración, lo único que tendremos que hacer es abrir el js/config.js e introduzca la URL de la instancia de Code Hub en el archivo SAMPLE_SERVER_BASE_URL variable:

Una vez guardado el archivo, puede actualizar la vista de demostración en la parte derecha de Stackblitz. Esta muestra se divide en varias partes que incluyen una vista de host, y dos maneras diferentes de ver el vídeo en sí. Nos centraremos en la emisión sin RTMP.
Cómo funciona la demostración
Configurar una aplicación de Vonage
Para que nuestra aplicación de video funcione, necesitamos que nuestro cliente y servidor se comuniquen con los servidores de Vonage. Code Hub configura esto por nosotros, pero si estás ejecutando el código localmente o quieres saber qué implica una aplicación de video, se configura como cualquier otra API. Necesitamos configurar una aplicación de Vonage para alojar toda la configuración de nuestra aplicación, además de ayudarnos a generar los elementos necesarios para realizar la autenticación.
Diríjase a su Panel de control del cliente de Vonage e inicia sesión. Una vez que hayas iniciado sesión:
- Haz clic en «Applications», dentro de «Compilar».
- Haga clic en "Crear una nueva aplicación".
- Ponle un nombre a la aplicación, por ejemplo, «Demostración básica de vídeo».
- Haz clic en «Generar clave pública y privada», lo que te llevará a descargar un archivo llamado
private.key. Guarda este archivo para más adelante. - Desplácese hacia abajo y active "Vídeo". Dejaremos estos valores vacíos por ahora.
- Haga clic en "Generar nueva aplicación" para crear la aplicación.
Una vez creada la aplicación, anote el ID de la aplicación. Si está ejecutando el código localmente, lo necesitaremos para configurar el backend. Si está utilizando Code Hub, el código del servidor ya tiene acceso al ID de la Aplicación y a la Clave Privada.
El lado del cliente
La parte cliente de la demostración consta de dos partes diferentes: algunos elementos HTML para colocar las fuentes de vídeo y, a continuación, JavaScript para obtener la información de inicio de sesión y comunicarse con los servidores de Vonage Video.
Dado que se trata de una demostración para navegador, utilizamos el SDK de JavaScript que se encuentra en https://unpkg.com/@vonage/client-sdk-video@latest/dist/js/opentok.js, e incluirlo en una etiqueta `script` de nuestro código HTML en index.html.
El anfitrión
Para la vista del anfitrión, en realidad sólo necesitamos ver la cámara del anfitrión, así como alguna interfaz de usuario para controlar diferentes opciones como iniciar la emisión, activar la baja latencia y las actualizaciones de estado. Para ver tu propia cámara, hacemos un <div> elemento que contiene el elemento de vídeo:
// host.html
<div>
<h2 class="font-black text-2xl">Your Camera</h2>
<div class="h-80 w-80" id="host"></div>
</div>
El resto de la página «Host» está compuesto por botones y opciones de configuración para la propia retransmisión en directo. No modificaremos ninguna de las opciones y nos centraremos en los controles de retransmisión. Se trata simplemente de unos botones sencillos que configuraremos para que llamen a la aplicación del servidor y así iniciar y detener las señales de retransmisión.
// host.html
<div><h2 class="font-black text-2xl">Broadcast Controls</h2></div>
<div>
<button x-show="broadcastStatus == 'stopped'" x-on:click="broadcastStatus = 'started'" id="btn-start" class="bg-blue-500 bold text-white p-4 rounded">Start Broadcast</button>
<button x-show="broadcastStatus == 'started'" x-on:click="broadcastStatus = 'stopped'" id="btn-end" class="bg-red-500 bold text-white p-4 rounded">Stop Broadcast</button>
</div>
Nuestra conexión en JavaScript es mínima en comparación con otras configuraciones en las que varias personas participarán juntas. Normalmente nos conectaríamos a la sesión y luego publicaríamos inmediatamente nuestros flujos de vídeo y audio, pero como estamos controlando cuándo se inicia y se detiene una emisión, lo haremos en dos etapas. En primer lugar, nos conectamos a la sesión de forma normal:
// js/host.js
document.addEventListener('DOMContentLoaded', async () => {
const credentials = await getCredentials('host');
const session = OT.initSession(
credentials.applicationId,
credentials.sessionId,
{
connectEventsSuppressed: true
}
);
session.connect(credentials.token, (error) => {
if (error) {
console.error(error);
return;
}
let publisher = initPublisher();
// ...
Una vez que nos hayamos conectado al flujo, añadimos un detector de eventos en el btn-start botón para que, cuando el usuario lo pulse, se publique y se inicie la retransmisión. El inicio (y el fin) de la retransmisión lo gestionan los SDK del lado del servidor, por lo que enviamos una solicitud a nuestro servidor backend para iniciar la retransmisión.
// js/host.js
document.getElementById('btn-start').addEventListener('click', async (el, event) => {
const rtmp = [];
if (document.getElementById('rtmpAddress').value) {
rtmp.push({
serverUrl: document.getElementById('rtmpAddress').value,
streamName: document.getElementById('rtmpKey').value,
});
}
broadcast = await fetch(`${SAMPLE_SERVER_BASE_URL}/broadcast/session/start`, {
method: "POST",
body: JSON.stringify({
rtmp,
lowLatency: document.getElementById('lowLatency').checked,
dvr: document.getElementById('dvr').checked,
sessionId: session.id,
streamMode: "auto"
}),
headers: {
"Content-type": "application/json"
}
})
.then(res => {
// Once the broadcast starts we finally publish the host
session.publish(publisher);
shouldCheckBroadcast = true;
setTimeout(checkBroadcast, 5000);
return res.json()
})
.catch(error => console.error(error));
});
En este momento, nuestro anfitrión está retransmitiendo a través de la propia emisión, al igual que cualquier otra persona que se conecte. La demo que tenemos admite invitados, por lo que, a medida que se invita a los invitados a las reuniones, la Video API de Vonage añade automáticamente sus transmisiones a la emisión.
La aplicación del servidor se encarga de detener la emisión, por lo que una llamada rápida a esa ruta en nuestro servidor backend detendrá la emisión por sí misma. Adjuntamos un receptor de eventos a la ruta btn-stop botón que se activa al hacer clic en él.
// js/host.js
document.getElementById('btn-end').addEventListener('click', async (el, event) => {
broadcast = await fetch(`${SAMPLE_SERVER_BASE_URL}/broadcast/session/stop`, {
method: "POST",
body: JSON.stringify({
sessionId: session.id
}),
headers: {
"Content-type": "application/json"
}
})
.then(res => {
session.unpublish(publisher);
shouldCheckBroadcast = false;
publisher = initPublisher();
return res.json()
})
.catch(error => console.error(error));
});
El espectador - Stream Broadcasting
En el caso de un espectador, solo necesitamos disponer de un lugar donde mostrar la transmisión de vídeo del anfitrión. Dado que los espectadores no van a publicar sus propias transmisiones, tendremos mucho menos código de interfaz de usuario en el que trabajar con ellos. Crearemos un <div> para alojar la retransmisión del anfitrión.
// view.html
<div class="grid grid-cols-1 container mx-auto pt-4">
<h2 class="font-black text-2xl mx-auto">Host Camera</h2>
<div class="w-1/2 h-96 mx-auto" id="host"></div>
</div>
Dado que un espectador nunca publica sus propios flujos, nuestro JavaScript simplemente se conecta al flujo y se limita a esperar a que la emisión cree flujos:
// js/view.js
const credentials = await getCredentials('viewer');
const session = OT.initSession(
credentials.applicationId,
credentials.sessionId,
{
connectEventsSuppressed: true
}
);
session.connect(credentials.token, (error) => {
if (error) {
console.log(error);
return;
}
session.on('streamCreated', (event) => {
session.subscribe(event.stream, 'host', {
insertMode: 'append',
width: '100%',
height: '100%',
})
});
});
The Viewer - HLS
Para ejecutar HLS sólo es necesario añadir un <video> en lugar de utilizar un elemento <div>. Si desea utilizar HLS en su lugar, hacemos un <video> al que adjuntaremos una fuente más adelante. Tenga en cuenta que necesitará JavaScript adicional para la mayoría de los navegadores, por lo que también incluiremos la biblioteca HLS JavaScript, disponible en NPM:
// hls.html
<script src="https://cdn.jsdelivr.net/npm/hls.js@1"></script>
<div class="grid grid-cols-1 container mx-auto pt-4">
<h2 class="font-black text-2xl mx-auto">HLS Stream</h2>
<div id="host">
<video class="w-1/2 mx-auto" id="video" autoplay controls></video>
</div>
</div>
En nuestra demostración, el usuario obtiene una URL del servidor que contiene la URL de la retransmisión como parámetro de consulta. La utilizaremos para vincular esa transmisión al reproductor de vídeo. También realizaremos algunas comprobaciones básicas para asegurarnos de que se admite HLS, ya que no todos los navegadores son compatibles con HLS de forma predeterminada.
const video = document.getElementById('video');
const videoSource = new URLSearchParams(window.location.search).get('url');
if (!videoSource) {
alert('No HLS URL was passed. No video will be displayed');
return;
}
if (Hls.isSupported()) {
const hls = new Hls();
hls.on(Hls.Events.MEDIA_ATTACHED, () => {
video.muted = true;
video.play();
});
hls.loadSource(videoSource);
hls.attachMedia(video);
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = videoSource;
} else {
alert('Browser does not seem to have HLS capabilities. No video will be displayed');
return;
}
});
El lado del servidor
La parte del lado del servidor de cualquier aplicación de Vonage Video se utiliza para gestionar la creación de sesiones, la generación de tokens de autenticación y tareas administrativas como iniciar y detener los archivos. Para esta demostración, lo único que nos interesa es crear sesiones y tokens para que los usuarios puedan unirse a la sala. Aunque la API en sí es una API REST y se puede invocar como se desee, te recomendamos que utilices la SDK de Vonage Node que se encarga de toda la autenticación y las llamadas HTTP por ti. Puedes instalarlo en tu propia aplicación con:
npm install -s @vonage/server-sdk
El código de demostración ya lo tiene preinstalado. Si estás ejecutando el código de forma local, tendrás que ejecutar:
npm install
para descargar todas las dependencias y, a continuación, copiar .envcopy a un nuevo archivo llamado .env. Deberá rellenar la información solicitada en .env como el ID de la aplicación, la ubicación de la clave privada en el disco y tu clave y secreto de la API de Vonage.
El anfitrión
Le daremos al anfitrión un moderator de modo que cuando el front-end solicite las credenciales crearemos la sesión con el rol apropiado. Por lo demás, casi no hay diferencia entre la sesión de un anfitrión de retransmisiones en directo y la de un usuario de vídeo normal con el rol moderator función.
// routes/index.js
router.get('/broadcast/:name/host', async function (req, res) {
const broadcastName = req.params.name + '-broadcast';
await createSession(res, broadcastName, { initialLayoutClassList: ['full', 'focus'] }, 'moderator');
});
Para obtener más información sobre cómo crear tokens, consulta nuestra Caso práctico de vídeo individual que detalla cómo se pueden crear sesiones.
Cuando el usuario desea iniciar realmente la emisión, utilizamos el SDK de servidor para llamar a la función vonage.video.startBroadcast() que convertirá los flujos publicados en una sesión de difusión. A continuación, devolvemos esos datos al cliente para que disponga de toda la información necesaria para buscar la emisión y controlarla posteriormente.
// routes/index.js
router.post('/broadcast/:room/start', async (req, res) => {
const { rtmp, lowLatency, fhd, dvr, sessionId, streamMode } = req.body;
// Kill any existing broadcasts we have, to be safe
vonage.video.searchBroadcasts({sessionId})
.then(list => {
list.items.map(async (broadcast) => {
vonage.video.stopBroadcast(broadcast.id)
})
})
vonage.video.startBroadcast(sessionId, {outputs: {rtmp, hls: {lowLatency, dvr}}, streamMode})
.then(data => {
broadcastsToSessionIdDictionary[sessionId] = data;
res.send(data)
})
.catch(error => {
console.error(error);
res.status(500).send(error)
})
})
La finalización de la emisión es prácticamente la misma: llamamos a la función del SDK del servidor vonage.video.stopBroadcast() método para finalizar la emisión.
// routes/index.js
router.post('/broadcast/:room/stop', async (req, res) => {
const { sessionId } = req.body
if (broadcastsToSessionIdDictionary[sessionId]) {
vonage.video.stopBroadcast(broadcastsToSessionIdDictionary[sessionId].id)
.then(data => {
delete broadcastsToSessionIdDictionary[sessionId]
res.send(data)
})
.catch(err => {
console.error(err)
res.status(500).send(err)
})
}
})
El espectador - Stream Broadcasting
En una situación de retransmisión, lo único que tenemos que hacer es proporcionar al espectador el tipo adecuado de token de conexión. Todo lo demás lo gestiona el código del lado del cliente directamente en el navegador.
router.get('/broadcast/:name/viewer', async function (req, res) {
const broadcastName = req.params.name + '-broadcast';
await createSession(res, broadcastName, { initialLayoutClassList: ['full', 'focus'] }, 'subscriber');
});
The Viewer - HLS
Los espectadores que ven a través de HLS no necesitan ninguna información de conexión especial, ya que todo se canaliza a través del reproductor de vídeo y la URL de emisión. Por lo tanto, no es necesario que el código del servidor genere ningún token. Si desea restringir la visualización de una emisión, deberá incorporarlo a su aplicación.
Conclusión
En este tutorial has visto qué implica el servidor backend tanto para las retransmisiones basadas en streaming como para las basadas en HLS, cómo crear un cliente web para que los usuarios puedan ver las retransmisiones, y también has podido comprobar lo fácil que es utilizar Vonage Code Hub y Stack Blitz para probar rápidamente los ejemplos.