VOD (Video on Demand) using HLS

HLS is great for live streams, but can it be used for VOD? Yeah, I know RTMP (Real-Time Messaging Protocol) already serves this purpose. It can also handle live streams, but the problem with RTMP is that viewers must have an Adobe Flash plugin running on their web browsers in order to watch your video content. That’s a problem considering Adobe Flash will eventually become obsolete.

Why use HLS or RTMP for video on demand when it’s easier to upload video files onto any web server and point the media player to the URL?

For starters, I’m big on digital rights management (DRM). There are extensions you can add to Chrome or Firefox that will allow you to download audio and video content when the owner has not made direct links to the content available. Savvier users can take advantage of built-in inspector tools to pinpoint the exact URL of your media.

RTMP and HLS obfuscates the location of your video files, making it significantly more difficult for would-be pirates to rip your content. At the end of the day, a determined pirate will get a copy of the video content you post on the Internet. With that in mind, it’s better to not post a video online if you don’t want to share it with the world.

So, how can you play an mp4 video file through HLS? The easy answer is you don’t. You have to take that mp4, convert it into TS file chunks, and compile a playlist in m3u8 format using FFmpeg. This tutorial assumes that you have access to an NGINX web streaming server and that you’re running macOS. These steps can also be adapted in Windows and Linux.

  • Launch the Terminal app in macOS, which can be found under Applications > Utilities
  • macOS doesn’t come with a command-based package manager installed under the hood. For that, you’ll need Homebrew. Copy and paste the following command in Terminal, and enjoy a cup of coffee or a glass of your favorite beer while the script runs:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
  • Install FFmpeg:
brew install ffmpeg
  • You’ll need an mp4 to work with. Let’s create a folder called “hls” on your desktop where you’ll download an mp4 to convert.
cd Desktop
mkdir hls
brew install wget
wget http://vod.leasewebcdn.com/bbb.mp4

I know, you could have simply created a folder on your desktop with the same name and downloaded this mp4 to that folder. These commands are for those who are running headless servers, and had I not given this a go I wouldn’t have learned that Wget is also not installed out of the box in macOS. Most Linux distributions, such as Ubuntu or Debian, will come with Wget. The install command will vary depending on which Linux distro you’re running.

  • Now it’s time for the fun part. Let’s take that mp4 and convert it so it’s playable with HLS. Navigate to the hls folder in Terminal and run FFmpeg:
cd hls
ffmpeg -i bbb.mp4 -profile:v baseline -level 3.0 -s 640x360 -start_number 0 -hls_time 10 -hls_list_size 0 -f hls bbb.m3u8

FFmpeg will break bbb.mp4 into small TS file chunks at around 10 seconds each with a resolution of 640×360. The conversion process is CPU intensive and the amount of time this will take depends on your machine’s processing power. Also keep in mind that the m3u8 file is not a video file. Think of it as a playlist or set of instructions for the video player to follow.

  • Check the hls folder to see if your hls files have been created. The terminal command for that is:

You should see a long list of numbered files ending with the .ts extension and a file called bbb.m3u8 – you can delete the original mp4 if you do not want to keep it.

rm bbb.mp4
  • Now it’s time to upload your HLS files to the streaming server. Again, you’ll need access to a streaming server running NGINX with the RTMP module installed for this to work.
  • Set ownership and permissions so the path is accessible:
chown -R www-data:www-data /real/path/to/video/files
chmod -R 0755 /real/path/to/video/files

http(s)://<IP address>:<Port number>/<Application>/bbb.m3u8

http(s)://This will be http or https if SSL is enabled.
<IP address>You can also use a domain name if configured.
:<Port number>There’s no need for this if using TCP port 80.
/<Application>/Not a directory. This is set in an NGINX config file like so:
rtmp {
     server {
          application vod {
               hls on;
               play /real/path/to/video/files;

Here are some examples of what the URL might look like based on the above configuration:

In this example, the actual location of bbb.m3u8 and the TS files is /real/path/to/video/files

Your m3u8 and TS files are located in /real/path/to/video/files/cartoon

Set the ownership to www-data and permissions to 0755 for sub directories recursively if you cannot playback content.

Use VLC, or any media player that’s capable of playing videos over a network to view your content. You could also right-click on the bbb.m3u8 in Finder on macOS and open it with VLC to view it locally.

1 reply

Trackbacks & Pingbacks

  1. […] of itself. Rather, HLS consists of a single m3u8 file that lists video file chunks. My tutorial on using HLS for video on demand provides a more detailed explanation on how this technology works and how it can be used for […]

Comments are closed.