Converting Video Files for HLS Streaming

Converting Video Files for HLS Streaming

This reference shows how to convert video files for HLS streaming with ffmpeg and how to create video files from .m3u8 manifest and .ts files.

On-demand content is at the core of any modern multimedia application or service. HTTP Live Streaming (also known as HLS) is a popular format for HTTP-based adaptive bitrate streaming. It breaks the media stream into small media segments through the use of M3U playlist files that direct the client to the media segment files. To know more, consider our article on Using HTTP Live Streaming (HLS) for live and on‐demand audio and video that covers the basics.

When working with HLS, you have to convert video files into media segments and manifest playlists. For this, you can utilize Apple's HTTP Live Streaming Tools package, which contains seven prerelease command-line tools for the deployment and validation of HTTP Live Streaming solutions. Most relevantly, the Media Stream Segmenter and Media File Segmenter are used to create the playlist and media segment files.

However, these tools are a prerelease and actually not as feature-rich as one might expect. Luckily, there is a long-standing alternative available to supercharge all your video conversion needs. Let's have a look.

Creating files for HLS streaming with ffmpeg

To create the needed files for HLS streaming, you can use the open-source ffmpeg media framework. It provides options to encode, decode, transcode, mux, demux and stream almost all media formats and is available on Linux, Windows and Mac OS among others.

On the Mac it requires the Homebrew packet manager to be installed. This can be done via the command line using Terminal:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Once Homebrew is available, ffmpeg can be installed using following command:

brew install ffmpeg

Once installation is completed, ffmpeg can be used to create all needed files for HLS streaming. The following command will create a .m3u8 playlist with .ts media segment files without re-encoding the media as a copy with a hls_time of 10 seconds for the length of each video segment.

ffmpeg -i filename.mp4 -codec: copy -start_number 0 -hls_time 10 -hls_list_size 0 -f hls filename.m3u8

Of course, you can also create multiple versions of the playlist and media segment files, for example to accommodate multiple resolutions and bandwidths to offer different video-on-demand streams for different network speeds. Following command creates 4 different playlists at scale 640x360, 842x480, 1280x720 and 1920x1080 in .h264 for a vod playlist with defined bitrates and buffer sizes.

ffmpeg -y -i filename.mp4 \
  -vf scale=w=640:h=360:force_original_aspect_ratio=decrease -c:a aac -ar 48000 -c:v h264 -profile:v main -crf 20 -sc_threshold 0 -g 48 -keyint_min 48 -hls_time 4 -hls_playlist_type vod  -b:v 800k -maxrate 856k -bufsize 1200k -b:a 96k -hls_segment_filename 360p_%03d.ts 360p.m3u8 \
  -vf scale=w=842:h=480:force_original_aspect_ratio=decrease -c:a aac -ar 48000 -c:v h264 -profile:v main -crf 20 -sc_threshold 0 -g 48 -keyint_min 48 -hls_time 4 -hls_playlist_type vod -b:v 1400k -maxrate 1498k -bufsize 2100k -b:a 128k -hls_segment_filename 480p_%03d.ts 480p.m3u8 \
  -vf scale=w=1280:h=720:force_original_aspect_ratio=decrease -c:a aac -ar 48000 -c:v h264 -profile:v main -crf 20 -sc_threshold 0 -g 48 -keyint_min 48 -hls_time 4 -hls_playlist_type vod -b:v 2800k -maxrate 2996k -bufsize 4200k -b:a 128k -hls_segment_filename 720p_%03d.ts 720p.m3u8 \
  -vf scale=w=1920:h=1080:force_original_aspect_ratio=decrease -c:a aac -ar 48000 -c:v h264 -profile:v main -crf 20 -sc_threshold 0 -g 48 -keyint_min 48 -hls_time 4 -hls_playlist_type vod -b:v 5000k -maxrate 5350k -bufsize 7500k -b:a 192k -hls_segment_filename 1080p_%03d.ts 1080p.m3u8

If you want to know more about options for generating HLS streaming files, there are more in-depth explanations of how to convert media files for a multi-bitrate HLS VOD stream. If you are curious about how to implement support for different HLS streams in your iOS app, take a look at our article about switching between HLS streams with AVKit.

Converting HLS streaming files to a single video file

Of course, you can also reconvert the created HLS files back to video files. It works similar to the initial conversion. This command will create a .mp4 file using the .m3u8 manifest file and merge all the media segment files into one single file.

ffmpeg -i video.m3u8 -c copy video.mp4

You can even do this from an online source of the .m3u8 manifest files, creating a single video file directly from the video-on-demand stream.

ffmpeg -protocol_whitelist file,http,https,tcp,tls,crypto -i "https://url.domain/video.m3u8" -c copy video.mp4

If multiple bitrate streams are available, for example, by accessing a primary playlist that redirects to different streams, the command will download the default stream. If a dedicated resolution is targeted, the command should direct the URL to the specific manifest files for the desired bitrate.


Getting started with HLS Streaming in your Apps

If you are curious and want to incorporate HTTP Live Streaming (HLS) inside your next app project, there are some more articles on Create with Swift to get you started: