Llamadas de aviso por interrupciones del servicio
La plataforma Vonage Video supervisa continuamente todos los servicios en ejecución. Cuando un fallo interno afecta a un servicio —como un fallo del servidor multimedia, un fallo del archivador, la caída de un nodo de emisión, un problema con la pasarela SIP o un fallo del motor de subtítulos—, el sistema de supervisión de la plataforma detecta el fallo, actualiza el estado del servicio y envía inmediatamente una notificación de devolución de llamada a tu terminal registrado.
Esta guía explica qué funciones de devolución de llamada emite cada servicio en caso de interrupción, cómo son las cargas útiles y cómo recuperar cada servicio mediante programación.
Visión general
Las interrupciones del servicio pueden afectar a cualquiera de los siguientes servicios de Vonage Video:
| Servicio | ¿Qué se ve afectado? | Mecanismo principal de devolución de llamada |
|---|---|---|
| Sesiones | El Media Router se bloquea; se interrumpen las conexiones y las transmisiones de los participantes | Webhook de supervisión de sesiones del lado del servidor + eventos del Client SDK |
| Archivos (Grabaciones) | El proceso «Archiver» se bloquea; la grabación finaliza de forma anómala | Webhook de estado del archivo ("status": "failed") |
| Emisiones | Fallo del nodo de retransmisión; se interrumpe la transmisión HLS/RTMP | Webhook de estado de la emisión ("status": "failed") |
| Llamadas SIP | La pasarela SIP falla; se interrumpe el tramo de la llamada | Webhook de supervisión de sesiones callDestroyed |
| Leyendas | Fallo del motor de subtítulos; se interrumpe la transcripción en directo | Webhook de estado de los subtítulos ("status": "failed") |
En todos los casos, el reason El campo en la carga útil de la llamada de retorno es normalmente ajustado a "forceDisconnected". Pueden aparecer otros valores de motivo en función de la naturaleza del fallo, por lo que tu código de recuperación debería tratar cualquier interrupción inesperada (que no esté causada por tus propias llamadas a la API) como una posible interrupción del servicio.
Nota: La plataforma también envía avisos previos a una interrupción para las rotaciones de servidores (reason: "serverRotation") a través de la sessionNotification evento. Véase Rotación de servidores y migración de sesiones para obtener más información sobre ese caso concreto.
Requisitos previos
Para recibir notificaciones de interrupciones del lado del servidor, debes registrar un URL de devolución de llamada para la supervisión de sesiones para tu proyecto. Consulta Control de la sesión para obtener instrucciones de configuración.
Para las notificaciones de estado de archivos, emisiones y subtítulos, configura la URL de notificación de estado correspondiente en tu Panel de control del proyecto de la Video API de Vonage.
Interrupción de la sesión
Cuando el Media Router que aloja una sesión se bloquea, la sesión se interrumpe y la plataforma envía un sessionDestroyed evento al punto final de supervisión de tu sesión.
Cargas útiles de devolución de llamada
{
"sessionId": "2_MX4xMzExMjU3MX5-MTQ3MDI1NzY3OTkxOH45QXRr",
"projectId": "123456",
"event": "sessionDestroyed",
"reason": "forceDisconnected",
"timestamp": 1718000050000
}
Eventos del Client SDK
Paralelamente a los webhooks del lado del servidor, los clientes reciben eventos del ciclo de vida a través del 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 los SDK nativos, utiliza los métodos delegados equivalentes:
- iOS:
OTSessionDelegate.sessionDidBeginReconnecting(_:)/sessionDidReconnect(_:)/sessionDidDisconnect(_:) - Android:
Session.SessionListener.onReconnecting()/onReconnected()/onDisconnected()
Recuperación
En sessionDisconnected incendios con reason: "forceDisconnected" (o después de sessionReconnecting tiempo de espera):
- Crea una nueva sesión a través de la API REST o del SDK del servidor.
- Emitir tokens nuevos para todos los participantes.
- Avisa a los clientes de que deben volver a conectarse, ya sea a través de tu propio canal de notificación, mediante una notificación push o con un mensaje dentro de la aplicación.
// 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);
});
Consejo: Si Migración de sesiones Si está activada, la plataforma puede recuperar la sesión automáticamente. En ese caso sessionReconnected se inician en el cliente y no es necesario volver a conectarse manualmente.
Interrupción del archivo (grabación)
Cuando un proceso de archivado se bloquea en mitad de la grabación, el sistema de supervisión de la plataforma detecta el fallo y marca el archivo como "failed", y envía una notificación de estado a la URL de estado del archivo que hayas registrado.
Carga útil de la llamada 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 clave:
| Campo | El valor de la disrupción |
|---|---|
status |
"failed" |
reason |
"Internal server failure" |
duration |
Quizás 0 si el fallo se produjo antes de que se escribiera el primer segmento |
Recuperación
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);
});
Nota: Verify siempre que la sesión siga teniendo participantes activos antes de reiniciar el archivo. Iniciar un archivo en una sesión vacía provocará un error.
Interrupción de la emisión
Cuando un nodo de emisión falla, la transmisión HLS o RTMP se interrumpe y la emisión se marca como "failed". Se envía una respuesta de estado a tu URL de estado de difusión.
Carga útil de la llamada 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"
}
Recuperación
- Recibe el
"failed"llamada de retorno de estado. - Espera a que los clientes se hayan vuelto a conectar a la sesión (espera a que se detecte
connectionCreatedeventos o participantes en las sesiones de votación). - Iniciar una nueva retransmisión:
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: La URL de HLS cambia con cada nueva emisión. Asegúrate de actualizar con la nueva URL todos los reproductores o sistemas posteriores que utilicen la transmisión.
Interrupción de una llamada SIP
Cuando un fallo en la pasarela SIP provoca la interrupción de un tramo de llamada activo, la conexión SIP se interrumpe y la plataforma envía callDestroyed a tu punto final de supervisión de sesiones con reason_message: "Unexpected Clearing". Los datos de una conexión SIP suelen contener un sip identificador para que puedas distinguirlo de las conexiones de los participantes habituales.
Carga útil de la llamada 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
}
}
Recuperación
Identificar las conexiones SIP mediante la inspección de connection.data, y luego vuelve a marcar:
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);
});
Interrupción de los subtítulos
Cuando el motor de subtítulos falla, la transcripción en directo se detiene y la sesión de subtítulos se marca como "failed". Se envía una respuesta de estado a la URL de estado de tus subtítulos.
Carga útil de la llamada 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"
}
Recuperación
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);
});
Buenas prácticas
- Comprueba siempre el
reasoncampo, pero no te fíes exclusivamente de ello. Aunque las interrupciones suelen conllevar"Internal server failure", tu lógica de recuperación debería gestionar cualquier"failed"estado o<something>Destroyedacontecimiento como una posible disrupción de la plataforma. - Implementar controladores de recuperación idempotentes. Las funciones de devolución de llamada pueden ejecutarse más de una vez. Utiliza el identificador del recurso (
archive.id,captionsId,session.id) para eliminar los duplicados. - Utiliza las advertencias previas a la rotación. En
sessionNotificationevento (conremainingTime: 3600o14400) te avisa con antelación de las rotaciones previstas. Úsalo para detener de forma ordenada los archivos, las emisiones y los subtítulos antes de la rotación, evitando así un"forceDisconnected"rescisión. - Registrar todos los incidentes de interrupción del servicio con toda su carga útil para el análisis posterior al incidente. El
timestampEste campo es el valor de referencia para calcular la duración del impacto. - Para las sesiones, es preferible utilizar la migración de sesiones. Al habilitar la migración de sesiones se reduce drásticamente el alcance de los fallos del Media Router, ya que los clientes se transfieren de forma transparente a un servidor en buen estado. Véase Rotación de servidores y migración de sesiones.
- Configura alertas en
"Internal server failure"funciones de devolución de llamada. Un repunte enInternal server failureLa aparición de eventos a lo largo de varias sesiones es un indicio temprano de un incidente más amplio en la plataforma.
Recursos relacionados
- Control de la sesión
- Rotación de servidores y migración de sesiones
- Guía de archivo
- Guía de programación
- Guía de interconexión SIP
- Guía de subtítulos en directo