Si planea crear una plataforma de contenido generado por el usuario (UGC) con Amazon Interactive Video Service (Amazon IVS), es probable que desee integrar algún tipo de tablero para monitorear el estado de las transmisiones en vivo de su usuario. Como siempre, la documentación proporciona una excelente descripción general de la supervisión del estado de la transmisión.
En esta publicación, iremos un poco más allá y mostraremos algunos ejemplos de cómo recuperar sesiones de transmisión y recuperar métricas de estado para una transmisión en vivo desde Amazon CloudWatch. Como beneficio adicional, también analizaremos la generación de algunos gráficos útiles que se pueden agregar a su panel de UGC para monitorear la salud en tiempo real.
Las métricas de estado de transmisión de Amazon IVS se almacenan en Amazon CloudWatch. Para recuperar estas métricas con AWS SDK para JavaScript v3, podemos usar los documentos del método GetMetricDataCommand
del cliente de Amazon CloudWatch ( @aws-sdk/client-cloudwatch
).
Este método espera que algunas propiedades filtren las métricas para un período de tiempo específico y un canal de Amazon IVS, como veremos a continuación.
Nota: Esta publicación se centrará en la recuperación de las métricas de salud de la transmisión con el SDK de Amazon CloudWatch, pero también se pueden observar métricas vitales de la salud de la transmisión a través de Amazon EventBridge para que pueda tomar las medidas necesarias cuando una transmisión no está en buen estado o se infringen los límites del servicio. Consulte la documentación para obtener más información.
Dado que necesitamos StartTime
y EndTime
para recuperar métricas de estado, tiene sentido recuperar una lista de sesiones de transmisión recientes a través del cliente de Amazon IVS ( @aws-sdk/client-ivs
). Para hacer esto, podemos usar ListStreamSessionsCommand
( docs ) y pasarle el ARN
del canal que nos interesa.
import { IvsClient, ListStreamSessionsCommand } from "@aws-sdk/client-ivs"; const ivsClient = new IvsClient(); const listStreamSessionsInput = { channelArn: process.env.DEMO_CHANNEL_ARN, maxResults: 3, // default=100 }; const listStreamSessionsRequest = new ListStreamSessionsCommand(listStreamSessionsInput); const listStreamSessionsResponse = await ivsClient.send(listStreamSessionsRequest); console.log(listStreamSessionsResponse)
La respuesta de ListStreamSessionsCommand
devolverá un objeto. La clave streamSessions
en ese objeto contiene una matriz de sesiones de transmisión, ordenadas por la sesión más reciente. Las sesiones activas se indican por la ausencia de un endTime
.
{ "$metadata": { "httpStatusCode": 200, "requestId": "[redacted]", "cfId": "[redacted]", "attempts": 1, "totalRetryDelay": 0 }, "nextToken": "AQI...[redacted]...A==", "streamSessions": [ { "endTime": undefined, "hasErrorEvent": false, "startTime": "2023-01-20T14:30:11.000Z", "streamId": "st-[redacted]" }, { "endTime": "2023-01-19T16:12:37.000Z", "hasErrorEvent": false, "startTime": "2023-01-19T16:12:29.000Z", "streamId": "st-[redacted]" }, { "endTime": "2023-01-19T16:12:25.000Z", "hasErrorEvent": false, "startTime": "2023-01-19T16:12:22.000Z", "streamId": "st-[redacted]" } ] }
En este punto, podríamos usar estas marcas de tiempo para recuperar nuestras métricas de transmisión. Pero, podría ser útil obtener un poco más de detalles, como la configuración de ingesta de audio y video. Para recuperar esta información, podemos usar GetStreamSessionCommand
( docs ). Este método espera el ARN
y un streamId
que ya hemos obtenido en el resultado anterior.
import { IvsClient, GetStreamSessionCommand } from "@aws-sdk/client-ivs"; import util from "node:util"; const ivsClient = new IvsClient(); const getStreamSessionInput = { channelArn: process.env.DEMO_CHANNEL_ARN, streamId: 'st-[redacted]' }; const getStreamSessionRequest = new GetStreamSessionCommand(getStreamSessionInput); const getStreamSessionResponse = await ivsClient.send(getStreamSessionRequest); console.log( util.inspect(getStreamSessionResponse, false, null, true) );
El método GetStreamSessionCommand
devuelve información sobre la sesión (en este caso, una transmisión en vivo activa). Tenga en cuenta que ingestConfiguration
contiene algunos elementos útiles como el códec, la tasa de bits, la tasa de fotogramas, etc. El objeto truncatedEvents
contiene todos los eventos que se activaron para esta transmisión en particular.
{ "$metadata": { "httpStatusCode": 200, "requestId": "[redacted]", "cfId": "[redacted]", "attempts": 1, "totalRetryDelay": 0 }, "streamSession": { "channel": { "arn": "[redacted]", "authorized": false, "ingestEndpoint": "[redacted]", "latencyMode": "LOW", "name": "demo-channel", "playbackUrl": "[redacted]", "recordingConfigurationArn": "[redacted]", "type": "STANDARD" }, "ingestConfiguration": { "audio": { "channels": 2, "codec": "mp4a.40.2", "sampleRate": 48000, "targetBitrate": 128000 }, "video": { "avcLevel": "3.1", "avcProfile": "Baseline", "codec": "avc1.42C01F", "encoder": "", "targetBitrate": 8500000, "targetFramerate": 30, "videoHeight": 1080, "videoWidth": 1920 } }, "recordingConfiguration": { "arn": "[redacted]", "destinationConfiguration": { "s3": { "bucketName": "[redacted]" } }, "state": "ACTIVE" }, "startTime": "2023-01-20T14:30:11.000Z", "streamId": "st-[redacted]", "truncatedEvents": [ { "eventTime": "2023-01-20T14:30:19.000Z", "name": "Recording Start", "type": "IVS Recording State Change" }, { "eventTime": "2023-01-20T14:30:18.000Z", "name": "Stream Start", "type": "IVS Stream State Change" }, { "eventTime": "2023-01-20T14:30:11.000Z", "name": "Session Created", "type": "IVS Stream State Change" } ] } }
Si planea integrar datos de métricas de estado de la transmisión en su aplicación, utilizará uno de los SDK de AWS. Pero, si solo busca ver datos de métricas de salud con menos frecuencia, puede verlos a través de la consola de AWS. Para ver las métricas de estado relacionadas con Amazon IVS, seleccione Todas las métricas y luego IVS a través de la consola de Amazon CloudWatch.
Podemos buscar datos de métricas eligiendo una dimensión.
Por ejemplo, para ver las métricas por canal, seleccione Por canal y elija el período de tiempo deseado, el canal y la métrica.
Estamos listos para usar el SDK de Amazon CloudWatch para recuperar datos de métricas de estado para un canal en función de las horas de inicio y finalización de la transmisión. GetMetricDataCommand
espera un objeto GetMetricDataCommandInput
( docs ).
Como se mencionó anteriormente, este objeto tiene propiedades StartTime
y EndTime
, así como una propiedad MetricDataQueries
que debe contener una matriz de consultas según las métricas de salud que nos gustaría recuperar. Hay cuatro propiedades relacionadas con el estado del canal de Amazon IVS que nos interesan aquí: IngestAudioBitrate
, IngestVideoBitrate
, IngestFramerate
y KeyframeInterval
. Construiremos una matriz para cada métrica, usando AWS/IVS
como Namespace
y filtrando en un canal específico tomando la parte del ARN del canal que sigue a /
.
import { CloudWatchClient, GetMetricDataCommand } from "@aws-sdk/client-cloudwatch"; const cloudWatchClient = new CloudWatchClient();
const getMetrics = async (arn, startTime, endTime) => { const streamHealthMetrics = [ "IngestAudioBitrate", "IngestVideoBitrate", "IngestFramerate", "KeyframeInterval" ]; const metricDataQueries = streamHealthMetrics.map((metric) => { return { Id: metric.toLowerCase(), MetricStat: { Metric: { MetricName: metric, Namespace: "AWS/IVS", Dimensions: [{ Name: "Channel", Value: arn.split("/")[1] }] }, Period: 5, Stat: "Average", } } }); const getMetricDataInput = { StartTime: startTime, EndTime: endTime, MetricDataQueries: metricDataQueries, MaxDatapoints: 100 }; const getMetricDataRequest = new GetMetricDataCommand(getMetricDataInput); const getMetricDataResponse = await cloudWatchClient.send(getMetricDataRequest); return getMetricDataResponse; }; // get metrics for a session const metrics = await getMetrics( process.env.DEMO_CHANNEL_ARN, new Date('2023-01-20T14:30:11.000Z'), new Date('2023-01-20T14:49:15.000Z') );
El resultado de llamar GetMetricDataCommand
será similar al siguiente resultado:
{ "$metadata": { "httpStatusCode": 200, "requestId": "[redacted]", "attempts": 1, "totalRetryDelay": 0 }, "MetricDataResults": [ { "Id": "ingestaudiobitrate", "Label": "IngestAudioBitrate", "Timestamps": [ "2023-01-20T14:49:10.000Z" ], "Values": [ 31049.333057821852 ], "StatusCode": "PartialData" }, { "Id": "ingestvideobitrate", "Label": "IngestVideoBitrate", "Timestamps": [ "2023-01-20T14:49:10.000Z" ], "Values": [ 3497988.4859657455 ], "StatusCode": "PartialData" }, { "Id": "ingestframerate", "Label": "IngestFramerate", "Timestamps": [ "2023-01-20T14:49:10.000Z" ], "Values": [ 29.143738984724312 ], "StatusCode": "PartialData" }, { "Id": "keyframeinterval", "Label": "KeyframeInterval", "Timestamps": [ "2023-01-20T14:49:10.000Z" ], "Values": [ 2.007629037 ], "StatusCode": "PartialData" } ], "NextToken": "[redacted]", "Messages": [] }
Es importante tener en cuenta que las métricas de Amazon CloudWatch se acumulan con el tiempo, por lo que la resolución granular disminuye con el tiempo.
Si tuviéramos que ejecutar la misma consulta con un rango de tiempo más grande (dependiendo de la disponibilidad de los datos como se mencionó anteriormente), podemos filtrar y agrupar los datos en función de una sola métrica y usar ese resultado para representar un buen gráfico de los valores. .
const videoBitrateMetrics = metrics .MetricDataResults .find((metric) => metric.Id === 'ingestvideobitrate'); const bitrateData = []; videoBitrateMetrics.Timestamps .sort((a, b) => new Date(a) > new Date(b) ? 1 : -1) .forEach((t, i) => { bitrateData.push({ timestamp: t, bitrate: videoBitrateMetrics.Values[i] / 1000, }) }); console.log(JSON.stringify(bitrateData));
Esto produce una matriz de objetos similar a la siguiente:
[ { "timestamp": "2023-01-20T14:47:05.000Z", "bitrate": 3497.9884859657454 } ]
Podemos usar estos datos filtrados para crear algunas visualizaciones agradables para nuestros paneles de UGC. Algunos ejemplos rápidos:
Otra opción genial es generar los gráficos directamente a través del SDK de Amazon CloudWatch. Consulte la documentación para obtener más información. Este es un ejemplo de generación de un gráfico para la métrica IngestFramerate
a través del SDK de Amazon CloudWatch.
const getMetricImage = async (arn, startDate, endDate) => { const cloudWatchClient = new CloudWatchClient(); const getMetricWidgetImageInput = { MetricWidget: JSON.stringify({ metrics: [ [ "AWS/IVS", "IngestFramerate", "Channel", arn.split("/")[1] ] ], start: startDate, end: endDate, period: 5 }) }; const getMetricWidgetImageRequest = new GetMetricWidgetImageCommand(getMetricWidgetImageInput); const getMetricWidgetImageResponse = await cloudWatchClient.send(getMetricWidgetImageRequest); return getMetricWidgetImageResponse; }; const metricImage = await getMetricImage( process.env.DEMO_CHANNEL_ARN, new Date('2023-01-20T14:30:11.000Z'), new Date('2023-01-20T14:49:15.000Z') );
La llamada a GetMetricWidgetImageCommand
devuelve un objeto JSON similar al siguiente:
{ '$metadata': { httpStatusCode: 200, requestId: '[redacted]', extendedRequestId: undefined, cfId: undefined, attempts: 1, totalRetryDelay: 0 }, MetricWidgetImage: Uint8Array(36660) [ 137, 80, 78, ... 36560 more items ] }
Podemos convertir Uint8Array
en una cadena base64:
const buffer = Buffer.from(metricImage.MetricWidgetImage); console.log(buffer.toString('base64'));
Que devuelve una cadena base64:
iVBORw0KGgoAAAANSUhEUgAAAlgAAAGQCAIAAAD9V4nPA...
Eso se puede usar para renderizar una imagen:
Incluso podemos combinar varias métricas en una sola imagen pasando métricas adicionales a GetMetricWidgetImageCommand
.
En esta publicación, analizamos cómo recuperar métricas de estado para una transmisión en vivo de Amazon IVS y representarlas como gráficos. Estén atentos a una publicación futura en la que analizaremos algunas de las otras métricas disponibles a través de Amazon CloudWatch relacionadas con los espectadores de transmisiones en vivo.