Este tópico descreve como se conectar à Realtime API no navegador usando WebRTC e JavaScript para ativar chamadas de áudio e vídeo em tempo real com o modelo qwen3.5-omni-plus-realtime.
O WebRTC é ideal para cenários de voz com baixa latência baseados em navegador. O áudio é transmitido diretamente via UDP, com cancelamento de eco e redução de ruído integrados. O WebRTC suporta apenas o modo VAD no lado do servidor (
server_vad ou semantic_vad). O modo manual não tem suporte.Pré-requisitos e observações
- Configure an API key e defina it as an environment variable.
- Use um navegador moderno com suporte a WebRTC (Chrome, Edge, Firefox, Safari, entre outros).
- O navegador precisa ter permissão de acesso ao microfone. Para chamadas de vídeo, também é necessária permissão da câmera.
- Devido a restrições de CORS, os navegadores não podem enviar solicitações de troca de SDP diretamente ao servidor. No demo, execute o comando curl em um terminal para concluir a conexão. Em produção, essa restrição não se aplica quando a solicitação passa por um proxy em um AppServer.
Implementar chamadas de áudio e vídeo com IA
O diagrama de sequência a seguir ilustra o fluxo completo de chamadas de áudio e vídeo via WebRTC:
Diagrama de sequência de chamada de áudio e vídeo via WebRTC

Crie RTCPeerConnection
Invoque o construtor nativo RTCPeerConnection do navegador para criar uma instância de conexão. Não é necessário configurar servidores ICE (o servidor gerencia a travessia de NAT).
Obter streams de mídia local
Faça uma única chamada a getUserMedia para solicitar áudio (obrigatório) e vídeo (opcional). A ativação do vídeo depende da caixa de seleção Enable video marcada pelo usuário.
Tanto o áudio quanto o vídeo são obtidos em uma única chamada a
getUserMedia, e não separadamente. A pré-visualização do vídeo roda a 30 fps (para garantir fluidez na visualização local); já a taxa de quadros enviada é reduzida para 2 fps via Canvas.Adicionar faixas de mídia ao PeerConnection
Adicionar faixa de áudio:
session.created:
Isso equivale a
enableSendMediaStream(false) em outros SDKs. O envio só deve ser restaurado após o recebimento de session.created.Crie DataChannel
Crie um DataChannel chamado oai-events para trocar eventos de controle de sessão com o servidor de IA.
Gerar Offer SDP
Chame createOffer() e defina a descrição local. Aguarde a conclusão da coleta de ICE antes de utilizar o Offer SDP completo.
Aguarde até que
iceGatheringState === "complete" antes de usar o SDP. Nesse momento, o SDP contém todas as informações dos candidatos ICE.Trocar SDP (via comando curl ou AppServer)
Envie o Offer SDP ao servidor e obtenha o Answer SDP. No demo, isso é feito por meio de um comando curl:
Em produção, faça o proxy dessa etapa por meio de um AppServer para evitar a exposição da chave de API no front-end.
{endpoint} é o endpoint da Realtime API.Definir Answer SDP para estabelecer a conexão
Configure o Answer SDP retornado pelo servidor como a descrição remota para estabelecer a conexão WebRTC. Normalize o formato do SDP antes de defini-lo:
A especificação SDP exige quebras de linha
\r\n. A função normalizeSdpForSetRemote garante a compatibilidade das quebras de linha provenientes de diferentes fontes.Configure sessão de IA (session.update)
Depois que a conexão é estabelecida, o servidor envia um evento session.created pelo DataChannel. Ao recebê-lo:
- Libere o controle de mídia para retomar o envio de áudio e vídeo
- Envie
session.updatepara configurar os parâmetros da sessão
O campo
turn_detection.type pode ser definido como server_vad (detecção baseada em volume) ou semantic_vad (detecção semântica). O modo VAD manual não tem suporte no modo WebRTC.Conversa em tempo real
Com a conexão estabelecida, o áudio e o vídeo são transmitidos em tempo real via RTP. As respostas de voz da IA remota chegam pelo callback ontrack e são reproduzidas. O MediaRecorder grava as respostas para permitir o download posterior.
Receber e gravar o áudio remoto:
session.created, response.audio_transcript.done, entre outros) aparecem no painel de eventos, com opção de expansão para visualizar o JSON completo:
Encerrar sessão e liberar recursos
Ao encerrar uma chamada, libere todos os recursos na ordem correta. A sequência é importante:
Após o término da sessão, use o botão Download remote audio para salve a gravação da resposta da IA no formato WebM.
Observações importantes
- O controle de mídia deve ser liberado após session.created: Dados de mídia enviados antes de o servidor emitir
session.createdserão descartados. UtilizereplaceTrack(null)para bloquear totalmente o envio até esse momento. - A redução de quadros de vídeo ocorre via Canvas: A pré-visualização local opera a 30 fps; apenas 2 fps são enviados ao servidor, controlados por
captureStream(2). Essa abordagem economiza largura de banda. - Normalização do formato SDP: Garanta que as quebras de linha sejam
\r\nantes de definir o Answer SDP. Caso contrário,setRemoteDescriptionpode falhar. - O vídeo é opcional: Se o usuário não ative o vídeo, apenas a permissão do microfone será solicitada — nenhum prompt de permissão da câmera aparecerá.
- O áudio remoto é gravado automaticamente: O MediaRecorder captura o stream de áudio da resposta da IA. Um arquivo WebM fica disponível para baixe após o fim da sessão.
- O WebRTC suporta apenas VAD no lado do servidor: O modo
manualnão tem suporte. Useserver_vad(detecção por volume) ousemantic_vad(detecção semântica).
Baixe o demo completo
Baixe o código de exemplo completo: webrtc_demo.html.
Documentos relacionados
- API WebRTC (MDN)
- RTCPeerConnection (MDN)
- Eventos do cliente do modelo qwen3.5-omni-plus-realtime: Client events
- Eventos do servidor do modelo qwen3.5-omni-plus-realtime: Server events
- WebRTC connection