Retornos de chamada em caso de interrupção do serviço

A plataforma Vonage Video monitora continuamente todos os serviços em execução. Quando uma falha interna afeta um serviço — como uma falha no servidor de mídia, uma falha no arquivador, a indisponibilidade de um nó de transmissão, um problema no gateway SIP ou uma falha no mecanismo de legendas —, o sistema de monitoramento da plataforma detecta a falha, atualiza o status do serviço e envia imediatamente uma notificação de retorno de chamada para o seu terminal registrado.

Este guia explica quais callbacks cada serviço emite em caso de interrupção, como são as cargas de dados e como recuperar cada serviço por meio de programação.

Visão geral

Interrupções no serviço podem afetar qualquer um dos seguintes serviços de vídeo da Vonage:

Serviço O que é afetado Mecanismo principal de retorno de chamada
Sessões O Media Router trava; as conexões e transmissões dos participantes são encerradas Webhook de monitoramento de sessão no lado do servidor + eventos do Client SDK
Arquivos (Gravações) O processo do Archiver trava; a gravação é encerrada de forma anômala Webhook de status do arquivo ("status": "failed")
Transmissões Falha no nó de transmissão; o fluxo HLS/RTMP é encerrado Webhook de status da transmissão ("status": "failed")
Chamadas SIP O gateway SIP apresenta falha; a ligação é interrompida Webhook de monitoramento de sessão callDestroyed
Legendas O mecanismo de legendas apresenta falha; a transcrição ao vivo é interrompida Webhook de status das legendas ("status": "failed")

Em todos os casos, o reason O campo na carga útil da chamada de retorno é normalmente definir como "forceDisconnected". Outros valores de motivo podem aparecer dependendo da natureza da falha; portanto, seu código de recuperação deve tratar qualquer encerramento inesperado (não causado por suas próprias chamadas de API) como uma possível interrupção.

Observação: A plataforma também envia avisos prévios de interrupção para rotações de servidores (reason: "serverRotation") por meio do sessionNotification evento. Veja Rotação de servidores e migração de sessões para obter mais detalhes sobre esse cenário específico.

Pré-requisitos

Para receber chamadas de retorno em caso de interrupções no lado do servidor, é necessário registrar um URL de retorno de chamada para monitoramento de sessão para o seu projeto. Veja Monitoramento de sessões para obter instruções de configuração.

Para callbacks de status de arquivo, transmissão e legendas, configure a URL de callback de status correspondente em seu Painel do projeto da Video API da Vonage.


Interrupção da sessão

Quando o Media Router que hospeda uma sessão apresenta falha, a sessão é encerrada e a plataforma envia um sessionDestroyed evento para o seu endpoint de monitoramento de sessão.

Cargas úteis de retorno de chamada

{
  "sessionId": "2_MX4xMzExMjU3MX5-MTQ3MDI1NzY3OTkxOH45QXRr",
  "projectId": "123456",
  "event": "sessionDestroyed",
  "reason": "forceDisconnected",
  "timestamp": 1718000050000
}

Eventos do Client SDK

Paralelamente aos webhooks do lado do servidor, os clientes recebem eventos do ciclo de vida por meio do SDK:

session.on('sessionReconnecting', () => {
  // Platform is attempting automatic reconnection via session migration
  showReconnectingBanner();
});

session.on('sessionReconnected', () => {
  // Automatic recovery succeeded — no further action needed
  hideReconnectingBanner();
});

session.on('sessionDisconnected', (event) => {
  // Automatic recovery failed or is not enabled
  if (event.reason === 'networkDisconnected' || event.reason === 'networkTimedout') {
    promptUserToRejoin();
  }
});

publisher.on('streamDestroyed', (event) => {
  if (event.reason === 'networkDisconnected') {
    event.preventDefault(); // Keep the publisher element in the DOM
    retryPublish();
  }
});

Para SDKs nativos, use os métodos delegados equivalentes:

  • iOS: OTSessionDelegate.sessionDidBeginReconnecting(_:) / sessionDidReconnect(_:) / sessionDidDisconnect(_:)
  • Android: Session.SessionListener.onReconnecting() / onReconnected() / onDisconnected()

Recuperação

Quando sessionDisconnected incêndios com reason: "forceDisconnected" (ou depois de sessionReconnecting tempo limite):

  1. Crie uma nova sessão por meio da API REST ou de um SDK de servidor.
  2. Emitir novos tokens para todos os participantes.
  3. Notifique os clientes para que se reconectem — por meio do seu próprio canal de notificação, de notificações push ou de mensagens no aplicativo.
// Server-side — handle sessionDestroyed with reason "forceDisconnected"
app.post('/callbacks/vonage/session', (req, res) => {
  const { event, reason, sessionId } = req.body;

  if (event === 'sessionDestroyed' && reason === 'forceDisconnected') {
    createNewSessionAndNotifyClients(sessionId);
  }

  res.sendStatus(200);
});

Dica: Se Migração de sessão Se estiver ativado, a plataforma poderá recuperar a sessão automaticamente. Nesse caso sessionReconnected ocorrem falhas no cliente e não é necessário reiniciar manualmente a conexão.


Interrupção no arquivo (gravação)

Quando um processo de arquivamento trava no meio da gravação, o sistema de monitoramento da plataforma detecta a falha e marca o arquivo como "failed", e envia uma resposta de status para a URL de status do arquivo que você registrou.

Carga útil da chamada de retorno

{
  "id": "b40ef09b-3811-4726-b508-e41a0f96c68f",
  "event": "archive",
  "status": "failed",
  "reason": "Internal server failure",
  "sessionId": "2_MX4xMzExMjU3MX5-MTQ3MDI1NzY3OTkxOH45QXRr",
  "projectId": "123456",
  "name": "My Recording",
  "createdAt": 1718000000000,
  "duration": 0,
  "outputMode": "composed",
  "hasVideo": true,
  "hasAudio": true
}

Campos principais:

Campo O valor da disrupção
status "failed"
reason "Internal server failure"
duration Talvez 0 se a falha ocorreu antes da gravação do primeiro segmento

Recuperação

app.post('/callbacks/vonage/archive', (req, res) => {
  const { status, reason, sessionId } = req.body;

  if (status === 'failed' && reason === 'Internal server failure') {
    // Start a new archive for the same session
    opentok.startArchive(sessionId, { name: 'Resumed recording' }, (err, archive) => {
      if (err) console.error('Failed to restart archive:', err);
      else console.log('New archive started:', archive.id);
    });
  }

  res.sendStatus(200);
});

Observação: Sempre verifique se a sessão ainda tem participantes ativos antes de reiniciar o arquivamento. Iniciar um arquivamento em uma sessão vazia resultará em um erro.


Interrupção na transmissão

Quando um nó de transmissão apresenta falha, o fluxo HLS ou RTMP é encerrado e a transmissão é marcada como "failed". Uma resposta de status é enviada para a sua URL de status de transmissão.

Carga útil da chamada de retorno

{
  "id": "1748b707-0a81-464c-9759-c46ad10d3734",
  "sessionId": "2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4",
  "applicationId": 100,
  "createdAt": 1437676551000,
  "updatedAt": 1437676551000,
  "event": "broadcast",
  "group": "status",
  "resolution": "640x480",
  "streamMode" : "auto",
  "streams" : [],
  "broadcastUrls": {
    "hls" : "http://server/fakepath/playlist.m3u8",
    "hlsStatus": "error",
    "rtmp": {
      "foo": {
        "serverUrl": "rtmps://myfooserver:443/myfooapp",
        "streamName": "myfoostream",
        "status": "error"
      },
      "bar": {
        "serverUrl": "rtmp://mybarserver:443/mybarapp",
        "streamName": "mybarstream",
        "status": "error"
      }
    }
  },
  "settings": {
    "hls": {
      "dvr": false,
      "lowLatency": false
    }
  },
  "status": "failed",
  "reason": "Internal server failure"
}

Recuperação

  1. Receba o "failed" callback de status.
  2. Aguarde até que os clientes tenham se reconectado à sessão (verifique se há connectionCreated eventos ou participantes de sessões de pesquisa).
  3. Iniciar uma nova transmissão:
app.post('/callbacks/vonage/broadcast', (req, res) => {
  const { status, reason, sessionId } = req.body;

  if (status === 'failed' && reason === 'Internal server failure') {
    waitForParticipants(sessionId).then(() => {
      opentok.startBroadcast(sessionId, broadcastOptions, (err, broadcast) => {
        if (err) console.error('Failed to restart broadcast:', err);
        else notifyViewersOfNewStreamUrl(broadcast.broadcastUrls);
      });
    });
  }

  res.sendStatus(200);
});

Importante: A URL do HLS muda a cada nova transmissão. Certifique-se de atualizar todos os reprodutores ou sistemas downstream que utilizam o stream com a nova URL.


Interrupção da chamada SIP

Quando uma falha no gateway SIP interrompe um trecho de chamada ativo, a conexão SIP é encerrada e a plataforma envia callDestroyed ao seu endpoint de monitoramento de sessão com reason_message: "Unexpected Clearing". Os dados de uma conexão SIP geralmente contêm um sip identificador para que você possa diferenciá-la das conexões de participantes comuns.

Carga útil da chamada de retorno

{
  "sessionId": "2_MX4xMzExMjU3MX5-MTQ3MDI1NzY3OTkxOH45QXRr",
  "applicationId": "123456",
  "event": "callDestroyed",
  "reason_code":  "703",
  "reason_message": "Unexpected Clearing",
  "timestamp": 1718000050000,
  "call": {
    "id":  "<conference-id>",
    "connectionId":  "<sip-ot-connection-id>",
    "createdAt":  1470257688143
  }
}

Recuperação

Identifique conexões SIP por meio da inspeção de connection.data, em seguida, disque novamente:

app.post('/callbacks/vonage/session', (req, res) => {
  const { event, reason_message, connection, sessionId } = req.body;

  if (event === 'callDestroyed' && reason_message === 'Unexpected Clearing') {
    let connData = {};
    try { connData = JSON.parse(connection.data); } catch (_) {}

    if (connData.sip) {
      // Re-initiate the SIP call
      const sipUri = getSipUriForConnection(connection.id);
      opentok.dial(sessionId, token, sipUri, sipOptions, (err, call) => {
        if (err) console.error('SIP redial failed:', err);
        else console.log('SIP call re-established:', call.id);
      });
    }
  }

  res.sendStatus(200);
});

Interrupção nas legendas

Quando o mecanismo de legendas apresenta falha, a transcrição ao vivo é interrompida e a sessão de legendas é marcada como "failed". Uma resposta de status é enviada para a URL de status das suas legendas.

Carga útil da chamada de retorno

{
  "captionsId": "<captionsId>",
  "projectId": "<applicationId>",
  "sessionId": "<sessionId>",
  "status": "failed",
  "createdAt": 1651253477,
  "updatedAt": 1651253837,
  "duration": 360,
  "languageCode": "en-US",
  "reason": "Internal server failure",
  "provider": "aws-transcribe",
  "event": "sessionStatus"
}

Recuperação

app.post('/callbacks/vonage/captions', (req, res) => {
  const { status, reason, sessionId } = req.body;

  if (status === 'failed' && reason === 'Internal server failure') {
    // Restart captions for the session
    fetch(`https://video.api.vonage.com/v2/project/${PROJECT_ID}/captions`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${jwt}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ sessionId, token: generateToken(sessionId) })
    })
    .then(res => res.json())
    .then(data => console.log('Captions restarted:', data.captionsId))
    .catch(err => console.error('Failed to restart captions:', err));
  }

  res.sendStatus(200);
});

Melhores práticas

  • Sempre verifique o reason campo, mas não confie exclusivamente nisso. Embora as interrupções geralmente acarretem "Internal server failure", sua lógica de recuperação deve tratar qualquer situação inesperada "failed" status ou <something>Destroyed evento como uma possível ruptura na plataforma.
  • Implementar manipuladores de recuperação idempotentes. As chamadas de retorno podem ser entregues mais de uma vez. Use o ID do recurso (archive.id, captionsId, session.id) para realizar a deduplicação.
  • Utilize avisos de pré-rotação. O sessionNotification evento (com remainingTime: 3600 ou 14400) avisa com antecedência sobre as rotações planejadas. Use-o para interromper de forma controlada arquivos, transmissões e legendas antes da rotação, evitando uma interrupção brusca "forceDisconnected" rescisão.
  • Registrar todos os eventos de interrupção com toda a sua carga útil para análise pós-incidente. O timestamp Esse campo é a sua referência para calcular a duração do impacto.
  • Para sessões, opte pela Migração de Sessões. A ativação da migração de sessão reduz drasticamente o alcance das falhas do Media Router, transferindo os clientes de forma transparente para um servidor em bom estado. Consulte Rotação de servidores e migração de sessões.
  • Configure alertas em "Internal server failure" callbacks. Um aumento repentino em Internal server failure A ocorrência de eventos em várias sessões é um sinal precoce de um incidente mais amplo na plataforma.

Recursos relacionados