Implementing a Virtual Channel

⚠️

Warning

This playbook implements a Virtual Channel with the management of Categories that has been deprecated.

1. Building a timeline

Define a channel start-time

By default, when creating a Virtual Channel service, the manifest delivered by broadpeak.io for this service, references the original content defined when the Service was created, until a program is scheduled. From there, any program can be scheduled in the future. The first program defines the beginning on your Virtual Timeline, this is your T0.

In some cases, you may not need to schedule content on a specific period of the day/night, while you still want the channel to be available in the EPG. It is perfectly fine not to schedule any program on the service, broadpeak.io will reference the original content defined at Service creation in the manifest when no programs are scheduled.

📘

Note

Commercially, your consumption will be counted as soon as the Virtual Channel Service is created. The time where no programs are scheduled on the channel is still considered as using the Service, and you will be charged for it.

Virtual Channel

If you don't intend to enable personalization per Audience in your service, and that you have skipped step 3, then this section is for you. If instead, you intend to use some personalization per Audience, you can go to the next chapter.

Scheduling

Program scheduling is achieved through the use of the broadpeak.io API, which can be found here. To better understand the concept of scheduling on broadpeak.io we invite you to check the Key concepts section.

Scheduling a Program

To schedule a VOD, or Live event program you must send a content replacement API Call as defined here (REST)

The mandatory information which needs to be provided using the REST API is as follows:

  • serviceId: this is the Id of the Virtual Channel service that you have created.
  • name: you must choose a name for your blackout slot.
  • start-time: the time you want the program to start. For the first program, this is your T0.
  • replacement: you must provide the Id of the broadpeak.io Source of the content you want to program, as an object.
  • duration: you must provide the duration of the program. It should be the duration of the VOD or Live event or if you don't want to schedule the whole asset, the duration time it should be displayed on the screen.

As a result the program will be scheduled at the defined start-time, for the provided duration.

Scheduling consecutive Programs

To build a full Virtual Channel, Programs must be scheduled consecutively. A content replacement slot must be created for each program to schedule, and timing shall be computed accordingly.

The logic is simple: the start-time of the next program is the sum of the start-time and the duration of the previous program. So to schedule three programs consecutively on a Virtual Channel service which Id is 10, from 2am, I would have to send the three following calls:

Sources:
VOD1:

  • broadpeak.io id: 1001
  • duration: 1800 seconds

VOD2

  • broadpeak.io id: 1002
  • duration: 3600 seconds

VOD3

  • broadpeak.io id: 1003
  • duration: 7200 seconds

Virtual Timeline:

Content replacement API calls:
Call 1:

  • serviceId: 10
  • name: program_vod_1
  • start-time: 2022-06-06T02:00:00Z
  • replacement: { id: 1001 }
  • duration: 1800
curl --request POST \
     --url https://api.broadpeak.io/v1/services/virtual-channel/10/slots \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer XXXX' \
     --header 'Content-Type: application/json' \
     --data '
{
     "replacement": {
          "id": 1001
     },
     "startTime": "2022-06-06T02:00:00Z",
     "name": "program_vod_1",
     "duration": 1800
}
'

Call 2:

  • serviceId: 10
  • name: program_vod_2
  • start-time: 2022-06-06T02:00:00Z + 1800 seconds = 2022-06-06T02:30:00Z
  • replacement: { id: 1002 }
  • duration: 3600
curl --request POST \
     --url https://api.broadpeak.io/v1/services/virtual-channel/10/slots \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer XXXX' \
     --header 'Content-Type: application/json' \
     --data '
{
     "replacement": {
          "id": "1002"
     },
     "startTime": "2022-06-06T02:30:00Z",
     "name": "program_vod_2",
     "duration": 3600
}
'

Call 3:

  • serviceId: 10
  • name: program_vod_3
  • start-time: 2022-06-06T02:30:00Z + 3600 = 2022-06-06T03:30:00Z
  • replacement: { id: 1003 }
  • duration: 7200
curl --request POST \
     --url https://api.broadpeak.io/v1/services/virtual-channel/10/slots \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer XXXX' \
     --header 'Content-Type: application/json' \
     --data '
{
     "replacement": {
          "id": 1003
     },
     "startTime": "2022-06-06T03:30:00Z",
     "name": "program_vod_3",
     "duration": 7200
}
'
Updating your schedule

In the event you need to make some change on the program scheduled, it is possible to update an existing content replacement slot to update some of the parameters such as the Source and the duration. This could be the case for sport content where sometimes games run overtime. The API documentation to update an existing slot is available here (REST) or here (ESNI).

🚧

Extending or shortening a scheduled program

Updating a program by extending or reducing the duration of the content-replacement might have an impact on your schedule. In fact, to ensure the best quality of experience, if one program is being shortened or extended, all the following programs must be updated as their start-time will most likely change as well. Don't forget to update the whole Virtual Timeline!

Personalized Virtual Channel

Scheduling

Channels can be personalized per Audience. To implement personalized Virtual Channels, the logic is the same, but slots must contain information about the Audience it targets.

For the sake of simplicity, we will take an example where TV Subscribers are split into three groups, Seniors, Adults, and young Adults. We will assume that Seniors are people of age going from 60 to 99 years old, Adults from 35 to 59 years old, and young Adults from 21 to 34 years old.

  • Seniors: 60 to 99 years old
  • Adults: 35 to 59 years old
  • Young Adults: 21 to 34 years old

From there, we will want to create three Variants on the Virtual Service Id 10, with some programs being common to the three Audiences, and others that are specific to each Audience. We will assume for this example that the Virtual Timeline is as below:

VOD 2 and VOD 4 are programs that are being scheduled regardless of the Audience, so everyone will experience it at the same time, for the same duration.

For Variant 1 which represents the Seniors, we need to send three content replacement calls for VOD1, VOD3, and LIVE1:

Call 1

curl --request POST \
     --url https://api.broadpeak.io/v1/services/virtual-channel/10/slots \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer XXXX' \
     --header 'Content-Type: application/json' \
     --data '
{
     "replacement": {
          "id": 1001
     },
     "categories": [
          {
               "key": "category",
               "value": "55"
          },
          {
               "key": "category",
               "value": "56"
          },
          .....
          {
               "key": "category",
               "value": "99"
          }
     ],
     "startTime": "2022-06-06T02:00:00Z",
     "name": "program_vod_1",
     "duration": 1800,
     "categoryName": "Seniors"
}

Call 2

curl --request POST \
     --url https://api.broadpeak.io/v1/services/blackout/10/slots \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer XXXX' \
     --header 'Content-Type: application/json' \
     --data '
{
     "replacement": {
          "id": 1002
     },
     "categories": [
          {
               "key": "category",
               "value": "55"
          },
          {
               "key": "category",
               "value": "56"
          },
          .....
          {
               "key": "category",
               "value": "99"
          }
     ],
     "startTime": "2022-06-06T03:30:00Z",
     "name": "program_vod_2",
     "duration": 3000,
     "categoryName": "Seniors"
}

Call 3

curl --request POST \
     --url https://api.broadpeak.io/v1/services/virtual-channel/10/slots \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer XXXX' \
     --header 'Content-Type: application/json' \
     --data '
{
     "replacement": {
          "id": 1003
     },
     "categories": [
          {
               "key": "category",
               "value": "55"
          },
          {
               "key": "category",
               "value": "56"
          },
          .....
          {
               "key": "category",
               "value": "99"
          }
     ],
     "startTime": "2022-06-06T05:20:00Z",
     "name": "program_vod_3",
     "duration": 1800,
     "categoryName": "Seniors"
}

For Variant 2 which represent the Adults, we need to send four content replacement calls for LIVE21, VOD22, VOD23 and VOD24.
Call 1 :

curl --request POST \
     --url https://api.broadpeak.io/v1/services/virtual-channel/10/slots \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer XXXX' \
     --header 'Content-Type: application/json' \
     --data '
{
     "replacement": {
          "id": 0021
     },
     "categories": [
          {
               "key": "category",
               "value": "35"
          },
          {
               "key": "category",
               "value": "36"
          },
          .....
          {
               "key": "category",
               "value": "54"
          }
     ],
     "startTime": "2022-06-06T02:00:00Z",
     "name": "program_vod_21",
     "duration": 1800,
     "categoryName": "Adults"
}

Call 2 :

curl --request POST \
     --url https://api.broadpeak.io/v1/services/virtual-channel/10/slots \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer XXXX' \
     --header 'Content-Type: application/json' \
     --data '
{
     "replacement": {
          "id": 1022
     },
     "categories": [
          {
               "key": "category",
               "value": "35"
          },
          {
               "key": "category",
               "value": "36"
          },
          .....
          {
               "key": "category",
               "value": "54"
          }
     ],
     "startTime": "2022-06-06T03:30:00Z",
     "name": "program_vod_22",
     "duration": 1500,
     "categoryName": "Adults"
}

Call 3 :

curl --request POST \
     --url https://api.broadpeak.io/v1/services/virtual-channel/10/slots \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer XXXX' \
     --header 'Content-Type: application/json' \
     --data '
{
     "replacement": {
          "id": 0023
     },
     "categories": [
          {
               "key": "category",
               "value": "35"
          },
          {
               "key": "category",
               "value": "36"
          },
          .....
          {
               "key": "category",
               "value": "54"
          }
     ],
     "startTime": "2022-06-06T03:55:00Z",
     "name": "program_vod_23",
     "duration": 1500,
     "categoryName": "Adults"
}

Call 4 :

curl --request POST \
     --url https://api.broadpeak.io/v1/services/virtual-channel/10/slots \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer XXXX' \
     --header 'Content-Type: application/json' \
     --data '
{
     "replacement": {
          "id": 0024
     },
     "categories": [
          {
               "key": "category",
               "value": "35"
          },
          {
               "key": "category",
               "value": "36"
          },
          .....
          {
               "key": "category",
               "value": "54"
          }
     ],
     "startTime": "2022-06-06T05:20:00Z",
     "name": "program_vod_24",
     "duration": 2000,
     "categoryName": "Adults"
}

For Variant 3, which represents the Young Adults, we need to send three content replacement calls for VOD31, VOD32 and VOD 33.
Call 1

curl --request POST \
     --url https://api.broadpeak.io/v1/services/virtual-channel/10/slots \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer XXXX' \
     --header 'Content-Type: application/json' \
     --data '
{
     "replacement": {
          "id": 1031
     },
     "categories": [
          {
               "key": "category",
               "value": "21"
          },
          {
               "key": "category",
               "value": "22"
          },
          .....
          {
               "key": "category",
               "value": "34"
          }
     ],
     "startTime": "2022-06-06T02:00:00Z",
     "name": "program_vod_31",
     "duration": 1800,
     "categoryName": "YoungAdults"
}

Call 2

curl --request POST \
     --url https://api.broadpeak.io/v1/services/virtual-channel/10/slots \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer XXXX' \
     --header 'Content-Type: application/json' \
     --data '
{
     "replacement": {
          "id": 1032
     },
     "categories": [
          {
               "key": "category",
               "value": "21"
          },
          {
               "key": "category",
               "value": "22"
          },
          .....
          {
               "key": "category",
               "value": "34"
          }
     ],
     "startTime": "2022-06-06T03:30:00Z",
     "name": "program_vod_32",
     "duration": 3600,
     "categoryName": "YoungAdults"
}

Call 3

curl --request POST \
     --url https://api.broadpeak.io/v1/services/virtual-channel/10/slots \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer XXXX' \
     --header 'Content-Type: application/json' \
     --data '
{
     "replacement": {
          "id": 1033
     },
     "categories": [
          {
               "key": "category",
               "value": "21"
          },
          {
               "key": "category",
               "value": "22"
          },
          .....
          {
               "key": "category",
               "value": "34"
          }
     ],
     "startTime": "2022-06-06T05:20:00Z",
     "name": "program_vod_33",
     "duration": 1500,
     "categoryName": "YoungAdults"
}

Since both VOD 2 and VOD4 should be scheduled at the same time for all Audiences, we will create two unconditional slots.

Call 1:

curl --request POST \
     --url https://api.broadpeak.io/v1/services/virtual-channel/10/slots \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer XXXX' \
     --header 'Content-Type: application/json' \
     --data '
{
     "replacement": {
          "id": 1002
     },
     "startTime": "2022-06-06T02:30:00Z",
     "name": "program_vod_2_unconditional",
     "duration": 3600,
}
'

Call 2:

curl --request POST \
     --url https://api.broadpeak.io/v1/services/virtual-channel/10/slots \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer XXXX' \
     --header 'Content-Type: application/json' \
     --data '
{
     "replacement": {
          "id": 1004
     },
     "startTime": "2022-06-06T04:20:00Z",
     "name": "program_vod_4_unconditional",
     "duration": 3600,
}
'

📘

Enabling DASH and HLS on your Virtual Channel

In broadpeak.io, a Virtual Channel only delivers a single format, DASH or HLS. When the need to use both formats raises, two different Virtual Channel Services need to be created. All Slots created on the DASH Service, must also be created on the HLS Service. The example above only shows the API call that would be sent to either a DASH or an HLS Service.

2. Scheduling system

The scheduling system is the component responsible for creating the schedule of your virtual channel on broadpeak.io to make sure that different sets of audiences watch the content they are allowed to watch.

Time synchronization

Virtual Channel application and program scheduling are all based on timing. Inaccurate timing between the programing system and broadpeak.io can lead to unexpected behavior and can have commercial and legal impacts.
To avoid this consequence, it is best to ensure the accuracy of the synchronization between systems, so we invite you to use a time synchronization mechanism (NTP, Chrony).

You can find more information in the Using broadpeak.io with a CDN section and in the Manifest manipulationsection.

Code and requests samples

If you don't feel like jumping straight into coding to build the logic to interop your programming system with broadpeak.io, there is a tool powered by swagger.io available on the API reference section, that can help you send sample requests to broadpeak.io! Give it a try, it's pretty cool!

In the same section, you can find code suggestions that you can use to build your application faster. A set of the most adopted languages is available.

Alternatively you can try our Postman Collections as well 🚀
Run in Postman

3. Streaming

Once the different programs, whether they are VOD or Live events, have been scheduled on a Virtual Channel, the schedule should be reflected and personalization should be implemented when it applies. To do so, the Virtual Channel and the different Sources used as program, must be configured to be delivered through a CDN. More information about CDN configuration can be found in the Using broadpeak.io with a CDNsection.

As an outcome of the CDN configuration, a streaming link which points to the CDN FQDN is provided. It should be used in the Service Plan and provided to players when they request to stream your Virtual Channel. It should look like the following:

https://myCDNFQDN/**d3d9446802a**/myStream/myOutput/index.mpd

Identification of the Audience when streaming

When using some level of personalization on a Virtual Channel service, the player or the service platform needs to specify some information about the Audience in the streaming request. broadpeak.io expects to receive query parameters which identify the category or the zip code in the streaming request. This way, it can identify which Audience the viewer belongs to and personalize the content accordingly.

The segment is identified with a subscriber Id

Example:

  • Audience sub1 : 0000001
  • Audience sub2 : 0000002

Streaming links per Audience:

The segment is identified with a device id

Example:

  • Audience device 1: ABCDEFG1
  • Audience device 2: ABCDEFG2

Streaming links per Audience:

The segment is identified with a subscriber profile type

Examples:

  • Adults
  • Kids
  • Men
  • Women
  • Etc…

Streaming links per Audience:

The segment is a group of zip codes

Ex:

Audience NYC :

  • zip code: 10001
  • zip code: 10002
  • ……………….,
  • zip code: 10100

Streaming links per Audience: