Arquitetura

WebRTC

Arquitetura WebRTC do stCall - SIP.js, PJSIP e fluxo de mídia.

Arquitetura WebRTC

O stCall usa WebRTC para chamadas de áudio diretamente no navegador, com SIP.js como biblioteca SIP e Asterisk PJSIP como servidor de mídia.

Stack WebRTC

Navegador (SIP.js)
    │
    │ SIP sobre WSS (:8089)
    ▼
Asterisk PJSIP
    │
    │ SIP Trunk / PSTN
    ▼
Rede Telefônica
  • Codec: Opus (principal), ulaw, alaw
  • Latência típica: < 100ms (geralmente < 50ms)
  • Largura de banda: ~30-50 kbps por chamada (Opus)
  • Setup time: < 2 segundos

Composable: useWebRTCPhone

O composable principal para WebRTC está em composables/webrtc/useWebRTCPhone.ts.

Registro

const phone = useWebRTCPhone()

await phone.register({
  wsServer: 'wss://dominio.com:8089/ws',
  domain: 'dominio.com',
  username: 'agent-1001',
  password: 'senha',
  displayName: 'João Silva',
})

O registro:

  1. Cria um UserAgent do SIP.js
  2. Conecta via WSS ao Asterisk
  3. Cria um Registerer com expiração de 5 minutos
  4. Envia REGISTER para o endpoint PJSIP

Fazer Chamada

await phone.call('1002')

Fluxo:

  1. Cria um Inviter (sessão de saída)
  2. Configura constraints de áudio ({ audio: true, video: false })
  3. Envia SIP INVITE para sip:1002@dominio
  4. Monitora mudanças de estado da sessão

Receber Chamada

Chamadas entrantes são tratadas pelo delegate onInvite:

// Internamente no useWebRTCPhone
delegate: {
  onInvite: handleIncomingCall,
}

O handler:

  1. Armazena a sessão (Invitation)
  2. Extrai número do chamador dos headers SIP
  3. Atualiza callState com estado ringing
  4. Frontend exibe diálogo de chamada entrante

Atender / Rejeitar

await phone.answer()  // Aceita com constraints de áudio
await phone.reject()  // Rejeita a chamada

Controles

phone.hangup()           // Encerrar chamada (SIP BYE)
phone.hold(true)         // Colocar em espera
phone.hold(false)        // Retomar
phone.mute(true)         // Silenciar microfone
phone.mute(false)        // Ativar microfone
phone.sendDTMF('5')     // Enviar tom DTMF

Estados da Sessão

O SIP.js emite eventos de mudança de estado:

EstadoSignificado
EstablishingChamada sendo estabelecida (ringing)
EstablishedChamada ativa, mídia conectada
TerminatedChamada encerrada

Fluxo de Mídia

Quando a chamada é estabelecida:

  1. RTCPeerConnection é criado pelo SIP.js
  2. Stream local (microfone) é capturado
  3. Stream remoto é recebido via RTP
  4. Streams são expostos via localStream e remoteStream
  5. Componente WebRTCAudioPlayer reproduz o áudio remoto
<!-- Reprodutor de áudio invisível -->
<WebRTCAudioPlayer :stream="phone.remoteStream.value" />

ICE e NAT Traversal

Configuração dos servidores ICE:

peerConnectionConfiguration: {
  iceServers: [
    { urls: 'stun:stun.l.google.com:19302' },
    {
      urls: 'turn:turn.dominio.com:3478',
      username: 'user',
      credential: 'pass',
    }
  ]
}
  • STUN resolve IPs públicos para NAT simétrico
  • TURN é necessário quando STUN falha (NAT restritivo)

Composable: useWebRTCIntegration

Ponte entre WebRTC e eventos ARI (composables/webrtc/useWebRTCIntegration.ts):

  • Observa mudanças no estado da chamada WebRTC e sincroniza com o callStore
  • Observa eventos ARI e sincroniza com o WebRTC (ex: hangup remoto)
  • Expõe isIntegrated (WebRTC registrado + WebSocket conectado)

Outros Composables WebRTC

ComposableArquivoResponsabilidade
useWebRTCCallwebrtc/useWebRTCCall.tsControle individual de chamada
useWebRTCMediawebrtc/useWebRTCMedia.tsGerenciamento de streams
useWebRTCSessionwebrtc/useWebRTCSession.tsSessão SIP
useWebRTCStatewebrtc/useWebRTCState.tsEstado reativo do WebRTC

Troubleshooting WebRTC

Sem áudio após conexão

  • Verificar permissões de microfone no navegador
  • Verificar se remoteStream está anexado ao elemento <audio>
  • Verificar logs do Asterisk para erros de negociação de mídia

Chamada falha imediatamente

  • Verificar credenciais PJSIP
  • Confirmar que WSS está ativo (não WS)
  • Verificar se o firewall permite portas UDP (RTP)

Áudio unidirecional

  • Verificar configuração NAT/firewall
  • Confirmar servidor TURN configurado para NAT simétrico
  • Verificar se range de portas RTP está aberto

Registro falha

  • Verificar transporte WSS do Asterisk: pjsip show transports
  • Verificar certificado SSL
  • Verificar endpoint: pjsip show endpoints
Copyright © 2026