Vídeo com múltiplos participantes usando a Video API da Vonage
A Video API da Vonage permite que você crie praticamente qualquer experiência de vídeo que desejar. Um caso de uso comum entre os desenvolvedores é a presença de vários usuários em uma única sala, como em uma reunião de equipe. Em muitos casos, essas sessões de vídeo precisarão ser gravadas. Fazer as duas coisas é fácil com a Video API da Vonage.
Neste tutorial
A Video API da Vonage permite que você crie rapidamente uma sala e adicione participantes a ela. Vamos mostrar como configurar uma demonstração usando nossos exemplos já prontos, para que você não precise escrever nenhum código, mas também explicaremos o que o código está fazendo nos bastidores.
- Veja a demonstração - Confira a demonstração sem precisar escrever nenhum código
- Como funciona a demonstração – Lado do cliente - O que o código do lado do cliente está fazendo
- Como funciona a demonstração – O lado do servidor - O que o código do lado do servidor está fazendo
Pré-requisitos
Para concluir o tutorial, você precisa de:
- A Account da Vonage - para sua chave e seu segredo da API
Veja a demonstração
Se você quiser conferir a demonstração antes de escrevermos qualquer código, temos um servidor web de exemplo e um código em JavaScript para você testar como funciona uma videochamada básica. Todo o código é de código aberto e está disponível publicamente; assim, você pode experimentar a demonstração e, em seguida, usar o código para fazer suas próprias modificações.
Inicie o servidor Node.js
A demonstração em vídeo requer um servidor de back-end para lidar com tarefas como a criação de tokens de cliente para autorização e o gerenciamento geral de sessões. Embora você possa desenvolvê-lo em qualquer linguagem de sua preferência, temos um servidor já pronto que você pode usar para começar, disponível em Servidor de Aprendizado por Vídeo da Vonage (Node.js) no Code Hub. A partir do Documentação para desenvolvedores, clique em “Code Hub” na barra de navegação superior e, em seguida, role a página para baixo até encontrar o cartão “Vonage Video Learning Server (Node.js)”. Clique nele para abri-lo.
Você receberá uma descrição do que este projeto faz. Por enquanto, vamos clicar em “Obter código” para que possamos carregá-lo no editor online do Code Hub. Clique em “Criar um novo ambiente de desenvolvimento”. Nomeie o espaço de trabalho como “Vonage Video Demo”, já que podemos usar esse back-end para várias demonstrações. Esta demonstração exige que um número seja atribuído a ela, já que o servidor de aprendizagem suporta chamadas telefônicas via SIP. Embora não vamos usar isso nesta demonstração, vá em frente e clique em “Atribuir um número” para atribuir um número existente que você tenha da Vonage ou compre um novo para usar em demonstrações futuras.

O Code Hub criará automaticamente um aplicativo para você, incluindo a configuração das chaves pública e privada que nosso aplicativo utilizará. Assim que o espaço de trabalho for criado, você será direcionado para o editor de código, que é uma versão online do Visual Studio Code. Fique à vontade para acompanhar as partes seguintes desta demonstração para ver o código, e você pode editá-lo conforme necessário para seus próprios projetos.

Para executar o aplicativo, clique em “Exibir” na parte superior do editor e, em seguida, em “Terminal”. Isso abrirá uma linha de comando na qual podemos executar comandos. Basta digitar vcr deploy e o código será implantado. Isso levará alguns instantes, pois o sistema empacota o código e o executa nos servidores do Vonage Code Hub. É importante anotar o “endereço do host da instância” que é exibido perto do final.

Se tudo estiver funcionando corretamente, você deverá conseguir acessar o “endereço do host da instância” e ver a seguinte página:

Teste o front-end
O servidor de back-end funciona diretamente com todas as nossas demonstrações pré-criadas, incluindo esta demonstração individual. Acesse https://github.com/Vonage-Community/Video API web samples/tree/main/Archiving, que é o código-fonte da parte front-end desta demonstração. Este exemplo permite que vários usuários, por meio da URL, participem de um bate-papo por voz e criem gravações da sessão, chamadas de “Arquivos”.
A maneira mais fácil de executar esta demonstração é clicar no botão “Abrir no Stackblitz” no arquivo README.

Isso abrirá o projeto no Stackblitz. Assim como no servidor de back-end, você pode examinar o código e modificá-lo aqui, se quiser. Para esta demonstração, tudo o que precisamos fazer é abrir o js/config.js arquivo e insira a URL da instância do Code Hub no SAMPLE_SERVER_BASE_URL variável:

Depois de salvar o arquivo, você pode atualizar a visualização da demonstração no lado direito do Stackblitz, e seu navegador deve solicitar que você autorize o uso do microfone e da câmera. Assim que você autorizar, sua imagem deve aparecer no canto inferior da barra lateral. Se você copiar a URL do Stackblitz acima do painel de demonstração e acessá-la no seu celular, em outro computador ou enviá-la a um amigo, qualquer pessoa que acessar o link deverá estar conectada à sua demonstração!
Como funciona a demonstração
Configurar uma aplicação da Vonage
Para que nosso aplicativo de vídeo funcione, precisamos de uma maneira de nosso cliente e servidor se comunicarem com os servidores da Vonage. O Code Hub configura isso para nós, mas se você estiver executando o código localmente ou quiser saber o que isso envolve, saiba que um aplicativo de vídeo é configurado exatamente como qualquer outra API. Precisamos configurar uma aplicação da Vonage para abrigar toda a configuração da nossa aplicação, além de ajudar a gerar os itens necessários para que possamos realizar a autenticação.
Dê uma passada no seu Painel do Cliente da Vonage e faça login. Depois de fazer login:
- Clique em “Applications” na seção “Compilação”.
- Clique em “Criar um novo aplicativo”.
- Dê um nome ao aplicativo, como “Demonstração básica de vídeo”.
- Clique em “Gerar chave pública e privada”, o que fará com que você baixe um arquivo chamado
private.key. Guarde esse arquivo para consultar mais tarde. - Role a página para baixo e ative a opção “Vídeo”. Por enquanto, vamos deixar esses campos em branco.
- Clique em “Gerar novo pedido” para criar o pedido.
Assim que o aplicativo for criado, anote o ID do aplicativo. Se você estiver executando o código localmente, precisaremos desse ID para configurar o backend. Se estiver usando o Code Hub, o código do servidor já tem acesso ao ID do aplicativo e à chave privada.
O lado do cliente
A parte do lado do cliente da demonstração consiste em dois elementos distintos: alguns elementos HTML para inserir os feeds de vídeo e, em seguida, um código JavaScript para obter as informações de login e se comunicar com os servidores da Vonage Video.
Como se trata de uma demonstração no navegador, utilizamos o SDK do JavaScript disponível em https://unpkg.com/@vonage/client-sdk-video@latest/dist/js/opentok.js, e incluir isso em uma tag script no nosso HTML em index.html.
Para adicionar pessoas a uma sala, precisamos apenas de dois elementos: um lugar para colocar o usuário atual — por exemplo, você —, que chamamos de “publisher”. Em seguida, precisamos de um lugar para colocar qualquer outra pessoa que entre na sala, à qual você irá “se inscrever”. Vamos colocá-las em um elemento “subscriber”.
Vamos criar dois div elementos e atribuir a um deles um ID de publisher e o outro, um ID de subscriber. Faremos referência a esses elementos no JavaScript quando a página for acessada e quando detectarmos que outro usuário entrou na videochamada.
Também criamos dois botões para controlar o início e a interrupção dos arquivos, bem como um espaço reservado para inserir a URL do arquivo assim que sua renderização for concluída.
// index.html
<div id="videos">
<div id="subscriber"></div>
<div id="publisher"></div>
</div>
<div id="buttonHolder">
<div id="buttons">
<button type="button" id="start">Start Archive</button>
<button type="button" id="stop">Stop Archive</button>
<span id="archiveLink"></span>
</div>
</div>
Manipulação de vídeo
No JavaScript, vamos primeiro obter algumas informações sobre a própria videochamada. Para nos conectarmos à videochamada, precisamos de um ID de aplicativo, um ID de sessão e um token.
- O ID do aplicativo é um identificador que o Client SDK do cliente utiliza para fazer referência a diferentes configurações do nosso aplicativo de vídeo no lado da Vonage.
- O ID da sessão é uma sessão de vídeo específica à qual queremos nos conectar, já que uma única Application pode ter várias sessões de vídeo simultâneas ao mesmo tempo.
- O Token é um token de autenticação JWT que permite que você participe de uma sessão específica com direitos específicos.
Embora seja possível gerar o ID de sessão e o token com antecedência, na prática você os gerará conforme a necessidade. Nosso código mostra como fazer isso. Mostraremos como essas informações são criadas daqui a pouco, mas vamos obtê-las do servidor de back-end que implantamos.
// src/app.js
// ...
} else if (SAMPLE_SERVER_BASE_URL) {
// Make a GET request to get the Vonage Video Application ID, session ID, and token from the server
fetch(SAMPLE_SERVER_BASE_URL + '/session')
.then((response) => response.json())
.then((json) => {
applicationId = json.applicationId;
sessionId = json.sessionId;
token = json.token;
// Initialize a Vonage Video Session object
initializeSession();
}).catch((error) => {
handleError(error);
alert('Failed to get Vonage Video sessionId and token. Make sure you have updated the config.js file.');
});
}
Assim que tivermos todas as informações de conexão, podemos prosseguir e chamar o SDK do JavaScript do Vonage Video, que se encarrega de todo o trabalho de conexão com a Video API do Vonage no front-end. Primeiro, obtemos um objeto de sessão com OT.initSession(). Em seguida, começamos a escutar no streamCreated evento com session.on(). Isso nos permite definir uma função de retorno a ser executada quando um stream de outro publisher for criado. Nesse caso, usamos session.subscribe() para se conectar ao evento recebido e enviá-lo para o subscriber div que definimos no HTML. Também monitoramos o sessionDisconnected evento para saber quando o outro usuário se desconecta, mas, nesta demonstração, limitamo-nos apenas a registrar que percebemos que ele saiu.
Em seguida, criamos o publisher objeto com OT.initPublisher(). Indicamos a qual div ele deve ser anexado (publisher), além de algumas opções básicas de formatação. Isso conecta sua câmera e seu microfone à Video API.
Em seguida, chamamos session.connect() para se conectar à sessão, usando o token JWT de conexão que obtivemos do servidor. É só isso que basta para duas pessoas entrarem em uma sala!
// src/app.js
function initializeSession() {
const session = OT.initSession(applicationId, sessionId);
// Subscribe to a newly created stream
session.on('streamCreated', (event) => {
const subscriberOptions = {
insertMode: 'append',
width: '100%',
height: '100%'
};
session.subscribe(event.stream, 'subscriber', subscriberOptions, handleError);
});
session.on('sessionDisconnected', (event) => {
console.log('You were disconnected from the session.', event.reason);
});
// initialize the publisher
const publisherOptions = {
insertMode: 'append',
width: '100%',
height: '100%',
resolution: '1280x720'
};
const publisher = OT.initPublisher('publisher', publisherOptions, handleError);
// Connect to the session
session.connect(token, (error) => {
if (error) {
handleError(error);
} else {
// If the connection is successful, publish the publisher to the session
session.publish(publisher, handleError);
}
});
}
Manuseio de arquivos
O gerenciamento propriamente dito dos arquivos é feito no lado do servidor do aplicativo, mas precisamos de uma maneira de instruir o sistema a iniciar e interromper a criação dos arquivos. Vamos utilizar os botões que adicionamos ao HTML, bem como o <span> para inserir uma URL mais tarde. Já que estamos nisso, também vamos ocultar o botão “Parar”, já que não precisamos exibi-lo até iniciarmos um arquivamento.
// src/app.js
const archiveStartBtn = document.querySelector('#start');
const archiveStopBtn = document.querySelector('#stop');
const archiveLinkSpan = document.querySelector('#archiveLink');
archiveStopBtn.style.display = "none";
Enviaremos algumas solicitações HTTP ao nosso servidor de back-end para, de fato, iniciar e interromper o arquivamento. Atribuiremos uma função aos eventos de clique dos nossos botões de iniciar e parar. O aplicativo do servidor terá código para se comunicar com a Video API do Vonage a fim de manipular os próprios arquivos.
// src/app.js
async function startArchiving(){
console.log('start archiving');
try {
archive = await postData(SAMPLE_SERVER_BASE_URL +'/archive/start',{sessionId});
console.log('archive started: ', archive);
if (archive.status !== 'started'){
handleError(archive.error);
} else {
console.log('successfully started archiving: ',archive);
}
}
catch(error){
handleError(error);
}
}
async function stopArchiving(){
console.log('stop archiving');
try {
archive = await postData(`${SAMPLE_SERVER_BASE_URL}/archive/${archive.id}/stop`,{});
console.log('archive stopped: ', archive);
if (archive.status !== 'stopped'){
handleError(archive.error);
} else {
console.log('successfully stopped archiving: ',archive);
}
}
catch(error){
handleError(error);
}
}
archiveStartBtn.addEventListener('click', startArchiving, false);
archiveStopBtn.addEventListener('click', stopArchiving, false);
A última coisa que precisamos fazer é monitorar os eventos do JavaScript relacionados ao arquivamento. Esses são um archiveStarted evento e um archiveStopped evento. Isso permite que o SDK saiba que essas operações estão sendo executadas, e podemos ajustar nossa interface de usuário com base no que está acontecendo. É melhor lidar com isso por meio do SDK, em vez das funções de ouvinte de eventos que criamos acima, pois assim sabemos imediatamente quando a própria Video API da Vonage executou as ações.
// src/app.js
session.on('archiveStarted', (event) => {
archive = event;
console.log('Archive started ' + archive.id);
archiveStartBtn.style.display = 'none';
archiveStopBtn.style.display = 'inline';
archiveLinkSpan.innerHTML = '';
});
session.on('archiveStopped', (event) => {
archive = event;
console.log('Archive stopped ' + archive.id);
archiveStartBtn.style.display = 'inline';
archiveStopBtn.style.display = 'none';
archiveLinkSpan.innerHTML = `<a href="${SAMPLE_SERVER_BASE_URL}/archive/${archive.id}/view" target="_blank">View Archive</a>`;
});
Quando o arquivamento começa, ocultamos o botão “Iniciar” e exibimos o botão “Parar”. Quando o arquivamento termina, ocultamos o botão “Parar” e preenchemos nosso <span> com a URL para visualizar o arquivo. Essa URL faz parte do servidor de back-end que implantamos anteriormente e não é a URL onde o próprio arquivo está armazenado. Para isso, você precisará acompanhar os eventos do lado do servidor.
O lado do servidor
A parte do lado do servidor de qualquer aplicativo Vonage Video é usada para lidar com a criação de sessões, a geração de tokens de autenticação e tarefas administrativas, como iniciar e interromper arquivamentos. Para esta demonstração, nosso único objetivo é criar sessões e tokens para que os usuários possam entrar na sala. Embora a API em si seja uma API REST e possa ser chamada da maneira que você preferir, recomendamos que você use a SDK do Vonage Node que cuida de toda a autenticação e das chamadas HTTP para você. Você pode instalá-lo em seu próprio aplicativo com:
npm install -s @vonage/server-sdk
O código de demonstração já vem com isso pré-instalado. Se você estiver executando o código localmente, precisará executar:
npm install
para baixar todas as dependências e, em seguida, copiar .envcopy em um novo arquivo chamado .env. Você precisará preencher as informações solicitadas em .env como o ID do aplicativo, o local da chave privada no disco e sua chave e segredo da API da Vonage.
Criação de sessão e participação na sessão
A primeira coisa que fazemos é verificar se já temos uma sessão para a sala que estamos gerando. Mantemos um dicionário na memória em roomToSessionIdDictionary, e se a sala já tiver uma sessão, simplesmente recuperamos essa sessão do dicionário. Em seguida, usamos o SDK do Vonage Video Node para criar um token de cliente chamando vonage.video.generateClientToken(), passando a ele o ID da sessão e um objeto com algumas configurações. No momento, tudo o que fazemos é definir o usuário como um moderator função para esta demonstração simples. Em seguida, retornamos o ID da aplicação, o ID da sessão e o token configurados de volta ao front-end.
Se a sessão não existir, criamos uma nova com vonage.video.createSession(). Isso acessa a API da Vonage e cria uma sessão à qual os usuários podem se conectar. Não temos nenhuma configuração específica para essa sessão, mas seria aqui que definiríamos itens como regras de arquivamento e como a sessão deve ser tratada, seja por roteamento ou ponto a ponto. Em seguida, assim como antes, criamos um token e enviamos todas essas informações de volta ao navegador.
// routes/index.js
async function createSession(response, roomName, sessionProperties = {}, role = 'moderator') {
let sessionId;
let token;
console.log(`Creating ${role} creds for ${roomName}`);
if (roomToSessionIdDictionary[roomName]) {
sessionId = roomToSessionIdDictionary[roomName];
// generate token for user
token = vonage.video.generateClientToken(sessionId, { role })
response.setHeader('Content-Type', 'application/json');
response.send({
applicationId: appId,
sessionId: sessionId,
token: token
});
} else {
try {
// Create the session
const session = await vonage.video.createSession(sessionProperties);
roomToSessionIdDictionary[roomName] = session.sessionId;
// generate token for user
token = vonage.video.generateClientToken(session.sessionId, { role });
response.setHeader('Content-Type', 'application/json');
response.send({
applicationId: appId,
sessionId: session.sessionId,
token: token
});
} catch(error) {
console.error("Error creating session: ", error);
response.status(500).send({ error: 'createSession error:' + error });
}
}
}
Manuseio de arquivos
Assim como a maioria dos recursos de gerenciamento e administração da Video API da Vonage, o gerenciamento de arquivos é feito por meio da API REST e dos nossos SDKs de servidor. Recebemos as solicitações do lado do cliente para iniciar e interromper um arquivo, mapeamos essas solicitações para uma rota em nosso servidor de back-end e chamamos vonage.video.startArchive() para criar um arquivo, e vonage.video.stopArchive() para interromper um arquivamento em andamento.
Quando iniciamos um arquivamento, enviamos as informações geradas de volta ao cliente. Dessa forma, ele sabe qual arquivamento interromper posteriormente. Ao interromper o arquivamento, também enviamos seu status, caso o cliente precise atualizar alguma coisa.
Essas chamadas acabarão por gerar o archiveStarted e archiveStopped Eventos do SDK que monitoramos.
// routes/index.js
router.post('/archive/start', async function (req, res) {
console.log('attempting to start archive');
const json = req.body;
const sessionId = json.sessionId;
try {
const archive = await vonage.video.startArchive(sessionId, { name: findRoomFromSessionId(sessionId) });
console.log("archive: ", archive);
res.setHeader('Content-Type', 'application/json');
res.send(archive);
} catch (error){
console.error("error starting archive: ",error);
res.status(500).send({ error: 'startArchive error:' + error });
}
});
router.post('/archive/:archiveId/stop', async function (req, res) {
const archiveId = req.params.archiveId;
console.log('attempting to stop archive: ' + archiveId);
try {
const archive = await vonage.video.stopArchive(archiveId);
res.setHeader('Content-Type', 'application/json');
res.send(archive);
} catch (error){
console.error("error stopping archive: ",error);
res.status(500).send({ error: 'stopArchive error:', error });
}
});
Para visualizar o arquivo, precisamos ter certeza de que ele está disponível. Quando o usuário clica no link na interface do usuário para visualizar o arquivo, a solicitação passa por uma rota no servidor de back-end que verifica se o arquivo está de fato pronto. Se o status for available, redirecionamos para a URL de armazenamento real do vídeo. Em seguida, deixamos que o navegador exiba o vídeo arquivado de forma nativa, já que a maioria dos principais navegadores é compatível com o formato MP4.
// routes/index.js
router.get('/archive/:archiveId/view', async function (req, res) {
const archiveId = req.params.archiveId;
console.log('attempting to view archive: ' + archiveId);
try {
const archive = await vonage.video.getArchive(archiveId);
if (archive.status === 'available') {
res.redirect(archive.url);
} else {
res.render('view', { title: 'Archiving Pending' });
}
} catch (error){
console.log("error viewing archive: ",error);
res.status(500).send({ error: 'viewArchive error:' + error });
}
});
Conclusão
Neste tutorial, você viu o que é necessário no servidor de back-end para uma sessão de vídeo com vários participantes, como criar um cliente web para que os usuários possam entrar em uma sessão e ver e ouvir uns aos outros, como gravar uma sessão de vídeo e visualizá-la, além de ter uma ideia de como é fácil usar o Vonage Code Hub e o Stack Blitz para testar rapidamente exemplos de código.