Live Stream Viewer Analytics with Amazon IVS

Todd Sharp - Feb 24 '23 - - Dev Community

In my last post, we looked at monitoring Amazon Interactive Video Service (Amazon IVS) live stream health metrics via the Amazon CloudWatch SDK. Health monitoring is a super important topic that is crucial to keeping your live streaming applications performant. Another crucial element is viewer analytics. In this post, we'll look at a few ways to provide insight into stream viewers.

Much of this post will look similar to my last post. That's because viewer data is also stored in CloudWatch and can be retrieved via the SDK. There is one additional method, as we'll see below, to get a count of the current viewers of a live stream which is a handy way to get a count that can be displayed on your front end.

Note: While this post focuses on live stream channel viewers, you can also retrieve metrics about your Amazon IVS chat rooms like ConcurrentChatConnections and messages Delivered. We won't cover that in this post, but you can check out the docs to learn more.

Retrieving Concurrent Views via the CloudWatch Console

If you're just looking for a glance at viewer data without retrieving the raw data, you can view your ConcurrentViews via the CloudWatch console. First, select All metrics, then choose IVS.

CloudWatch console

Next, select By channel.

CloudWatch dimensions

Then select the checkbox in the row that contains ConcurrentViews for any of your Amazon IVS channels.

CloudWatch chart

Another way to find concurrent views for a stream session is via the Amazon IVS console. Select your channel, then choose a Stream id from the channel details page.

Stream sessions

The details for a stream session will contain several charts, one of which contains the Concurrent views for the session.

Concurrent view chart

Retrieving Concurrent Views via the CloudWatch SDK

To integrate this data into your own application, you can retrieve the data via the CloudWatch SDK. Similarly to health metrics, you'll need a the channel's ARN, a StartTime, and an EndTime to retrieve ConcurrentViews.

Instead of randomly choosing the start and end times, it probably makes sense to dynamically obtain these times by choosing the start and end times from a live stream session. You can retrieve a list of stream sessions via the Amazon IVS SDK (as we saw in the previous post).

Reminder: You'll always need an EndTime, even for streams that are currently live. For live streams, you can always use the current time as the EndTime when using the SDK to retrieve metrics.

To retrieve this data via the AWS SDK for JavaScript (v3), you will need to install the @aws-sdk/client-cloudwatch package and create an instance of the client (new CloudWatchClient()). After the client instance is created, set a few variables for the required inputs.



const startTime = new Date('2023-02-10T14:00:00.000Z');
const endTime = new Date('2023-02-10T14:30:00.000Z');
const arn = process.env.DEMO_CHANNEL_ARN;


Enter fullscreen mode Exit fullscreen mode

Next, create an input object. The input object will contain the StartTime, EndTime, and an array of MetricDataQueries. The queries array will contain a single object that specifies the MetricName (ConcurrentViews), the Namespace (AWS/IVS), and the Dimensions to filter by (channel name, in this case).



const getMetricDataInput = {
  StartTime: startTime,
  EndTime: endTime,
  MetricDataQueries: [{
    Id: "concurrentviews",
    MetricStat: {
      Metric: {
        MetricName: "ConcurrentViews",
        Namespace: "AWS/IVS",
        Dimensions: [{ Name: "Channel", Value: arn.split("/")[1] }]
      },
      Period: 5,
      Stat: "Average",
    }
  }],
  MaxDatapoints: 100
};


Enter fullscreen mode Exit fullscreen mode

Now send the request and log the result.



const getMetricDataRequest = new GetMetricDataCommand(getMetricDataInput);
let metrics = await cloudWatchClient.send(getMetricDataRequest);
console.log(metrics);


Enter fullscreen mode Exit fullscreen mode

Which produces output that looks like the following (extraneous SDK metadata removed for brevity):



{
  "MetricDataResults": [
    {
      "Id": "concurrentviews",
      "Label": "ConcurrentViews",
      "Timestamps": [
        "2023-02-10T14:29:00.000Z",
        "2023-02-10T14:28:00.000Z",
        "2023-02-10T14:27:00.000Z",
        "2023-02-10T14:26:00.000Z",
        "2023-02-10T14:22:00.000Z"
      ],
      "Values": [
        3,
        3,
        3,
        3,
        10
      ],
      "StatusCode": "PartialData"
    }
  ]
}


Enter fullscreen mode Exit fullscreen mode

You can filter, sort, and output this data to produce a format useful for generating charts.



const viewMetrics = metrics
  .MetricDataResults
  .find((metric) => metric.Id === 'concurrentviews');

const viewValues = viewMetrics.Values.reverse();

const viewData = [];

viewMetrics
  .Timestamps
  .reverse()
  .forEach((t, i) => {
    viewData.push({
      timestamp: t,
      concurrentviews: viewValues[i],
    })
  });

console.log(JSON.stringify(viewData));


Enter fullscreen mode Exit fullscreen mode

Which produces an array of objects.



[
  {
    "timestamp": "2023-02-10T14:22:00.000Z",
    "concurrentviews": "10.00"
  },
  {
    "timestamp": "2023-02-10T14:26:00.000Z",
    "concurrentviews": "3.00"
  },
  ...
]


Enter fullscreen mode Exit fullscreen mode

You can use this data with our favorite charting library (or a generic online chart generator like I did).

Concurrent View Chart

Generating Chart Images with the CloudWatch SDK

In the last post, we looked at generating the image directly via the CloudWatch SDK. This approach also applies to your view metrics.



const startTime = new Date('2023-02-10T14:00:00.000Z');
const endTime = new Date('2023-02-10T14:25:00.000Z');
const arn = process.env.DEMO_CHANNEL_ARN;

const cloudWatchClient = new CloudWatchClient();
const getMetricWidgetImageInput = {
  MetricWidget: JSON.stringify({
    metrics: [
      [
        "AWS/IVS",
        "ConcurrentViews",
        "Channel",
        arn.split("/")[1]
      ]
    ],
    start: startTime,
    end: endTime,
    period: 5,
    stat: "Average"
  })
};
const getMetricWidgetImageRequest = new GetMetricWidgetImageCommand(getMetricWidgetImageInput);
const metricImage = await cloudWatchClient.send(getMetricWidgetImageRequest);


Enter fullscreen mode Exit fullscreen mode

Which returns an object with the key MetricWidgetImage that contains an array buffer (Uint8Array) containing the chart image.



{
  "MetricWidgetImage": {
    "0": 137,
    "1": 80,
    "2": 78,
    ...
  }
}


Enter fullscreen mode Exit fullscreen mode

To convert this array buffer to a base64 string:



const buffer = Buffer.from(metricImage.MetricWidgetImage);
console.log(buffer.toString('base64'));



Enter fullscreen mode Exit fullscreen mode

Which gives us:



iVBORw0KGgoAAAANSUhEUgAAAlgAAAGQCAIAAAD9V4nPAAAACXBIWXMA...


Enter fullscreen mode Exit fullscreen mode

That can be converted to an image that looks like so:

CloudWatch generated chart

Retrieving Current Live View Sessions for a Channel

As mentioned above, you can easily get a count of the current view sessions for the active live stream on a channel via the Amazon IVS client module in the AWS SDK. For this, use the GetStream method.



import { GetStreamCommand, IvsClient } from "@aws-sdk/client-ivs";

const client = new IvsClient();

const getStreamCommandInput = {
  channelArn: process.env.DEMO_CHANNEL_ARN,
};
const getStreamRequest = new GetStreamCommand(getStreamCommandInput);
const getStreamResponse = await client.send(getStreamRequest);
console.log(getStreamResponse);


Enter fullscreen mode Exit fullscreen mode

Which produces output like the following.



{
  "stream": {
    "channelArn": "arn:aws:ivs:us-east-1:[redacted]:channel/[redacted]",
    "health": "HEALTHY",
    "playbackUrl": "https://[redacted].us-east-1.playback.live-video.net/api/video/v1/us-east-1.[redacted].channel.x4aGUUxIp5Vw.m3u8",
    "startTime": "2023-02-10T15:46:36.000Z",
    "state": "LIVE",
    "streamId": "st-[redacted]",
    "viewerCount": 5
  }
}


Enter fullscreen mode Exit fullscreen mode

Note the property viewerCount which is a live count of view sessions for the current live stream.

Summary

In this post, we learned how to retrieve view data for our Amazon IVS live streams via the CloudWatch and Amazon IVS SDKs. To learn more, check out the documentation.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player