Server-less OTT-Only Playout

Eyevinn Technology
Feb 23, 2018 · 5 min read

We asked ourselves the question: If we would startup a TV channel for distribution only over the Internet (OTT) today, how would a technical solution for this look like? The answer to this question was elaborated around in a previous post here, and now we have at our website tv.eyevinn.technology a proof-of-concept demonstration of a fully “server-less” OTT-only TV channel playout. In this post we will describe how this was done.

The reason why we wanted a server-less solution was that we wanted the cost to be driven directly by the amount of content we have and number of active users. Basically if no-one were watching we would only pay for the storage cost. A storage cost that correlated directly to the amount of content available. Another benefit of having a server-less design is that it allows us to scale up and down the solution to handle peak hours and off-hours.

A TV channel is an editorial based packaging of content designed for the laid-back viewer. Though the on-demand watching is becoming a big portion of TV consumption today there are still room for a service directed to a viewer that doesn’t know exactly what to watch, which is why we believe consumption of TV channels still has a place in this landscape. But instead of having a number of fixed and pre-programmed TV channels each viewer will have their own personalized TV channel. However, that doesn’t mean that we would have one encoder per viewer and instead we found a more efficient and scalable way of achieving this.

The general concept that we used is that we take a content repository with already encoded video on demand (VOD) packages and dynamically “stitch” these VOD packages together into a “live” stream. For the player and viewer it looks and feels like a “live” TV channel but it is actually created on-the-fly by concatenating the already prepared VOD packages.

System Architecture for a Server-less OTT-only Playout

Channel Engine

To understand what the Channel Engine does, let's start with a short explanation on Apple HLS and streaming format in general. The key difference between a broadcast stream and an OTT stream is when a broadcast stream pushes video to the player an OTT stream is instead pulled by the video player. Very similar to how an image or HTML document is pulled from a web server to the browser. In OTT streaming we have a set of video files transcoded in various resolution and sizes, and to be able to switch between the different resolutions during playback the video files are split into smaller chunks (3-9 seconds long). The location and order of these chunks are described by a manifest file (suffixed by .m3u8 in Apple HLS).

For VOD content all these chunks are available from the start and for Live content these chunks are continuously made available. As these new chunks are appended to the HLS manifest and older chunks removed, an HLS video player is instructed to continuously refresh and refetch this manifest from the server.

Based on this we can emulate an HLS live stream simply by picking the video chunks from the VOD content and having an engine (Channel Engine) constructing and updating the "live manifests" that the video player is fetching. In order to do this we first need to "slice" the VOD content chunks into media sequences. Each media sequence corresponds to a subset of the VOD content to simulate that new video chunks are appended.

The pseudo code for the Channel Engine can be described like this (simplified):

server.get('/live/master.m3u8', function(req, res) {
session = generateNewSession();
res.send(
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=300000,RESOLUTION=...
master300000.m3u8;session=$session
#EXT-X-STREAM-INF:BANDWIDTH=600000,RESOLUTION=...
master600000.m3u8;session=$session
...
);
});

server.get('/live/master(\d+).m3u8;session=(.*)', function(req, res) {
bandwidth = $1;
session = $2;
vod = getCurrentVod(session);
mediaSequence = getNextMediaSequence(vod, session);
res.send(mediaSequence.m3u8);
});

Content Distribution

Frontend Distribution

Content Ingest

Lambda function to trigger transcoding job

The transcoder puts the result in the S3 bucket that is used for the Content Distribution as earlier described. The content and URI is then registered in a Dynamo DB.

Asset Manager API

Demo

Me and my colleagues would like to thank you for reading and if you want to know more about this proof-of-concept you can contact me, Jonas Rydholm Birmé, on Twitter or email.

  • Twitter: @JonasBirme
  • Email: jonas.birme@eyevinn.se

Eyevinn Technology is the leading independent consultant firm specializing in video technology and media distribution, and proud organizer of the yearly nordic conference Streaming Tech Sweden.

Eyevinn Technology

Written by

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