https://a.storyblok.com/f/270183/41165/f32a02b216/e_vonage-video-api_1200x600-1.png

Crie um chat de vídeo básico com a Video API da Vonage

Publicado em April 20, 2021

Tempo de leitura: 6 minutos

Esta série de tutoriais explorará a Video API da Vonage (anteriormente TokBox OpenTok) e o que você pode criar com ela. A Video API é muito robusta e altamente personalizável, e em cada postagem mostraremos como implementar um recurso específico usando a API, começando pelo chat de áudio e vídeo mais básico.

Como essa aplicação exigirá algum código do lado do servidor, vamos usar o Glitch para facilitar a configuração. Você também pode baixar o código deste projeto do Glitch e implantá-lo no seu servidor ou na plataforma de hospedagem de sua escolha (provavelmente será necessário fazer alguns ajustes de configuração de acordo com os requisitos da sua plataforma).

Não utilizaremos nenhum framework de front-end nesta série, apenas JavaScript puro, para manter o foco na própria Video API. Ao final deste tutorial, você deverá ser capaz de iniciar um bate-papo com áudio e vídeo com um amigo, compartilhando um link com ele.

Screenshot of video chat

Todo o código deste aplicativo pode ser encontrado neste repositório do GitHub ou modificado no Glitch.

Pré-requisitos

Antes de começarmos, você precisará de um Account da Video API da Vonage, que pode ser criado gratuitamente aqui. Você também precisará do do Node.js instalado (caso você não esteja usando o Glitch).

Criar um projeto de API

Depois de fazer login na sua conta, você verá a interface do seu painel. Você pode criar um novo projeto selecionando “Criar novo projeto” na barra lateral esquerda.

Serão apresentadas duas opções: Incorporar ou API. Escolha a opção API clicando no botão Criar projeto personalizado .

Na próxima etapa, será solicitado o nome do seu projeto e o codec de sua preferência. Dê ao seu projeto o nome que desejar e escolha a opção de codec sugerida: VP8 por enquanto. Detalhes sobre a diferença entre VP8 e H.264 estão descritos aqui.

Assim que seu projeto for criado, você terá acesso à sua chave e ao seu segredo da API. Cada projeto terá sua própria chave e seu próprio segredo da API.

Configuração no Glitch

Se você optar por não usar o Glitch, pode pular esta parte e ir direto para a análise passo a passo do código e a explicação na próxima seção.

Na página inicial do Glitch, selecione Novo Projeto no canto superior direito da página e escolha o opção hello-express , que fornece um aplicativo Node com o Express instalado.

Glitch landing page

Você pode instalar bibliotecas adicionais pela linha de comando, abrindo o console. Clique no botão “Ferramentas” na parte inferior da barra lateral esquerda e, em seguida, clique em Logs.

Screenshot showing the location of the Tools button

Instale o SDK do servidor da Video API da Vonage usando o seguinte comando:

pnpm install opentok --save

Observe o uso de pnpm em vez de npm, que é o gerenciador de pacotes preferido no Glitch. Ele faz a mesma coisa que npm.

Screenshot of Glitch terminal after opentok is installed

Depois de fazer isso, vá em frente e limpe o server.js arquivo para remover o código de espaço reservado desnecessário.

Screenshot of the server.js file on Glitch

Acesse o .env arquivo e adicione sua chave e seu segredo da Video API do seu projeto da Video API da Vonage.

Screenshot of the .env file on Glitch

Estrutura básica do projeto

Esta é a estrutura de pastas exibida ao iniciar um novo Glitch hello-express :

Folder structure of the project

Nosso aplicativo será composto por duas páginas: uma página inicial para os usuários criarem uma sessão (vamos chamá-la de “Sala”, e os participantes subsequentes poderão entrar nessa mesma “Sala”) e, em seguida, a página propriamente dita do chat por vídeo.

Vamos adicionar um landing.html arquivo à views pasta clicando no botão botão “Novo Arquivo” na barra lateral esquerda. Nomeie o arquivo views/landing.html e cole a seguinte marcação na página. A página terá um elemento de formulário simples com um campo de entrada que permite aos usuários enviar o nome de uma sala. Você pode usar a seguinte marcação caso não queira escrever a sua própria do zero.

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Basic Video Chat</title>
    <meta name="description" content="A basic audio-video chat application" />
    <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>The most basic video chat</h1>
    </header>

    <main>
      <form id="registration" class="registration">
        <label>
          <span>Room</span>
          <input
            type="text"
            name="room-name"
            placeholder="Enter room name"
            required
          />
        </label>
        <button>Enter</button>
      </form>
    </main>
  </body>
</html>

Creating a new file in your Glitch project

A index.html página também será relativamente simples por enquanto, com dois div elementos: um para o assinante e outro para o provedor. Veremos o que esses termos significam quando chegarmos à seção sobre a Video API da Vonage neste tutorial.

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Basic Video Chat</title>
    <meta name="description" content="A basic audio-video chat application" />
    <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>The most basic video chat</h1>
    </header>

    <main>
      <div id="subscriber" class="subscriber"></div>
      <div id="publisher" class="publisher"></div>
    </main>
    
    <script src="https://static.opentok.com/v2/js/opentok.min.js"></script>
    <script src="/client.js"></script>
  </body>
</html>

Para o server.js arquivo, vamos remover o código de preenchimento desnecessário. Você deve ficar com algo assim:

const express = require("express");
const app = express();

app.use(express.static("public"));

app.get("/", (request, response) => {
  response.sendFile(__dirname + "/views/index.html");
});

const listener = app.listen(process.env.PORT, () => {
  console.log("Your app is listening on port " + listener.address().port);
});

Por fim, vamos também apagar os estilos existentes dentro do style.css arquivo para que possamos substituí-los pelos nossos próprios assim que tivermos tudo configurado.

A visão geral de como a Video API da Vonage funciona para conectar as pessoas e permitir que elas façam uma videochamada é a seguinte:

  • Passo 1: A sessão é criada pelo servidor de aplicativos

  • Etapa 2: Um cliente abre o aplicativo e o servidor gera um token

  • Etapa 3: O cliente se conecta e começa a transmitir para a sessão

  • Etapa 4: Um novo cliente se conecta à sessão

  • Etapa 5: Os clientes se inscrevem nos fluxos uns dos outros

Uma introdução completa, com GIFs animados que mostram todo o fluxo, está disponível no site de documentação da Video API da Vonage.

Inicializando uma sessão

Conforme mencionado no início, o TokBox OpenTok agora é a Video API da Vonage. Não fizemos nenhuma alteração nos nomes dos nossos pacotes, portanto, você ainda deverá fazer referência ao OpenTok em seu código. Comece instanciando um objeto OpenTok com sua chave de API e seu segredo no server.js arquivo.

const OpenTok = require("opentok");
const OT = new OpenTok(process.env.API_KEY, process.env.API_SECRET);

Vamos modificar as rotas das nossas duas páginas para que os usuários vejam a página inicial no primeiro carregamento, o que lhes permite inserir o nome de uma sala para iniciar uma sessão. Assim que isso for feito com sucesso, eles serão redirecionados para a página principal do aplicativo, onde o Video será exibido.

app.get("/", (request, response) => {
  response.sendFile(__dirname + "/views/landing.html");
});

app.get("/session/:room", (request, response) => {
  response.sendFile(__dirname + "/views/index.html");
});

No nosso landing.html arquivo, vamos adicionar um manipulador de eventos para o envio do formulário, que irá POST o nome da sala para o nosso servidor. Como são quatro linhas de código, vamos adicioná-lo como uma tag de script na parte inferior da página.

const form = document.getElementById("registration");
form.addEventListener("submit", event => {
  event.preventDefault();
  location.pathname = `/session/${form.elements["room-name"].value}`;
});

Isso significa que teremos que lidar com a POST rota no server.js arquivo. O trecho de código a seguir é bastante longo, por isso incluí explicações como comentários no código. Em resumo, ele verificará se já existe uma sessão ou criará uma nova, se necessário, com base no nome da sala inserido na página inicial. Cada sessão possui um ID exclusivo, o que permite que outras pessoas participem dela.

Esse código irá, então, gerar as credenciais necessárias para que o cliente se conecte à sessão. Elas consistem no ID da sessão, um token e a chave da API. Essas credenciais serão enviadas de volta ao cliente como resposta.

let sessions = {};

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 OpenTok 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
  });
}

Conectando-se à sessão, inscrevendo-se e publicando

No lado do cliente, primeiro criamos um objeto de sessão com a chave da API e o ID da sessão obtidos da resposta. Também precisamos criar um objeto publisher, que substituirá o elemento div pelo id=publisher com o seu feed de Video.

Vamos nos conectar à sessão usando o session.connect() método e, se for bem-sucedido, publicaremos nosso stream de Video com o session.publish() método.

Também iremos monitorar o streamCreated evento para que possamos nos inscrever para receber notificações sobre os usuários que entrarem na sessão depois que nos conectarmos a ela.

// Create a session object with the session ID
const session = OT.initSession(apiKey, sessionId);

// Create a publisher
const publisher = OT.initPublisher(
  "publisher", // should match the ID of an element in your HTML
  {
    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 => {
  session.subscribe(
    event.stream,
    "subscriber",
    {
      insertMode: "append",
      width: "100%",
      height: "100%"
    },
    handleCallback
  );
});

// Callback handler
function handleCallback(error) {
  if (error) {
    console.log("error: " + error.message);
  } else {
    console.log("callback success");
  }
}

Quando o formulário com o nome da sala for enviado, faremos uma POST solicitação à /session/:room rota e usaremos os dados da resposta para executar a funcionalidade detalhada acima. Para isso, vamos agrupar tudo em uma função chamada initializeSession() da seguinte forma:

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
  const 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 => {
    session.subscribe(
      event.stream,
      "subscriber",
      {
        insertMode: "append",
        width: "100%",
        height: "100%"
      },
      handleCallback
    );
  });
}

Algumas alterações de estilo para deixar tudo mais organizado

A funcionalidade geral do nosso chat Video já está pronta, então só falta adicionar alguns estilos para ajustar o layout. Os dois div elementos (para assinante e editor) terão seus conteúdos substituídos por seus respectivos feeds de Video.

Markup when publisher is publishing to the session

Este é o estilo de layout mais básico para fazer com que a transmissão de Video do seu editor seja exibida no canto inferior esquerdo da página, enquanto as outras pessoas na transmissão ocupam todo o fundo da página.

html {
  box-sizing: border-box;
  height: 100%;
}

*,
*::before,
*::after {
  box-sizing: inherit;
  margin: 0;
  padding: 0;
}

body {
  height: 100%;
  display: flex;
  flex-direction: column;
}

header {
  text-align: center;
  padding: 0.5em;
}

main {
  flex: 1;
  display: flex;
  position: relative;
}

input,
button {
  font-size: inherit;
  padding: 0.5em;
}

.registration {
  display: flex;
  flex-direction: column;
  margin: auto;
}

.registration input[type="text"] {
  display: block;
  margin-bottom: 1em;
}

.subscriber {
  width: 100%;
  height: 100%;
  display: flex;
}

.publisher {
  position: absolute;
  width: 25vmin;
  height: 25vmin;
  min-width: 8em;
  min-height: 8em;
  align-self: flex-end;
}

Esses estilos oferecem o chat por Video mais básico, com o layout mais simples, que você já viu no início deste tutorial.

Screenshot of landing page

Screenshot of video chat

Você pode então adicionar qualquer elemento de estilo visual, como fontes, cores e até mesmo imagens de logotipo, se quiser, para dar um toque especial.

E agora?

Existem funcionalidades adicionais que podemos desenvolver com a Video API da Vonage, que serão abordadas em tutoriais futuros; mas, enquanto isso, você pode saber mais em nosso site de documentação completa. Se você tiver algum problema ou dúvida, entre em contato conosco na nossa Slack da Comunidade. Obrigado pela leitura!

Compartilhar:

https://a.storyblok.com/f/270183/384x384/46621147f0/huijing.png
Hui Jing ChenEx-funcionários da Vonage

Hui Jing é Developer Advocate na Nexmo. Ela tem um amor imenso por CSS e tipografia e, de modo geral, é apaixonada por tudo que diz respeito à web.