https://a.storyblok.com/f/270183/25746/777e2e4737/dev_stream-video_texting_1200x600.png

Transmita um bate-papo por vídeo com mensagens de texto usando a Video API da Vonage

Publicado em May 5, 2021

Tempo de leitura: 4 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. Desta vez, veremos como oferecer uma opção para que as pessoas assistam a uma transmissão do seu chat de vídeo e interajam entre si por meio de chat de texto.

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 este 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ê será capaz de participar do chat de vídeo como espectador ou como Participante. A diferença entre essas duas funções é que os espectadores podem assistir a todas as transmissões de Video publicadas e interagir com outras pessoas por meio do chat de texto, enquanto os participantes pode, além disso, publicar seu Video no chat.

Screenshot of viewer page with text chat open

O código final 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).

Este tutorial dá continuidade a um tutorial anterior: Adicionar funcionalidade de mensagens de texto a um chat por Video. Ele aborda como usar a API de sinalização para recursos de mensagens de texto em seu chat de Video.

Se esta for a primeira vez que você usa a Video API, recomendamos fortemente que leia o primeiro artigo introdutório da série: Criando um bate-papo por Video básico, pois ele aborda a configuração básica a seguir:

  • Criar um projeto da Video API da Vonage

  • Configuração no Glitch

  • Estrutura básica do projeto

  • Inicializando uma sessão

  • Conectando-se à sessão, assinando e publicando

  • Estilos básicos de layout para um bate-papo por Video

Configuração inicial

Como vamos desenvolver um chat de vídeo básico com recursos de mensagens de texto, comece adaptando o projeto criado no tutorial anterior. Clique no grande botão “Remix” abaixo para fazer isso. 👇

Remix this

Sua estrutura de pastas deve ficar mais ou menos assim:

Folder structure of the project

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ê continuará fazendo referência ao OpenTok em seu código.

Para colocar o chat por vídeo em funcionamento, acesse o .env arquivo e preencha com sua chave e seu segredo da API do seu projeto, que você pode encontrar no painel da Video API da Vonage. Depois disso, faremos algumas adições ao projeto para fornecer uma interface aos espectadores.

Adicione a marcação necessária

Nosso aplicativo será composto por três páginas: uma página inicial para que os usuários criem ou participem de uma sessão, bem como para selecionar se desejam ser espectadores ou participantes, e as duas páginas de chat por vídeo para cada função, respectivamente.

Precisaremos criar uma página adicional para o visualizador. Vamos adicionar um viewer.html arquivo à views pasta clicando no botão botão “Novo Arquivo” na barra lateral esquerda. Nomeie o arquivo views/viewer.html e cole a seguinte marcação na página. Essa página é quase igual ao index.html arquivo, exceto que não possui um div editor.

Add a viewer.html to the views folder

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Stream your video chat (enhanced)</title>
    <meta
      name="description"
      content="Stream a basic audio-video chat plus texting with Vonage Video API in Node.js"
    />
    <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>Viewer</h1>
    </header>

    <main>
      <div id="subscriber" class="subscriber"></div>
    </main>

    <footer>
      <p>
        <small
          >Built on <a href="https://glitch.com">Glitch</a> with the
          <a href="https://tokbox.com/developer/">Vonage Video API</a>.</small
        >
      </p>
    </footer>

    <script src="https://static.opentok.com/v2/js/opentok.min.js"></script>
    <script src="/client.js"></script>
  </body>
</html>

Também precisaremos adicionar um conjunto de botões de opção para que os usuários selecionem suas funções na landing.html página.

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

  <!-- Add the user type radio buttons -->
  <p>Select your role:</p>
  <fieldset>
    <label>
      <input type="radio" name="user-type" value="viewer" checked />
      <span>Viewer</span>
    </label>

    <label>
      <input type="radio" name="user-type" value="participant" />
      <span>Participant</span>
    </label>
  </fieldset>

  <label>
    <span>User name</span>
    <input
      type="text"
      name="user-name"
      placeholder="Enter your name"
      required
    />
  </label>

  <button>Enter</button>
</form>

Definir o estilo do novo fieldset

Você pode adicionar os estilos a seguir para deixar o layout padrão do fieldset e dos botões de opção um pouco mais agradável. Ou pode reformular o estilo de todos eles de uma só vez, de acordo com suas preferências.

fieldset {
  border: 0;
  display: flex;
  justify-content: space-between;
  margin-bottom: 1em;
}

fieldset label {
  padding: 0.25em 0em;
  cursor: pointer;
}

Reestruturar o JavaScript do lado do cliente

O script na parte inferior da página de destino precisa ser modificado para redirecionar os usuários para a página correta, de acordo com o tipo de usuário que eles selecionaram.

const form = document.getElementById("registration");
form.addEventListener("submit", event => {
  event.preventDefault();
  const isViewer = form.elements["user-type"].value === "viewer";

  if (isViewer) {
    location.href = `/session/viewer/${form.elements["room-name"].value}?username=${form.elements["user-name"].value}&type=viewer`;
  } else {
    location.href = `/session/participant/${form.elements["room-name"].value}?username=${form.elements["user-name"].value}&type=participant`;
  }
});

Quanto ao client.js arquivo, as variáveis declaradas no início do arquivo também precisam de alguns ajustes, já que nosso formato de URL é um pouco diferente neste tutorial.

let session;
const url = new URL(window.location.href);
// Room name is now the fourth item
const roomName = url.pathname.split("/")[3];
const userName = url.searchParams.get("username");
// Additional variable for user type
const userType = url.searchParams.get("type");

Diferentes funções no server.js arquivo gerarão tokens de assinante e de editor; portanto, essas informações serão incluídas na POST solicitação quando a página for carregada.

fetch(location.pathname, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ username: userName, type: userType })
})
  .then(res => {
    return res.json();
  })
  .then(res => {
    const apiKey = res.apiKey;
    const sessionId = res.sessionId;
    const token = res.token;
    const streamName = res.streamName;
    initializeSession(apiKey, sessionId, token, streamName);
  })
  .catch(handleCallback);

O ajuste final é na initializeSession() função, já que apenas os participantes precisam criar um editor e publicar na sessão.

function initializeSession(apiKey, sessionId, token, streamName) {
  // Create a session object with the sessionId
  session = OT.initSession(apiKey, sessionId);
  
  // Check if user type is participant
  if (userType === 'participant') {
    // If so, create a publisher
    const publisher = OT.initPublisher(
      "publisher",
      {
        insertMode: "append",
        width: "100%",
        height: "100%",
        name: streamName
      },
      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);
      }
    });
  } else {
    // Connect to the session as a viewer
    session.connect(token, error => handleCallback(error));
  }

  initiateSessionListeners(session);
}

Gerenciar rotas no servidor

No server.js arquivo, precisaremos fazer algumas alterações adicionais para disponibilizar os arquivos corretos para os espectadores e participantes, respectivamente.

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

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

Como agora temos duas páginas para cuidar, vamos transferir a POST funcionalidade do manipulador para uma função separada, que recebe userType como parâmetro para que possamos usá-la durante a geração de tokens.

app.post("/session/participant/:room", (request, response) => {
  initSession(request, response, "publisher");
});

app.post("/session/viewer/:room", (request, response) => {
  initSession(request, response, "subscriber");
});

function initSession(request, response, userType) {
  const roomName = request.params.room;
  const streamName = request.body.username;
  const isExistingSession = checkSession(roomName);

  isExistingSession.then(sessionExists => {
    if (sessionExists) {
      sessionDb
        .get(roomName)
        .then(sessionInfo => {
          generateToken(roomName, streamName, userType, sessionInfo, response);
        })
        .catch(error => error);
    } else {
      OT.createSession((error, session) => {
        if (error) {
          console.log("Error creating session:", error);
        } else {
          const sessionInfo = {
            _id: roomName,
            sessionId: session.sessionId,
            messages: []
          };
          sessionDb.put(sessionInfo);
          generateToken(roomName, streamName, userType, sessionInfo, response);
        }
      });
    }
  });
}

A generateToken() função agora recebe userType para diferenciar o token “tole” entre espectadores e participantes.

function generateToken(roomName, streamName, userType, sessionInfo, response) {
  const tokenOptions = {
    role: userType,
    data: `roomname=${roomName}?streamname=${streamName}`
  };
  let token = OT.generateToken(sessionInfo.sessionId, tokenOptions);
  response.status(200);
  response.send({
    sessionId: sessionInfo.sessionId,
    token: token,
    apiKey: process.env.API_KEY,
    streamName: streamName
  });
}

Se tudo correu bem, você deve conseguir entrar em uma sala como participante e participar de uma videoconferência com outros participantes, além de interagir com os espectadores por meio do chat de texto. Se você entrou na sala como espectador, deve conseguir assistir a uma videoconferência em andamento (desde que haja uma acontecendo) e conversar com todos os participantes da sessão por meio do chat de texto.

Screenshot of viewer page with text chat open

Não deixe de conferir o código final em Glitch ou no GitHub e fique à vontade para remixar ou clonar o código e brincar com ele por conta própria.

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 abrangente. 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.