m3u8 is a ruby gem facilitates the generation of m3u8 playlists for HTTP Live Streaming (HLS). You can use this to serve up playlists from a rails application for the integration of authentication and other customizations, while serving the actual MPEG transport stream files (.ts) from a CDN. You can also use m3u8 to generate playlist files as part of an encoding / production pipeline.

Creating a master playlist for adaptive bitrate streaming is very straightforward. Master playlists can also be used create a playlist of different programs by specifying different program-id’s. Adaptive playlists entries will all have the same program-id, as shown below.

require 'm3u8'

playlist = M3u8::Playlist.new
options = { width: 1920, height: 1080, profile: 'high', level: 4.1, audio: 'aac-lc'}
playlist.add_playlist('1', 'http://playlist_url_or_path_file', 50000, options)

options = { width: 1280, height: 720, profile: 'main', level: 4.0, audio: 'aac-lc'}
playlist.add_playlist('1', 'http://playlist_url_or_path_file', 30000, options)

options = { width: 640, height: 360, profile: 'baseline', level: 3.1, audio: 'aac-lc'}
playlist.add_playlist('1', 'http://playlist_url_or_path_file', 10000, options)

playlist.add_playlist('1', 'http://playlist_url_or_path_file', 6400, { :audio: 'aac-lc' })

M3u8 can also generate standard playlists by adding TS segments, these are typically what your master playlist would point to but they can be standalone as well for non-adaptive bitrate streaming. TS segments are typically 10 second long encoded video/audio in a MPEG-TS container. If you try to mix playlist types (master and segments) in the same object instance you will get an exception thrown.

playlist = M3u8::Playlist.new
playlist.add_segment(11.344644, '1080-7mbps00000.ts')

You can also use the library to just generate the codecs string used by HLS.

options = { profile: 'baseline', level: 3.0, audio: 'aac-lc' }
codecs = M3u8::Playlist.codecs(options)
#=> "avc1.66.30,mp4a.40.2"

You can specify options for the playlist during instantiation, these are ignored if playlist becomes a master playlist (child playlist added) since they are no longer relevant:

options = { version: 1, cache: false, target: 12, sequence: 1}
playlist = M3u8::Playlist.new(options)

Finally to actually generate the playlist content you can pass an IO object to the write method or just access to the to_s method.

require 'tempfile'

file = Tempfile.new('test')
playlist.write(file)
# or just via assigment to string
content = playlist.to_s