Pular para conteúdo

SDK JavaScript (@videochamada/embed)

O SDK oficial @videochamada/embed permite incorporar uma videochamada na sua própria aplicação e montar a interface com a sua cara — escondendo os controles nativos e comandando tudo (microfone, câmera, tela, chat, layout, encerrar) por JavaScript.

É um wrapper fino e tipado sobre o protocolo iframe + postMessage descrito em Controle Embed. Use o SDK para não precisar escrever postMessage na mão.

Como se encaixa

  • White-label visual (cor e logo da sua marca por projeto) e domínio personalizado continuam valendo — veja Personalização de URLs.
  • A criação da chamada acontece no seu backend via POST /api/calls com a sua API Key. O SDK cuida só da interface no navegador.

Instalação

npm install @videochamada/embed

Ou direto no navegador via um CDN de ES modules:

<script type="module">
  import { VideochamadaCall } from 'https://esm.sh/@videochamada/embed';
  // ...
</script>

Início rápido

import { VideochamadaCall } from '@videochamada/embed';

const call = new VideochamadaCall({
  container: '#video',                              // seletor CSS ou elemento
  baseUrl: 'https://sua-org.videochamada.com.br',   // subdomínio da org OU domínio próprio
  callId: 'abc-123',                                // vindo de POST /api/calls
  username: 'Maria',
  hideControls: true,                               // esconde nossos controles: você desenha os seus
});

// eventos da chamada
call.on('ready', () => console.log('iframe carregado'));
call.on('participantJoined', (p) => console.log('entrou:', p));
call.on('participantLeft', (p) => console.log('saiu:', p));
call.on('callEnded', (info) => console.log('encerrou:', info));
call.on('status', (s) => console.log('status:', s));

// os seus botões
botaoMic.onclick    = () => call.toggleAudio();
botaoCam.onclick    = () => call.toggleVideo();
botaoTela.onclick   = () => call.toggleScreenShare();
botaoSair.onclick   = () => call.endCall();

Fluxo completo

1. Backend:  POST https://api.videochamada.com.br/api/calls
             Authorization: Bearer SUA_API_KEY        ->  { id: "abc-123", ... }
2. Backend devolve o callId para o navegador.
3. Front:    new VideochamadaCall({ callId, baseUrl, container, hideControls: true })
4. Você renderiza a sua UI e comanda a chamada pelos métodos abaixo.

Opções do construtor

Opção Tipo Padrão Descrição
container string \| HTMLElement Onde montar o iframe. Obrigatório.
baseUrl string Origem do seu projeto (subdomínio da org ou domínio próprio). Obrigatório.
callId string Id da chamada (de POST /api/calls). Obrigatório.
username string Pré-preenche o nome do participante.
userId string Id estável do participante.
hideControls boolean false Atalho para features.controlBar = false.
features object {} Desliga recursos individualmente (só false tem efeito).
width / height number \| string 100% Tamanho do iframe (número = px).
allow string camera; microphone; display-capture; autoplay; fullscreen Atributo allow do iframe.

features aceita: chat, clock, controlBar, closeButton, raiseHand, screenShare, recording, transcription, virtualBackground, hardwareTest, pendingCallCard, nameInput, waitingRoom, summary.

Recursos são disable-only

As flags só desligam recursos. Se um recurso já estiver desativado no painel do projeto, a URL/SDK não consegue religá-lo — a configuração do painel sempre vence.

Métodos

Método Ação
toggleAudio() / mute() / unmute() Microfone
toggleVideo() / enableCamera() / disableCamera() Câmera
toggleScreenShare() / startScreenShare() / stopScreenShare() Compartilhar tela
openChat() / closeChat() / toggleChat() Chat
toggleRaiseHand() Levantar a mão
setLayout('mosaic' \| 'sidebar') Trocar o layout direto
openLayoutDialog() Abrir o seletor de layout
openSettings() Abrir configurações de dispositivos
toggleConnectionStatus() Mostrar/ocultar status de conexão
endCall() Encerrar a chamada
getStatus(timeoutMs?) Promise<CallStatus> com o status atual
destroy() Remove o iframe e desliga os listeners

Eventos

Assine com call.on(evento, handler) — retorna uma função para cancelar a assinatura.

Evento Payload
ready — (iframe carregou)
status CallStatus
audioToggled { enabled }
videoToggled { enabled }
screenShareToggled { enabled }
participantJoined { participantId, name }
participantLeft { participantId }
callEnded { reason }

CallStatus: { audioEnabled, videoEnabled, screenShareEnabled, chatOpen, handRaised, layoutMode, participantCount, isRecording, connectionStatusVisible }.

Tema / white-label (deixar a chamada com a sua cara)

Passe um theme para restilizar a chamada por dentro — fundo, barra de controles, botões, tiles de vídeo, cantos e fonte — sem tocar na nossa marcação interna. Requer @videochamada/embed ≥ 0.2.0.

const call = new VideochamadaCall({
  container: '#video', baseUrl, callId, hideControls: true,
  theme: {
    background: '#0b1220',
    controlBarBackground: '#111a2e',
    buttonBackground: '#0ea5a4',
    buttonText: '#04121a',
    accent: '#0ea5a4',
    endCallBackground: '#e11d48',
    tileBackground: '#0f172a',
    tileRadius: '18px',
    textColor: '#e6edf7',
    font: 'Inter, sans-serif',
  },
});

// trocar em tempo real:
call.setTheme({ accent: '#9333ea', controlBarBackground: '#1e1b4b' });

Tokens disponíveis

Token Aplica em
background Fundo da área de vídeo
surface Painéis (chat, diálogos)
controlBarBackground Barra de controles
buttonBackground / buttonText Botões de controle
accent Cor de destaque + paleta primária (chat, sala de espera)
endCallBackground Botão de encerrar
tileBackground / tileRadius Fundo e cantos dos tiles de vídeo
textColor Nome do participante
font Fonte

Seguro por padrão

Todos os campos são opcionais — o que você não passar mantém o visual padrão. Só valores CSS seguros são aceitos (o app rejeita url(), @import e caracteres que quebrariam a regra). A estilização é aplicada por dentro do iframe pelo próprio app (o navegador não deixa o site pai injetar CSS num iframe de outro domínio).

Exemplo com React

import { useEffect, useRef, useState } from 'react';
import { VideochamadaCall } from '@videochamada/embed';

export function Call({ baseUrl, callId, username }) {
  const box = useRef(null);
  const call = useRef(null);
  const [status, setStatus] = useState({});

  useEffect(() => {
    const c = new VideochamadaCall({ container: box.current, baseUrl, callId, username, hideControls: true });
    c.on('status', setStatus);
    call.current = c;
    return () => c.destroy();   // limpa o iframe + listeners
  }, [baseUrl, callId, username]);

  return (
    <div>
      <div ref={box} style={{ aspectRatio: '16 / 9' }} />
      <button onClick={() => call.current.toggleAudio()}>
        {status.audioEnabled === false ? 'Ativar microfone' : 'Mutar'}
      </button>
      <button onClick={() => call.current.toggleVideo()}>Câmera</button>
      <button onClick={() => call.current.endCall()}>Encerrar</button>
    </div>
  );
}

Segurança

  • O SDK só aceita mensagens vindas da origem de baseUrl e envia comandos apenas para essa origem.
  • Mantenha a sua API Key no backend. Nunca a exponha no código do navegador — o front só precisa do callId.

Solução de problemas

Sintoma Causa provável O que fazer
Os eventos nunca disparam baseUrl diferente do domínio real do iframe Use exatamente o subdomínio da org (ou o domínio personalizado). A checagem de origem descarta mensagens de outra origem.
Câmera/microfone não ligam Permissão do navegador negada O usuário precisa permitir câmera/microfone; o iframe já pede via allow. Em https apenas.
Um recurso não aparece mesmo passando features Ele está desligado no painel do projeto As flags são disable-only — o painel vence. Reative pelo painel.
getStatus() dá timeout Iframe ainda não carregou Chame após o evento ready, ou aumente o timeoutMs.
Iframe em branco callId inválido/expirado Gere um novo callId em POST /api/calls.