Create your own FAST Channels based on VOD2Live Technology and Open Source Components

Eyevinn Technology
6 min readMar 6, 2023

--

VOD2Live is a technology to produce FAST channels of higher video and audio quality to a considerable lower cost than traditional methods. Instead of encoding and transcoding a live channel 24/7 it utilizes already transcoded and available VODs. In this blog post we will walk you through how you can create FAST channels based on this technology and with our open source components.

We will be using Docker throughout this blog post so it is recommended to have it installed before continuing.

The Eyevinn Channel Engine library is the core component of this solution and the component that uses VOD2Live technology to produce linear HLS live streams from already available HLS VOD streams. With the latest release (v4.0.0) of the library now including support for HLS CMAF and having audio and video in separate media segments, it now basically supports all non-DRM encrypted HLS flavors available out there.

The Channel Engine library is designed to not contain any type of business logic and decisioning on what to play next, instead that logic is placed outside of this component. You connect the engine library to an adapter that provides the engine information on what to play next.

const { ChannelEngine } = require('eyevinn-channel-engine');

const myAssetManager = new MyAssetManager();
const myChannelManager = new MyChannelManager();
const engine = new ChannelEngine(myAssetManager, { channelManager: myChannelManager });
engine.start();
engine.listen(process.env.PORT || 8080);

Eyevinn FAST Engine

Follow this tutorial for more details on how to build your own engine based on this library. However, in this setup we will be using the open source Eyevinn FAST Engine which is an implementation of this library bundled with some pre-built adapters as plugins. With the provided Docker container you can try it out with your content using the Loop-plugin. This plugin creates an HLS live stream by playing the provided HLS VOD on repeat.

docker run --rm -d -p 8000:8000 \
-e FAST_PLUGIN=Loop \
-e LOOP_VOD_URL=<uri-to-hls-vod> \
-e LOOP_CHANNEL_NAME=testchannel \
eyevinntechnology/fast-engine

When the container is up and running you can then access the HLS live stream at http://localhost:8000/channels/testchannel/master.m3u8 and try it out in your favourite HLS video player. The above assumes that the VOD has audio and video in separate media segments. If that is not the case you can add the -e OPTS_USE_DEMUXED_AUDIO=false to the command line above.

And to try it out with a sequence of VODs you can create a text-file containing a list of HLS URLs. Each line contains one HLS URL, e.g.

https://my-vod-cdn/vod1/index.m3u8
https://my-vod-cdn/vod2/index.m3u8
https://my-vod-cdn/vod3/index.m3u8

Put this text-file somewhere it can be downloaded and then we can use the Playlist plugin included in the FAST Engine container.

docker run --rm -d -p 8000:8000 \
-e FAST_PLUGIN=Playlist \
-e PLAYLIST_URL=https://my-site/playlist.txt \
-e PLAYLIST_CHANNEL_NAME=testchannel \
eyevinntechnology/fast-engine

The engine will then play the VODs in the same order in the text-file and start from the top after the last VOD has been played.

Now that we have verified we can use the FAST Engine to produce an HLS live stream from our types of VOD we can move on with the next step and to connect it with a schedule service.

Eyevinn Schedule Service

The Eyevinn Schedule Service is an open source service that manages channels and schedules. Create channels, populate the channels with schedule events and use the FAST Engine to produce the HLS live stream for each channel.

The service uses AWS DynamoDB as the database store and in this example setup we will be using a local AWS DynamoDB instance. Start a local AWS DynamoDB instance with this command:

docker run --rm -d -p 6000:8000 amazon/dynamodb-local

When this container is up and running you can start the Schedule Service.

docker run --rm -p 8080:8080 \
-e DB=dynamodb://host.docker.internal:6000/eu-north-1 \
-e AWS_ACCESS_KEY_ID=null \
-e AWS_SECRET_ACCESS_KEY=null \
-e IF=0.0.0.0 \
eyevinntechnology/schedule-service

Once this container is up and running you have the Swagger API docs available at http://localhost:8080/api/docs

To get the list of available channels you can use the Swagger API or curl

curl -X 'GET' \
'http://localhost:8080/api/v1/channels' \
-H 'accept: application/json'

A demo channel called eyevinn is available that is auto-populated with some demo content. You can obtain the current schedule with the following HTTP/curl command.

curl -X 'GET' \
'http://localhost:8080/api/v1/channels/eyevinn/schedule?date=2023-03-06' \
-H 'accept: application/json'

where you have replaced 2023-03-06 with today’s date.

In response you should get something similar to this:

[
{
"id": "83ef225b-89a0-4c19-9628-02c262d1cdf3",
"channelId": "eyevinn",
"title": "stswe19-industry-group-low-latency-hls",
"start_time": 1678118514195,
"end_time": 1678118910195,
"start": "2023-03-06T16:01:54.195Z",
"end": "2023-03-06T16:08:30.195Z",
"url": "http://lambda.eyevinn.technology/stitch/master.m3u8?payload=eyJ1cmkiOiJodHRwczovL2xhYi5jZG4uZXlldmlubi50ZWNobm9sb2d5L3N0c3dlMTktaW5kdXN0cnktZ3JvdXAtbG93LWxhdGVuY3ktaGxzLm1wNC9tYW5pZmVzdC5tM3U4IiwiYnJlYWtzIjpbeyJwb3MiOjAsImR1cmF0aW9uIjoxMDUwMDAsInVybCI6Imh0dHBzOi8vbWFpdHYtdm9kLmxhYi5leWV2aW5uLnRlY2hub2xvZ3kvVklOTi5tcDQvbWFzdGVyLm0zdTgifV19",
"duration": 396,
"type": "VOD"
},
{
"id": "160f2513-4c5b-4bea-99d9-24637b7d7c3e",
"channelId": "eyevinn",
"title": "OWL_MVP_2021",
"start_time": 1678118515195,
"end_time": 1678118514195,
"start": "2023-03-06T16:01:55.195Z",
"end": "2023-03-06T16:01:54.195Z",
"url": "http://lambda.eyevinn.technology/stitch/master.m3u8?payload=eyJ1cmkiOiJodHRwczovL2xhYi5jZG4uZXlldmlubi50ZWNobm9sb2d5L09XTF9NVlBfMjAyMS5tcDQvbWFuaWZlc3QubTN1OCIsImJyZWFrcyI6W3sicG9zIjowLCJkdXJhdGlvbiI6MTA1MDAwLCJ1cmwiOiJodHRwczovL21haXR2LXZvZC5sYWIuZXlldmlubi50ZWNobm9sb2d5L1ZJTk4ubXA0L21hc3Rlci5tM3U4In1dfQ==",
"duration": -1,
"type": "VOD"
},
...
]

Let us now connect the Schedule Service with the FAST Engine.

docker run --rm -p 8000:8000 \
-e OPTS_USE_DEMUXED_AUDIO=false \
-e FAST_PLUGIN=ScheduleService \
-e SCHEDULE_SERVICE_API_URL=http://host.docker.internal:8080/api/v1 \
eyevinntechnology/fast-engine

Give it a couple of minutes for the channel to become ready and then you can play the eyevinn channel with this URL: http://localhost:8000/channels/eyevinn/master.m3u8

We need to use the OPTS_USE_DEMUXED_AUDIO=false as the demo channel contains VODs that has audio and video in the same media segments. Now that we have the demo channel up and running we can move on and create a channel with your content.

Create a new channel using the API and againcurl

curl -X 'POST' \
'http://localhost:8080/api/v1/channels' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"id": "mychannel",
"tenant": "test",
"title": "My channel"
}'

We create a channel with the ID mychannel and we can check that is created by listing the schedule events for this channel.

curl -X 'GET' \
'http://localhost:8080/api/v1/channels/mychannel/schedule?date=2023-03-06' \
-H 'accept: application/json'

It should return an empty array which is expected as we have not created any schedule events yet. Now let us fill this channel with some events and to do that we will use the same playlist as previously and the playlist auto-scheduler to populate the channel with events. The playlist auto-scheduler has the same logic as the Playlist plugin we used before.

curl -X 'POST' \
'http://localhost:8080/api/v1/auto/playlist' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"id": "mychannelscheduler",
"tenant": "test",
"url": "https://my-site/playlist.txt",
"channelId": "mychannel"
}'

Now if we fetch the schedule events for this channel we will have some events based on the playlist provided. Now the channel is ready to be streamed. Point your HLS video player to the URL: http://localhost:8000/channels/mychannel/master.m3u8

If your playlist contains VODs that have separate audio and video segments you need to create the channel with the audio tracks defined, e.g.

curl -X 'POST' \
'http://localhost:8080/api/v1/channels' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"id": "mychannel",
"tenant": "test",
"title": "My channel",
"audioTracks": [
{
"language": "en",
"name": "English",
"default": true
}
]
}'

And the FAST-Engine container with the option OPTS_USE_DEMUXED_AUDIO=true A limitation today is that one FAST Engine instance can be working in either mode. The current workaround is to run two FAST Engine instances where one has the demuxed audio option enabled and the other does not. Both can be connected to the same Schedule Service as the engine will filter out channels that it cannot support.

All of the above is also available as a docker-compose file as a starting point.

If you want to extend this example setup into a more production like setup we are happy to assist. Just drop an email to sales@eyevinn.se and we can tell you more how we can help. We are vendor-independent video streaming experts that provides tech strategy consulting, video software development and open-source contributions.

--

--

Eyevinn Technology

We are consultants sharing the passion for the technology for a media consumer of the future.