
Compartilhar:
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.
Compartilhe sua tela com a Video API da Vonage
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 adicionar o compartilhamento de tela ao seu chat básico de áudio e vídeo.
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 compartilhar sua tela com a pessoa com quem estiver conversando por vídeo.

O código final deste aplicativo pode ser encontrado neste repositório do GitHub ou modificado no Glitch.
Pré-requisitos
Antes de começar, 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 não esteja usando o Glitch).
Este tutorial dá continuidade ao primeiro post introdutório da série: Criação de um chat de vídeo básico. Se esta for a primeira vez que você usa a Video API, recomendamos fortemente que você leia esse post, 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 do OpenTok
Conectando-se à sessão, assinando e publicando
Estilos básicos de layout para um bate-papo por Video
Prepare-se para várias transmissões publicadas
No aplicativo anterior, seu navegador se conectava à sessão e publicava um único fluxo (sua câmera). No entanto, com a adição do compartilhamento de tela, você pode estar publicando dois fluxos na mesma sessão. Para lidar com isso, em public/client.js, mova o session para uma variável global.
Antes:
function initializeSession(apiKey, sessionId, token) {
const session = OT.initSession(apiKey, sessionId);
// more code below
}Depois:
let session;
function initializeSession(apiKey, sessionId, token) {
session = OT.initSession(apiKey, sessionId);
// more code below
}Em views/index.html, você deve fornecer um elemento de espaço reservado para que o Video do compartilhamento de tela seja exibido e um botão para acionar o compartilhamento. Crie também um botão para interromper o compartilhamento de tela, que será usado mais tarde:
<main>
<!-- This element is new -->
<div id="screen" class="screen"></div>
<!-- These two elements already exist from the first tutorial -->
<div id="subscriber" class="subscriber"></div>
<div id="publisher" class="publisher"></div>
<!-- These are both new too -->
<button id="startScreenShare" class="screen-share">Share Screen</button>
<button id="stopScreenShare" class="screen-share hidden">Stop Sharing Screen</button>
</main> Verifique os recursos de compartilhamento de tela
Quando o botão “Compartilhar” for pressionado, o aplicativo deve primeiro verificar se é possível compartilhar a tela. Adicione este código ao final de client.js:
const startShareBtn = document.getElementById("startScreenShare");
startShareBtn.addEventListener("click", event => {
OT.checkScreenSharingCapability(response => {
if (!response.supported || response.extensionRegistered === false) {
alert("Screen sharing not supported");
} else if (response.extensionInstalled === false) {
alert("Browser requires extension");
} else {
// Share screen code
}
});
});
O OT.checkScreenSharingCapability() método retorna informações sobre os recursos do navegador atual. Com base nisso, é possível determinar se o navegador não oferece suporte a esse recurso, se requer uma extensão em navegadores mais antigos ou se permite o compartilhamento por meio de APIs nativas.
No Chrome 71 e versões anteriores, no Firefox 51 e versões anteriores e no Opera 58 e versões anteriores, o usuário precisará instalar uma extensão para compartilhar sua tela. Esta publicação não aborda extensões, mas você pode saber mais na documentação.
Compartilhe sua tela
Adicione o código a seguir no else bloco de instruções acima:
const screenSharePublisher = OT.initPublisher(
"screen",
{
insertMode: "append",
width: "100%",
height: "100%",
videoSource: "screen",
publishAudio: true
},
handleCallback
);
session.publish(screenSharePublisher, handleCallback);O primeiro parâmetro é o id do elemento HTML, que será preenchido pelo Video do editor. Compartilhar uma tela é muito semelhante a compartilhar uma câmera nos navegadores modernos. Ao adicionar videoSource: "screen" às opções do publisher, o navegador solicitará as permissões corretas em seu nome. publishAudio é opcional.
Depois de criar o novo editor, você poderá publicá-lo em nossa sessão.

Funciona, mas, como você deve ter notado, o Video do compartilhamento de tela fica encostado na lateral da janela, e os botões estão em um lugar estranho. Adicione o seguinte ao seu public/style.css arquivo:
.screen {
width: 100%;
height: 100%;
display: flex;
}
.screen-share {
position: absolute;
bottom: 0;
right: 0;
}
.hidden {
display: none;
} Pare de compartilhar sua tela
Para interromper o compartilhamento de um stream publicado, é necessário ter acesso à variável à qual ele está atribuído. Acima do ouvinte de eventos, crie uma variável screenSharePublisher variável:
let screenSharePublisher;No ouvinte de evento, atribua OT.initPublisher(...) à nova variável removendo a const palavra-chave.
Na parte inferior de client.js adicione um ouvinte de evento para o botão “Parar de compartilhar”:
const stopShareBtn = document.getElementById("stopScreenShare");
stopShareBtn.addEventListener("click", event => {
screenSharePublisher.destroy();
});
Corrigir os problemas de layout restantes
A esta altura, seu aplicativo já deve estar mais ou menos assim:

Ficou um pouco melhor do que no início, mas ainda parece estar com erros. Vamos corrigir isso com um pouco de CSS e JavaScript (para ativar e desativar as classes CSS necessárias).
Vamos remover os .screen estilos de style.css:
/* We don't need these any more */
.screen {
width: 100%;
height: 100%;
display: flex;
}Modifique os .subscriber estilos da classe da style.css da seguinte maneira:
.subscriber,
.screen.pub-active,
.screen.sub-active {
width: 100%;
height: 100%;
display: flex;
}
.screen.sub-active ~ .subscriber,
.screen.pub-active ~ .subscriber {
position: absolute;
width: 25vmin;
height: 25vmin;
min-width: 8em;
min-height: 8em;
align-self: flex-end;
right: 0;
}O que estamos fazendo aqui é fazer com que o elemento que abriga a transmissão de compartilhamento de tela ocupe toda a área da janela de visualização quando estiver ativo, enquanto a transmissão da câmera fica posicionada no canto inferior direito da janela de visualização.
Em seguida, precisaremos garantir que as classes corretas sejam adicionadas aos elementos apropriados quando o compartilhamento de tela começar:
screenSharePublisher = OT.initPublisher(
"screen",
{
insertMode: "append",
width: "100%",
height: "100%",
videoSource: "screen",
publishAudio: true
},
handleCallback
);
session.publish(screenSharePublisher, handleCallback);
// CSS classes when screen-sharing starts
startShareBtn.classList.toggle("hidden");
stopShareBtn.classList.toggle("hidden");
document.getElementById("screen").classList.add("pub-active");O contrário precisa acontecer quando o compartilhamento de tela for encerrado:
stopShareBtn.addEventListener("click", event => {
screenSharePublisher.destroy();
// CSS classes when screen-sharing stops
startShareBtn.classList.toggle("hidden");
stopShareBtn.classList.toggle("hidden");
document.getElementById("screen").classList.remove("pub-active");
});
No início, tudo parece estar certo quando você inicia o compartilhamento de tela. Mas, para a pessoa do outro lado da chamada, o layout ainda está meio desorganizado.

Para resolver isso, vamos modificar o streamCreated ouvinte de eventos que se inscreve em quaisquer transmissões recém-criadas. Verificaremos se a transmissão criada é de uma câmera ou de compartilhamento de tela. Se for de compartilhamento de tela, adicionaremos a sub-active classe CSS a ele.
Antes:
session.connect(token, error => {
// Other code not included for brevity
// Subscribe to a newly created stream
session.on("streamCreated", event => {
session.subscribe(
event.stream,
"subscriber",
{
insertMode: "append",
width: "100%",
height: "100%"
},
handleCallback
);
});
});
Depois:
// Subscribe to a newly created stream
session.on("streamCreated", event => {
const streamContainer =
event.stream.videoType === "screen" ? "screen" : "subscriber";
session.subscribe(
event.stream,
streamContainer,
{
insertMode: "append",
width: "100%",
height: "100%"
},
handleScreenShare(event.stream.videoType)
);
});
// Function to handle screen share layout
function handleScreenShare(streamType, error) {
if (error) {
console.log("error: " + error.message);
} else {
if (streamType === "screen") {
document.getElementById("screen").classList.add("sub-active");
}
}
}
E também precisaremos adicionar um ouvinte de evento para quando o compartilhamento de tela for interrompido:
session.on("streamDestroyed", event => {
document.getElementById("screen").classList.remove("sub-active");
});
O resultado final para a pessoa que está recebendo o compartilhamento de tela deve ser algo assim:

Depois de tudo isso, seu client.js arquivo ficaria assim:
let session;
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
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 => {
const streamContainer =
event.stream.videoType === "screen" ? "screen" : "subscriber";
session.subscribe(
event.stream,
streamContainer,
{
insertMode: "append",
width: "100%",
height: "100%"
},
handleScreenShare(event.stream.videoType)
);
});
session.on("streamDestroyed", event => {
document.getElementById("screen").classList.remove("sub-active");
});
}
// Function to handle screenshare layout
function handleScreenShare(streamType, error) {
if (error) {
console.log("error: " + error.message);
} else {
if (streamType === "screen") {
document.getElementById("screen").classList.add("sub-active");
}
}
}
// Callback handler
function handleCallback(error) {
if (error) {
console.log("error: " + error.message);
} else {
console.log("callback success");
}
}
let screenSharePublisher;
const startShareBtn = document.getElementById("startScreenShare");
startShareBtn.addEventListener("click", event => {
OT.checkScreenSharingCapability(response => {
if (!response.supported || response.extensionRegistered === false) {
alert("Screen sharing not supported");
} else if (response.extensionInstalled === false) {
alert("Browser requires extension");
} else {
screenSharePublisher = OT.initPublisher(
"screen",
{
insertMode: "append",
width: "100%",
height: "100%",
videoSource: "screen",
publishAudio: true
},
handleCallback
);
session.publish(screenSharePublisher, handleCallback);
startShareBtn.classList.toggle("hidden");
stopShareBtn.classList.toggle("hidden");
document.getElementById("screen").classList.add("pub-active");
}
});
});
const stopShareBtn = document.getElementById("stopScreenShare");
stopShareBtn.addEventListener("click", event => {
screenSharePublisher.destroy();
startShareBtn.classList.toggle("hidden");
stopShareBtn.classList.toggle("hidden");
document.getElementById("screen").classList.remove("pub-active");
});
E agora?
O código final sobre Glitch e GitHub contém tudo o que abordamos neste post bastante extenso, mas reorganizado, de modo que o código ficou mais limpo e mais fácil de manter. Fique à vontade para adaptar ou clonar o código e brincar com ele por conta própria.
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!