Category Archives: ffmpeg

How to Encrypt Video for HLS

In this post, we’ll look at what encryption HLS supports and how to encrypt your videos with ffmpeg.

Encryption is the process of encoding information in such a way that only authorised parties can read it. The encryption process requires some kind of secret (key) together with an encryption algorithm.

There are many different types of encryption algorithms but HLS only supports AES-128. The Advanced Encryption Standard (AES) is an example of a block cipher, which encrypts (and decrypts) data in fixed-size blocks. It’s a symmetric key algorithm, which means that the key that is used to encrypt data is also used to decrypt it. AES-128 uses a key length of 128 bits (16 bytes).

HLS uses AES in cipher block chaining (CBC) mode. This means each block is encrypted using the cipher text of the preceding block, but this gives us a problem: how do we encrypt the first block? There is no block before it! To get around this problem we use what is known as an initialisation vector (IV). In this instance, it’s a 16-byte random value that is used to intialize the encryption process. It doesn’t need to be kept secret for the encryption to be secure.

Before we can encrypt our videos, we need an encryption key. I’m going to use OpenSSL to create the key, which we can do like so:

$ openssl rand 16 > enc.key

This instructs OpenSSL to generate a random 16-byte value, which corresponds to the key length (128 bits).

The next step is to generate an IV. This step is optional. (If no value is provided, the segment sequence number will be used instead.)

$ openssl rand -hex 16

Make a note of the output as you’ll need it shortly.

To encrypt the video we need to tell ffmpeg what encryption key to use, the URI of the key, and so on. We do this with -hls_key_info_file option passing it the location of a key info file. The file must be in the following format:

Path to key file
IV (optional)

The first line specifies the URI of the key, which will be written to the playlist. The second line is the path to the file containing the encryption key, and the (optional) third line contains the initialisation vector. Here’s an example (enc.keyinfo):

Now that we have everything we need, run the following command to encrypt the video segments:

ffmpeg -y \
    -i \
    -hls_time 9 \
    -hls_key_info_file enc.keyinfo
    -hls_playlist_type vod \
    -hls_segment_filename "fileSequence%d.ts" \

Take a look at the generated playlist (prog_index.m3u8). It should look something like this:


Note the URI of the encryption key. The player will retrieve the key from this location to decrypt the media segments. To protect the key from eavesdroppers it should be served over HTTPS. You may also want to implement some of authentication mechanism to restrict who has access to the key. If you’re interested, the book goes into some detail about how to achieve this. Click here to buy a copy.

To verify that the segments really are encrypted, try playing them using a media player like QuickTime or VLC. You shouldn’t be able to. Now run the command above without the encryption and then try playing a segment. Notice the difference.

Even though HLS supports encryption, which provides some sort of content protection, it isn’t a full DRM solution. If that kind of thing interests you then you may want to take a look at Apple’s FairPlay Streaming solution.

Segmenting Video with ffmpeg – Part 2

In a previous post I showed how to segment video for HLS using ffmpeg’s segment muxer. In this one, I’ll demonstrate how to use ffmpeg’s hls muxer. It has more features specific to HLS like support for encryption, subtitles, specifying the type of playlist, and so on.

To follow along, you’ll need a recent version of ffmpeg with support for HLS. (I used version 3.1.1 on Ubuntu 14.04.) To see if your version supports HLS, run the command below. You should see something like this:

$ ffmpeg -formats | grep hls
 E hls              Apple HTTP Live Streaming
D  hls,applehttp    Apple HTTP Live Streaming

If ffmpeg complains about an unrecognized option when executing the commands in this post, you can see what options are supported by running the following from a terminal:

$ ffmpeg -h muxer=hls

If an option is not supported, you’ll need to upgrade your version of ffmpeg.
Continue reading

Segmenting Video with ffmpeg

To stream video with HLS, you need to divide your video into segments of a fixed duration and add them to a playlist. In the book I use Apple’s HTTP Live Streaming tools to do this. Here’s an example using mediafilesegmenter:

$ mediafilesegmenter -f /Library/WebServer/Documents/vod

This command takes the video ( and writes out the segments and the playlist to the /Library/WebServer/Documents/vod directory. Unfortunately, Apple’s tools will only work on a Mac.

However, recent versions of ffmpeg can also output HLS compatible files. Given a video as input, it will divide it into segments and create a playlist for us.

Here’s the equivalent of the command above using ffmpeg:

$ ffmpeg -y \
 -i \
 -codec copy \
 -bsf h264_mp4toannexb \
 -map 0 \
 -f segment \
 -segment_time 10 \
 -segment_format mpegts \
 -segment_list "/Library/WebServer/Documents/vod/prog_index.m3u8" \
 -segment_list_type m3u8 \

We use ffmpeg‘s segment muxer to segment the video. We can specify the segment duration with the -segment_time option. The last argument passed to ffmpeg is the path to where the segments should be written; it contains a format specifier (%d) similar to those supported by the printf function in C. The %d will be replaced with the current sequence number. In this example, the segments will be named fileSequence0.ts, fileSequence1.ts, and so on.

And that’s how you process a video for streaming with HLS using ffmpeg. There are other examples in the book, including how to use ffmpeg to segment a live video stream, so if you want to learn how, buy your copy today.

In part 2 we’ll look at how to segment video using ffmpeg’s hls muxer.