api.video

Features

Documentation

Tips for Working with api.video Analytics Data

March 31, 2021 - Erikka Innes in Analytics, Python

analytics data, apivideo, api.video, video and live stream analysis

Analytics data - Photo by Luke Chesser on Unsplash

You may want to grab analytics data from api.video and then visualize it different ways. Today we'll take a look at the data you can use, what that data looks like, and the code snippets for data retrieval. api.video has three sets of analytics you can collect:

  • Video on Demand Session Analytics
  • Live Stream Session Analytics
  • Player Session Analytics

Everything is set up so you can pull details at a granular level - so for each request to the API, you would choose the video, live stream, or player you want details about, and send an individual request for information about that that asset. If you want to pull data for an individual asset, or multiple assets, the first thing you need to do is get a list of those assets.

You can also see a fun project using api.video analytics data over at Observable. We made a notebook that shows where all our live stream viewers watch from.

Get All Videos, Live Streams, or Players

The first step in using your analytics data, is to find out what you have available to analyze. You're going to want to know what videos, live streams, and players you have.

  1. Authenticate with your API key and get a token.
  2. Use the token with the List all videos, List all live streams, or List all players endpoint to get all listings for everything in that category.

The code for this part looks like this:

import requests
import json 

# Get api.video token 

url = "https://ws.api.video/auth/api-key"

payload = {"apiKey": "api key here"}
headers = {
    "Accept": "application/json",
    "Content-Type": "application/json"
}

response = requests.request("POST", url, json=payload, headers=headers)
response = response.json()
token = response.get("access_token")

# Retrieve the live-streams and write to file

url = "https://ws.api.video/live-streams"

querystring = {"currentPage":"1","pageSize":"25"}

headers = {
    "Accept": "application/json",
    "Authorization": token
    }

response = requests.request("GET", url, headers=headers, params=querystring)

response = response.json()

with open("live_stream.json", "w") as live:
    json.dump(response, live)

# Retrieve the VODs and write to file

url = "https://ws.api.video/videos"

querystring = {"currentPage":"1","pageSize":"25"}

headers = {
    "Accept": "application/json",
    "Authorization": token
    }

response = requests.request("GET", url, headers=headers, params=querystring)

response = response.json()

with open("vod.json", "w") as vod: 
    json.dump(response, vod)

# Retrieve all players and write to file

url = "https://ws.api.video/players"

querystring = {"currentPage":"1","pageSize":"25"}

headers = {
    "Accept": "application/json",
    "Authorization": token
    }

response = requests.request("GET", url, headers=headers, params=querystring)

response = response.json()

with open("players.json", "w") as players: 
    json.dump(response, players)

In this sample, we went through every endpoint and got a complete list of assets. Then, so we don't have to keep going back to the API for this information, we output each set of details to a .json file. You probably won't want to necessarily save this, but for learning or browsing, it's great to be able to open the file and see this data you'll be working with. If you want to experiment with retrieving data from these files and converting to different formats, these can be helpful.

Data Structure for a Live Stream

If you were to retrieve a single live stream, it would contain the data shown here, and a pagination section in case you have so many entries you need to retrieve multiple pages of asset listings.

{
    "data": [
        {
            "liveStreamId": "li312mYKSgQ6xs7taUeSaEKr",
            "createdAt": "2020-01-31T10:17:47+00:00",
            "updatedAt": "2020-09-23T17:58:08+00:00",
            "streamKey": "32287931-229e-42cf-b5f9-e91bcc1f7332",
            "name": "Live Stream",
            "public": true,
            "record": true,
            "broadcasting": false,
            "assets": {
                "iframe": "<iframe src=\"https://embed.api.video/live/li312mYKSgQ6xs7taUeSaEKr\" width=\"100%\" height=\"100%\" frameborder=\"0\" scrolling=\"no\" allowfullscreen=\"true\"></iframe>",
                "player": "https://embed.api.video/live/li312mYKSgQ6xs7taUeSaEKr",
                "hls": "https://live.api.video/li312mYKSgQ6xs7taUeSaEKr.m3u8",
                "thumbnail": "https://live.api.video/li312mYKSgQ6xs7taUeSaEKr/thumbnail.jpg"
            },
            "playerId": "ptSQlUSqn5KIn9tGxlA88Q1"
        }
    ],
    "pagination": {
        "currentPage": 1,
        "currentPageItems": 15,
        "pageSize": 25,
        "pagesTotal": 1,
        "itemsTotal": 15,
        "links": [
            {
                "rel": "self",
                "uri": "/live-streams?currentPage=1&pageSize=25"
            },
            {
                "rel": "first",
                "uri": "/live-streams?currentPage=1&pageSize=25"
            },
            {
                "rel": "last",
                "uri": "/live-streams?currentPage=1&pageSize=25"
            }
        ]
    }

Data Structure for a Video

As with live streams, if you were to retrieve a single video, it would contain the data shown here. Notice there's a ton of videos - 608 to be exact, and the pagination section provides details for grabbing additional pages of data so you can get an exhaustive list of all assets if you need it.

{
    "data": [ 
       {
            "videoId": "vi54QrBFkhpNoUVObqkZVYF",
            "title": "Test create video",
            "description": "",
            "public": true,
            "panoramic": false,
            "mp4Support": true,
            "publishedAt": "2020-02-19T14:47:48+00:00",
            "createdAt": "2020-02-19T14:47:48+00:00",
            "updatedAt": "2020-02-19T14:47:48+00:00",
            "tags": [],
            "metadata": [],
            "source": {
                "type": "upload",
                "uri": "/videos/vi54QrBFkhpNoUVObqkZVYF/source"
            },
            "assets": {
                "iframe": "<iframe src=\"https://embed.api.video/vod/vi54QrBFkhpNoUVObqkZVYF\" width=\"100%\" height=\"100%\" frameborder=\"0\" scrolling=\"no\" allowfullscreen=\"true\"></iframe>",
                "player": "https://embed.api.video/vod/vi54QrBFkhpNoUVObqkZVYF",
                "hls": "https://cdn.api.video/vod/vi54QrBFkhpNoUVObqkZVYF/hls/manifest.m3u8",
                "thumbnail": "https://cdn.api.video/vod/vi54QrBFkhpNoUVObqkZVYF/thumbnail.jpg"
            }
        }
    ],
    "pagination": {
        "currentPage": 1,
        "currentPageItems": 25,
        "pageSize": 25,
        "pagesTotal": 25,
        "itemsTotal": 608,
        "links": [
            {
                "rel": "self",
                "uri": "/videos?currentPage=1&pageSize=25"
            },
            {
                "rel": "first",
                "uri": "/videos?currentPage=1&pageSize=25"
            },
            {
                "rel": "next",
                "uri": "/videos?currentPage=2&pageSize=25"
            },
            {
                "rel": "last",
                "uri": "/videos?currentPage=25&pageSize=25"
            }
        ]
    }
}

Data Structure for a Player

For players you get details about how each one is customized. It has the same pagination feature as the other data structures. Because you don't use this information to retrieve session details, it's more for informational purposes only if you wanted to know about the players you have.

{
   "data": [ 
        {
            "playerId": "ptSQlUSqn5KIn9tGxlA88Q1",
            "createdAt": "2020-08-25T14:27:08+00:00",
            "updatedAt": "2020-08-26T17:42:55+00:00",
            "assets": {
                "logo": "https://cdn.api.video/player/ptSQlUSqn5KIn9tGxlA88Q1/logo.png",
                "link": "https://twitter.com/uwbuckybadger"
            },
            "shapeMargin": 0,
            "shapeRadius": 0,
            "shapeAspect": "flat",
            "shapeBackgroundTop": "rgba(50, 50, 50, .7)",
            "shapeBackgroundBottom": "rgba(50, 50, 50, .8)",
            "text": "rgba(218,223,225, 1)",
            "link": "rgba(100,101,105, 1)",
            "linkHover": "rgba(249,249,249, 1)",
            "linkActive": "rgba(197,5,12,1)",
            "trackPlayed": "rgba(155,0,0, .95)",
            "trackUnplayed": "rgba(218,223,225, .35)",
            "trackBackground": "rgba(218,223,225, .2)",
            "backgroundTop": "rgba(197,5,12, .7)",
            "backgroundBottom": "rgba(247,247,247, .7)",
            "backgroundText": "rgba(197,5,12, 1)",
            "enableApi": true,
            "enableControls": true,
            "forceAutoplay": true,
            "hideTitle": false,
            "forceLoop": true
        }
    ],
    "pagination": {
        "currentPage": 1,
        "currentPageItems": 5,
        "pageSize": 25,
        "pagesTotal": 1,
        "itemsTotal": 5,
        "links": [
            {
                "rel": "self",
                "uri": "/players?currentPage=1&pageSize=25"
            },
            {
                "rel": "first",
                "uri": "/players?currentPage=1&pageSize=25"
            },
            {
                "rel": "last",
                "uri": "/players?currentPage=1&pageSize=25"
            }
        ]
    }
}

Retrieve Sessions

The next part of retrieving your data is to grab session information. Because the analytics endpoints are set up to be granular, you need the unique live stream, video, or player ID to use with the associated endpoint. Then you can retrieve details about all sessions for that endpoint. Live stream and video sessions come back using the same structure. Players are different (as you'll see).

The code to retrieve details about one asset for video or live stream would be:

import requests
import json

# Get api.video token 

url = "https://ws.api.video/auth/api-key"

payload = {"apiKey": "api key here"}
headers = {
    "Accept": "application/json",
    "Content-Type": "application/json"
}

response = requests.request("POST", url, json=payload, headers=headers)
response = response.json()
token = response.get("access_token")

# Retrieve all session details for one live stream

url = "https://ws.api.video/analytics/live-streams/liveStreamId"

querystring = {"currentPage":"1","pageSize":"25"}

headers = {
    "Accept": "application/json",
    "Authorization": token
    }

response = requests.request("GET", url, headers=headers, params=querystring)

response = response.json()

with open("live_stream_session_data.json", "w") as ls: 
    json.dump(response, ls)

# Retrieve all session details for one video 

url = "https://ws.api.video/analytics/videos/videoId"

querystring = {"currentPage":"1","pageSize":"25"}

headers = {
    "Accept": "application/json",
    "Authorization": token
    }

response = requests.request("GET", url, headers=headers, params=querystring)

response = response.json()

with open("vod_session_data.json", "w") as vod: 
    json.dump(response, vod)

# Retrieve all details of events that occurred in one session for a player

url = "https://ws.api.video/analytics/sessions/sessionId/events"

headers = {
    "Accept": "application/json",
    "Authorization": token
    }

response = requests.request("GET", url, headers=headers, params=querystring)

response = response.json()

with open("player_session_data.json", "w") as player: 
    json.dump(response, player)

Data Structure for Live Stream and Video

Live streams and videos bring back information with the same format. Something to remember is when the information comes back, it will not include the title of your live stream or video, or its type. If you were to get back one single session for a live stream or video, it would come back like this:

{
    "data": [
        {
            "session": {
                "sessionId": "ps2ThzKCMbrmT9ntv1AC4mVV",
                "loadedAt": "2021-02-05T14:46:34+00:00",
                "endedAt": "2021-02-05T14:46:37+00:00"
            },
            "location": {
                "country": "United Kingdom",
                "city": "Hitchin"
            },
            "referrer": {
                "url": "https://go.api.video/",
                "medium": "unknown",
                "source": "unknown",
                "searchTerm": "unknown"
            },
            "device": {
                "type": "computer",
                "vendor": "unknown",
                "model": "Other"
            },
            "os": {
                "name": "Mac OS X",
                "shortname": "Mac OS X",
                "version": "11.0.1"
            },
            "client": {
                "type": "unknown",
                "name": "Chrome",
                "version": "88.0.4324"
            }
        }
    ],
    "pagination": {
        "currentPage": 1,
        "currentPageItems": 8,
        "pageSize": 25,
        "pagesTotal": 1,
        "itemsTotal": 8,
        "links": [
            {
                "rel": "self",
                "uri": "/analytics/videos/vi1UQBDAMqAPCRxB3dmw1thc?currentPage=1&pageSize=25"
            },
            {
                "rel": "first",
                "uri": "/analytics/videos/vi1UQBDAMqAPCRxB3dmw1thc?currentPage=1&pageSize=25"
            },
            {
                "rel": "last",
                "uri": "/analytics/videos/vi1UQBDAMqAPCRxB3dmw1thc?currentPage=1&pageSize=25"
            }
        ]
    }
}

Data Structure for Player

Because you are reviewing session details on a player for a particular video or live stream, you may want to note this in your data at some point. The returned data for a session doesn't include details about what video or live stream it's for beyond repeating the session ID in the pagination URLs.

{
    "data": [
        {
            "type": "ready",
            "emittedAt": "2021-02-05T14:46:34+00:00",
            "at": 0
        },
        {
            "type": "play",
            "emittedAt": "2021-02-05T14:46:36+00:00",
            "at": 0
        },
        {
            "type": "pause",
            "emittedAt": "2021-02-05T14:46:37+00:00",
            "at": 1
        }
    ],
    "pagination": {
        "currentPage": 1,
        "currentPageItems": 3,
        "pageSize": 25,
        "pagesTotal": 1,
        "itemsTotal": 3,
        "links": [
            {
                "rel": "self",
                "uri": "/analytics/sessions/ps2ThzKCMbrmT9ntv1AC4mVV/events?currentPage=1&pageSize=25"
            },
            {
                "rel": "first",
                "uri": "/analytics/sessions/ps2ThzKCMbrmT9ntv1AC4mVV/events?currentPage=1&pageSize=25"
            },
            {
                "rel": "last",
                "uri": "/analytics/sessions/ps2ThzKCMbrmT9ntv1AC4mVV/events?currentPage=1&pageSize=25"
            }
        ]
    }
}

Tips for Handling Data

This section includes some tips for handling your analytics data.

  • It will be easier if you know what you want to do at the start so you can retrieve appropriate information for your project.
  • When creating a file to work with, remember that flattening the JSON makes your project easier. Flattening the JSON means that you undo the nesting for each entry, so that everything for each is in a single row.
  • You may want to add extra details when you retrieve informat for an asset, like a column for the title. If you mix your live stream and video data to get big picture analytics data, you may want to have another column that lists whether something is a live stream or video. Otherwise, you don't have a way to retrieve that information later.
  • If you don't know what you want to do, you may want to design a way to gather all the data together. One way is to put live stream and video data into a table, and then join that table to a player table based on session ID. This would be a way to build a master file of your data.

Erikka Innes

Developer Evangelist

Get started now

Connect your users with videos