Building an open-source OTT platform

Attention: I released resty-dynacode an openresty library enabling users to add Lua code dynamically to Nginx.

Create software from “scratch” might not be a good idea at first but it’s often a great way to study a specific technology or even to deepen your knowledge in a particular field of computer science.

In this three-post series, we’re going to build a simple video platform using open-source software, will add features to it so it handles the computional power on the front end (edge computing) and we’ll conclude designing a platform that will enable us to add code/features dynamically to the servers.

Screen Shot 2020-04-21 at 9.07.02 AM

An over-the-top (OTT) is a streaming media service offered directly to viewers via the Internet. OTT bypasses cable, broadcast, and satellite television platforms. Now you don’t need to spend your money that much.

Edge computing is the ability to put computation and storage closer to the place where it is demanded, in simpler terms is the code running within your front end servers.

We’re going to design two distinct services: a simple video streaming solution and an edge computing platform for this video streaming service.

  1. Building NOTT – an open source OTT video platform
  2. Add edge computation to NOTT – empower nginx with lua code
    • token authentication code
    • IP acl
    • forbid other sites
    • add a custom HLS tag on the fly
    • expose metrics in HTTP headers
    • count user request per IP
  3. Platformize the edge computing – using lua + redis
  4. $profit$

The NOTT

The new OTT is a VERY SIMPLE open-source video platform that expects an input signal and produces an output stream. It was made mostly as an excuse to discuss and design an edge computing platform around it.

NOTT
NOTT is built using a simple html5 app
Screen Shot 2020-04-12 at 8.11.15 AM
NOTT architecture

The UI app is a simple static html5 file served from nginx. We’re using Clappr (backed by hls.js and shaka) as the selected player. The front end works as a caching layer for the video streaming and it also hosts the NOTT app.

The live streaming reaches the platform through FFmpeg, the broacasting, which is also used to transcode the input producing multiple renditions. The nginx-rtmp acts as a packager, converting the RTMP input into the adaptive output streaming format known as HLS.

The main selling point of our OTT platform is that it has the popular TV channel color bar (60fps) and the legendary TV show big buck bunny (partner’s licensed content). :slightly_smiling_face:

Compatibility: I didn’t test on all platforms (browsers, ios, android, CTVs), video is hard and NOTT won’t cover 100% of the devices but it should work in most places.

How does it work?

To broadcast the color bar TV show into the platform, we’ll use FFmpeg. It has some filters that are capable to create synthetic color bar frames at a given rate. It also offers an audio source filter known as sine can be used to create artificial sound.

This command creates color bar pictures at 60 frames per second and a sine wave sound at 48000 hertz. It encodes them to the video codec h264 using the libx264 and to the audio codec aac. Finally, we send them to the transcoder/packager using RTMP.

ffmpeg -f lavfi -i 'testsrc2=size=1280×720:rate=60,format=yuv420p' \
-f lavfi -i 'sine=frequency=440:sample_rate=48000:beep_factor=4' \
-c:v libx264 -preset ultrafast -tune zerolatency -profile:v high \
-b:v 1400k -bufsize 2800k -x264opts keyint=120:min-keyint=120:scenecut=-1 \
-c:a aac -b:a 32k -f flv rtmp://transcoder/encoder/colorbar

The ingest server runs nginx-rtmp and it acts as input service, receiving the FFmpeg synthetic stream. It also transcodes (spawning FFmpeg processes for that) and creates the HLS format in a given folder.

The front end servers will consume the streaming via HTTP backed by this ingest server.

rtmp {
server {
listen 1935;
application encoder {
live on;
exec ffmpeg -i rtmp://localhost:1935/encoder/$name
-c:v libx264 -b:v 750k -f flv -s 640×360 rtmp://localhost:1935/hls/$name_high
-c:v libx264 -b:v 400k -f flv -s 426×240 rtmp://localhost:1935/hls/$name_mid
-c:v libx264 -b:v 200k -f flv -s 426×240 rtmp://localhost:1935/hls/$name_low;
}
application hls {
live on;
hls on;
hls_variant _high BANDWIDTH=878000,RESOLUTION=640×360;
hls_variant _mid BANDWIDTH=528000,RESOLUTION=426×240;
hls_variant _low BANDWIDTH=264000,RESOLUTION=426×240;
}
}
}
view raw nginx.conf hosted with ❤ by GitHub

The front end server we chose was nginx, a scalable web server and reverse proxy. This will be the endpoint where the final users can access the html5 application to watch the stream. It will also work as a caching layer for scalability.

http {
upstream backend {
server ingest;
}
server {
listen 8080;
location / {
proxy_cache my_cache;
proxy_cache_lock on;
proxy_pass http://backend;
}
location /app {
alias /usr/local/openresty/nginx/;
}
}
}
view raw nginx.conf hosted with ❤ by GitHub

Finally, the app is a simple HTML static file that instantiates the player.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>NOTT – The New OTT</title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/clappr@latest/dist/clappr.min.js"></script>
</head>
<body class="notstealenfromnetflix">
<ul class="flex-container">
<li class="flex-item">
<div id="player"></div>
</li>
</ul>
<script>
var player = new Clappr.Player(
{
source: "http://localhost:8080/hls/colorbar.m3u8&quot;,
parentId: "#player",
poster: 'https://www.bogotobogo.com/FFMpeg/images/test_patterns/testsrc010.png&#39;,
mute: true,
height: 360,
width: 640,
});
</script>
</body>
</html>
view raw app.html hosted with ❤ by GitHub

How to use it

The entire platform was conceived with Linux containers in mind so you just need to run make run and this is going to start it all. You also need to start the color bar in a different tab by running make broadcast_tvshow and point your browser to http://localhost:8080/app.

# make sure you have docker
git clone https://github.com/leandromoreira/nott.git
cd nott
git checkout 0.0.3
# in a tab
make run
# wait until the platform is up and running
# and in another tab run
make broadcast_tvshow
# ^ for linux users you use –network=host and your
# IP instead of this docker.for.mac.host.internal
# for windows user I dunno =(
# but you can use OBS and point to your own machine
# open your browser and point it to http://localhost:8080/app
view raw steps.sh hosted with ❤ by GitHub

Conclusion

The genuine reason we created this simplistic video platform is to have a software where we can explore the computation at the edge. The next post will be empowering the Nginx front end with Lua code to add features to NOTT, things like authentication and IP acl.

2 thoughts on “Building an open-source OTT platform

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s