Concept TV by Nader Al Masri & Vanessa Hanna

How NV-TV works

NV-TV is a concept television channel that runs on two servers in Amazon Web Services. One plays the films out, the other turns them into a stream your browser can play. Everything on this page describes the live system, not a mock-up.

About this project

NV-TV is a concept TV channel, not a real broadcaster. It was designed and built by Nader Al Masri & Vanessa Hanna as a university project on automating a secure video streaming platform in the cloud, from the servers and network to the website you are reading.

From server to screen

  1. Playout server

    A private server holds each film, already encoded at 3 quality levels with a keyframe every 2 seconds. A small playout program works out which film the schedule says should be on right now, starts it at the right second and sends all quality levels at once over RTMP, without re-encoding anything.

  2. Private link

    RTMP travels on port 1935 inside a private network. The frontend accepts a stream only from the playout server's address, and only when it carries the current secret key, which lives in HashiCorp Vault and is never written to the code repository.

  3. Packager

    nginx with the RTMP module cuts each quality level into 4-second HLS segments and DASH fragments, writes a master playlist that lists every level, and keeps about the last 60 seconds so you can rewind.

  4. Your screen

    The player in this page downloads the playlist and segments over HTTPS and feeds them to your browser's video decoder. It checks every few seconds that the stream is still being updated and reconnects on its own if the connection drops.

The schedule

The line-up is a list of films that repeats every 40 minutes, counted from a fixed starting point. The playout server and this website both read the same list and the same clock, so the guide and the on-screen banner know what is on without any extra connection between them. If the playout server restarts, it simply rejoins the schedule at the right place.

Changing what is on air means editing one file in the repository, running one command that downloads and encodes the new films, and redeploying. No page on this site changes by hand.

Picture quality

Every film is available at these levels. They share the same keyframe positions, so the player can switch between them at any segment boundary without a visible jump.

LevelPictureVideoAudio
480p854 × 4801000 kb/s96 kb/s
360p640 × 360600 kb/s96 kb/s
240p426 × 240300 kb/s64 kb/s

With Auto, the player measures how fast segments arrive and picks the highest level your connection can keep up with, stepping down before the picture stalls. Choosing a level fixes it. Auto switching works with HLS; DASH plays one level at a time because the packager writes a separate manifest per level.

Sound is normalised to the European broadcast loudness standard (EBU R128), so one film is not suddenly louder than the next.

Headlines and clock

The channel logo, the clock and the news band are drawn into the picture itself by the playout server before it encodes each quality level, exactly as a broadcaster does. They appear in every player, including VLC and full screen on a phone, and cost the playout server one live encode per quality level instead of a simple copy.

The band along the bottom of the picture carries news about Lebanon and the region. Every 10 minutes, the web server itself fetches the latest headlines from Google News, BBC News, France 24, keeps those from the last 36 hours and publishes them as a small file on this site. Your browser never contacts the news sites, so the page still loads nothing from third parties.

Headlines are treated as untrusted text: the feeds are parsed with a hardened XML parser that refuses entity tricks, any markup is stripped, only web links are kept, and the page inserts them as plain text. The fetcher runs as its own unprivileged user that can write to one folder and nothing else.

Each headline belongs to its publisher and links to the original story in the Headlines list on the watch page, which is also the way to read them at your own pace. The clock in the band alternates between Paris and Beirut time.

Reading the signal

The Signal panel on the watch page shows what the player measures in real time.

Source
How long ago the playlist on the server last changed. A new segment every 4 seconds means the playout server is on air. If it stops changing, the panel says the picture is frozen at the source.
Behind live
How far your picture is behind the newest segment. A live stream always runs a little behind real time, because a segment can only be sent once it is complete, and the player keeps a few in hand.
Buffered ahead
How many seconds of video are already downloaded and waiting. A healthy buffer is what lets playback ride out a short network hiccup.
Picture and frame rate
The resolution the decoder is producing right now and how many frames per second it is showing. With Auto quality, the resolution follows your connection.
Video bitrate
How much data the current quality level uses per second, averaged over the last few segments.
Your connection
How fast segments actually download to you. When it is comfortably above the video bitrate, Auto can step up a level.
Dropped frames
Frames the browser decoded but could not show in time, usually because the device was busy. A handful is normal; a steadily rising number means the device is struggling.
Segments received
How many 4-second pieces of video the player has downloaded since you tuned in. The ticks on the rewind bar under the picture mark the same segments.
Delay behind live setting
Short, Balanced or Long changes how many segments the player keeps in hand. Short is closer to live but stalls sooner on a weak network.

Security and privacy

The site is served only over HTTPS with TLS 1.2 or 1.3 and a certificate from Let's Encrypt that renews itself. Browsers are told to use HTTPS for a year (HSTS).

The pages load nothing from other sites: no fonts, analytics, advertising or trackers, and no cookies. A Content Security Policy only lets the browser run the scripts this server sends, and the two player libraries are pinned to exact versions and checked against known fingerprints twice, once when the server downloads them and again in your browser.

Only the watch page, the playlists and the segments are reachable from the internet. The playout server has no public entry point at all, and administration happens through an AWS-managed tunnel tied to a signed-in identity rather than an open SSH port.

How it is built

The network, servers and firewall rules are described in Terraform and created from code. Ansible configures both servers: system hardening, the firewall, the packager, the playout program, this website and the certificate. Secrets such as the stream key come from HashiCorp Vault at deploy time.

Both servers send their metrics and logs to Grafana Cloud, where alerts watch for a frozen picture, an unreachable stream, an expiring certificate and a server going down. Every change goes through a pull request that runs linters, a secret scanner and infrastructure security checks, and the live site is scanned with OWASP ZAP.

Other players

The stream is standard HLS and DASH, so it plays in VLC, ffplay or any compatible player. In VLC, choose Media, then Open Network Stream, and paste https://tv.nadermasri.com/hls/stream.m3u8. The Signal panel on the watch page has copy buttons for both links.

Credits and licences

Every film on NV-TV is an open movie released under a Creative Commons licence that allows redistribution with attribution.

FilmYearByLicence
Big Buck Bunny 2008 Blender Foundation CC BY 3.0
Caminandes: Gran Dillama 2013 Blender Foundation CC BY 3.0
Sintel 2010 Blender Foundation CC BY 3.0
Tears of Steel 2012 Blender Foundation CC BY 3.0

Headlines

Headlines and links on the ticker come from Google News, BBC News, France 24 and remain the property of their publishers.

Software

Playback uses hls.js (Apache License 2.0) and dash.js (BSD 3-Clause), served from this site. Encoding and playout use FFmpeg; packaging uses nginx with the RTMP module.