Solution: Virtual Channels - EyevinnOSC/community GitHub Wiki

Getting Started

About Virtual Channels

Virtual channels is a technology where you can generate linear TV channels from a library of Video On-Demand (VOD) files without having to do any live transcoding. This is the most cost-efficient solution to generate linear TV channels at scale.

A live transcoder converts a video signal into downloadable media chunks and a playlist that is continuously updated with links to new media chunks. A video player continuously polls this playlist and downloads added media chunks and stitch these together in the player. The media chunks are created in real-time.

Video on-demand (VOD) also consists of a playlist of downloadable media chunks with the difference that these are created once and not in real time.

A virtual channels engine also produces a playlist that it continuously updates with new media chunks but the difference is that does not produce any new media chunks and reuses the media chunks from the VOD. The video player interprets this as a live playlist and handles it as a live stream. This is an efficient approach for providing a linear TV channels that mainly consists of pre-produced and non-live content, and as no real-time transcoding needs to take place you can scale this out and provide a great number of channels with a very low CPU consumption.

The FAST Channel Engine in Eyevinn Open Source Cloud is an open source virtual channels engine.

Virtual channels with ads inserted between and inside a program

This tutorial describes how you with the open source FAST Channel Engine and the HLS VOD Stitcher, made available as a service in Eyevinn Open Source Cloud, can produce virtual channels with ads inserted between and inside a program.

docs_vc_with_ads

Prerequisites

  • If you have not already done so, sign up for an Eyevinn OSC account.
  • This requires the use of two services which means you need to be on at least the Startup plan.
  • If using the sample webhook as a service you can purchase it separately or upgrade the plan to Business where more services are included.

Step 1: Create a HLS VOD Stitcher

Navigate to the HLS VOD Stitcher service in the web console. Click on the button "Create stitcher".

Skärmavbild 2024-11-25 kl  23 11 49

Give the stitcher a name, in this case we name it guide.

Note down the URL to this instance, in our case it is https://eyevinnlab-guide.eyevinn-lambda-stitch.auto.prod.osaas.io.

Step 2: Provide a webhook

The webhook is an endpoint that the engine will send an HTTP request to whenever it is time to switch to next program. This is where you build the logic on what the engine should play next. It provides the channelId as a query parameter which can be used as a basis for decision. Below is an example of a webhook in NodeJS that we will use as a base.

const fastify = require('fastify');
const { randomUUID } = require('node:crypto');

const app = fastify();
app.get('/loop/nextVod', (request, reply) => {
  const channelId = request.query.channelId;
  console.log(`Requesting next VOD for channel ${channelId}`);

  const vodResponse = {
    id: randomUUID(),
    title: 'Example',
    hlsUrl: 'https://lab.cdn.eyevinn.technology/osc/VINN-10/339bd6f7-5db1-4faf-9b95-eb5c90f017f5/index.m3u8'
  };
  reply.send(vodResponse);
});

app.listen({ port: 3000, host: '0.0.0.0' }, (err, address) => {
  if (err) console.error(err);
  console.log(`Server listening at ${address}`);
});

This webhook will basically generate a channel with one VOD on a loop. You can try it out using curl:

% curl http://localhost:3000/loop/nextVod
{"id":"bc15d513-b258-42bd-9514-25b839ce3702","title":"Example","hlsUrl":"https://lab.cdn.eyevinn.technology/osc/VINN-10/339bd6f7-5db1-4faf-9b95-eb5c90f017f5/index.m3u8"}

Now we will extend this webhook with another endpoint. This endpoint will return a VOD that uses the HLS VOD Stitcher to insert an ad in the beginning of the program and 20 seconds into the program.

...
app.get('/ads/nextVod', async (request, reply) => {
  const channelId = request.query.channelId;
  console.log(`Requesting next VOD for channel ${channelId}`);

  const STITCH_URL = 'https://eyevinnlab-guide.eyevinn-lambda-stitch.auto.prod.osaas.io'
  const response = await fetch(new URL('/stitch/', STITCH_URL),
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        uri: 'https://lab.cdn.eyevinn.technology/osc/VINN-10/339bd6f7-5db1-4faf-9b95-eb5c90f017f5/index.m3u8',
        breaks: [
          { 
            pos: 0,
            duration: 10000,
            url: 'https://lab.cdn.eyevinn.technology/osc/probably_the_best/006386b7-7aa8-46a2-86ce-3f2ecfb7e1a7/index.m3u8'
          },
          {
            pos: 20000,
            duration: 10000,
            url: 'https://lab.cdn.eyevinn.technology/osc/probably_the_best/006386b7-7aa8-46a2-86ce-3f2ecfb7e1a7/index.m3u8'
          }
        ]
      })
    }
  )
  if (response.ok) {
    const stitchedVod = await response.json();
    const vodResponse = {
      id: randomUUID(),
      title: 'Example with ads',
      hlsUrl: new URL(stitchedVod.uri, STITCH_URL).toString()
    };
    reply.send(vodResponse);
  } else {
    const vodResponse = {
      id: randomUUID(),
      title: 'Example',
      hlsUrl: 'https://lab.cdn.eyevinn.technology/osc/VINN-10/339bd6f7-5db1-4faf-9b95-eb5c90f017f5/index.m3u8'
    };
    reply.send(vodResponse);  
  }
});
...

Full source code for above is available on GitHub

Step 3: Launch sample webhook

This sample webhook is also available as a service in Eyevinn Open Source Cloud and what we will use to complete this tutorial.

Navigate to the FAST Engine Sample Webhook service and launch an instance.

Skärmavbild 2024-11-26 kl  00 03 42

Take a note of the URL to the created instance. In this case it is https://eyevinnlab-guide.eyevinn-ce-sample-webhook.auto.prod.osaas.io. We can test it with this curl command to verify that it is operational:

% curl -v https://eyevinnlab-guide.eyevinn-ce-sample-webhook.auto.prod.osaas.io/ads/nextVod
{"id":"d7de378c-3f45-45ed-82cc-02fd8e9f1714","title":"Example with ads","hlsUrl":"https://eyevinnlab-guide.eyevinn-lambda-stitch.auto.prod.osaas.io/stitch/master.m3u8?payload=eyJ1cmkiOiJodHRwczovL2xhYi5jZG4uZXlldmlubi50ZWNobm9sb2d5L29zYy9WSU5OLTEwLzMzOWJkNmY3LTVkYjEtNGZhZi05Yjk1LWViNWM5MGYwMTdmNS9pbmRleC5tM3U4IiwiYnJlYWtzIjpbeyJwb3MiOjAsImR1cmF0aW9uIjoxMDAwMCwidXJsIjoiaHR0cHM6Ly9sYWIuY2RuLmV5ZXZpbm4udGVjaG5vbG9neS9vc2MvcHJvYmFibHlfdGhlX2Jlc3QvMDA2Mzg2YjctN2FhOC00NmEyLTg2Y2UtM2YyZWNmYjdlMWE3L2luZGV4Lm0zdTgifSx7InBvcyI6MjAwMDAsImR1cmF0aW9uIjoxMDAwMCwidXJsIjoiaHR0cHM6Ly9sYWIuY2RuLmV5ZXZpbm4udGVjaG5vbG9neS9vc2MvcHJvYmFibHlfdGhlX2Jlc3QvMDA2Mzg2YjctN2FhOC00NmEyLTg2Y2UtM2YyZWNmYjdlMWE3L2luZGV4Lm0zdTgifV19"}

Step 4: Create a virtual channel

Now we are going to put these pieces together and create a virtual channel using this sample webhook. We will get a channel with a program on loop and with ads inserted between the program and 20 seconds into the program.

Navigate to FAST Channel Engine in the web console. Click on the button "Create channel". Enter the following settings and press Create.

Skärmavbild 2024-11-26 kl  00 07 41

  • Name: guide
  • Type: Webhook
  • URL: https://eyevinnlab-guide.eyevinn-ce-sample-webhook.auto.prod.osaas.io/ads/nextVod

Make sure you have set the option Demuxed to true as the VOD in this example have separated audio and video files. You should now have a channel up and running with a program on loop and with ads inserted.

Skärmavbild 2024-11-26 kl  00 08 56