HLS Manifest DSL
HTTP Live Streaming is a communication protocol for adaptive bitrate streaming.
What this means is that with HLS we can enable HTML5 video clients to stream video online. One of the main benefits of the HLS protocol is that it allows clients to change the video quality on the fly based on several factors. This ability to change the video quality improves the overall user experience as it helps reduce buffering times, provides the best possible video resolution based on your screen size and more.
There are two essential parts to HLS
- Master Playlist
- Media Playlist
The master playlist defines a list of available media playlists. More on this in the Master Playlist Section. The media playlist defines where the different video segments are located. More on this in the Media Playlist Section.
The HLS DSL is a library that enables you to correctly define a very small yet correct and playable HLS manifest that can be used for video streaming.
With this DSL, you can define a Master and Media playlist.
A master playlist defines multiple media playlists for different video renditions.
You can download the DSL from GitHub or install it using gradle or maven:
implementation("io.onema:playlist-dsl:0.1.0")
<dependency>
<groupId>io.onema</groupId>
<artifactId>playlist-dsl</artifactId>
<version>0.1.0</version>
</dependency>
import io.onema.manifestservice.playlist.master
val master = master playlist {
version set 5
add stream {
streamInf resolution "resolution1" codecs "codec" bandwidth 12345 frameRate 123F
info name "videoName" rendition "rendition"
}
}
val expectation = """#EXTM3U
|#EXT-X-VERSION:5
|#EXT-X-STREAM-INF:RESOLUTION=resolution1,CODECS="codec",BANDWIDTH=12345,FRAME-RATE=123.000
|media/rendition""".trimMargin()
assertEquals(expectation, master)
import io.onema.manifestservice.playlist.PlaylistTypeEnum.VOD
import io.onema.manifestservice.playlist.media
val media = media playlist {
version set 5
type set VOD
mediaSequence set 0
targetDuration set 6
method value "NONE"
add segment {
extInf duration 2.0F
byteRange length 123 position 321
info name "videoName" rendition "rendition"
}
}
val expectation = """#EXTM3U
|#EXT-X-VERSION:5
|#EXT-X-PLAYLIST-TYPE:VOD
|#EXT-X-MEDIA-SEQUENCE:0
|#EXT-X-TARGETDURATION:6
|#EXT-X-KEY:METHOD=NONE
|#EXTINF:2.0
|#EXT-X-BYTERANGE:123@321
|segment/rendition
|#EXT-X-ENDLIST""".trimMargin()
assertEquals(expectation, media, "Media playlist didn't match expected value")
.
When using HLS, a basic workflow of how the client interacts with the different playlist looks like this:
sequenceDiagram autonumber Client ->> Master Playlist: GET Master Playlist -->> Client: master.m3u8 alt media playlist 480x270 Client ->> Media Playlist: GET 480x270 Media Playlist -->> Client: 480 x 270.m3u8 else media playlist 640x360 Client ->> Media Playlist: GET 640x360 Media Playlist -->> Client: 640 x 360.m3u8 end par segment 1 Client ->> Media Origin: GET Byte 0 - 491431 Media Origin -->> Client: Bytes 🎥 and segment 2 Client ->> Media Origin: GET Byte 491432 - 1013319 Media Origin -->> Client: Bytes 🎥 and segment N Client ->> Media Origin: GET Bytes ... end
The master playlist (master.m3u8
) defines the available media playlists. Each media playlist entry describes the main characteristics of the video renditions they represent.
These include the codec, video resolution, frame rate, the location of the playlist, and more.
Based on this information, the video player will select the best possible video rendition for you.
My video player selected, to begin with, the 640x360
media playlist. In this playlist, a series of video segments and byte ranges.
The video player will start downloading each of these segments and initiate the video playback.
The origin is where the media files are located. There are many ways to store the files, one file for each rendition or one file for each segment for each rendition. In this example, there is one file for each rendition, and the media playlist knows what byte range to request from that file.
Adaptive bitrate streaming allows your player to download different video renditions based on your screen size, network conditions, device type, and more.
Have you ever seen a video that starts pixelated and improves over time? This is adaptive bitrate streaming at work!
In this particular example, after a little while, the video player downloaded a different media playlist (1280x720
) and eventually started downloading and playing the segments with better quality.
I’ve created an end-to-end example of a serverless streaming platform (transcoding and video streaming) where I use this library to generate the master and media playlists dynamically.
To run the demo, use Safari, as it will support HLS natively.
The HLS DSL, is a Kotlin DSL that enables users to generate HLS playlists. With these playlists, you will be able to create a basic HLS streaming service.
I’ll be creating a follow-up article defining how to develop a simple transcoding pipeline and streaming service. If you want to learn more about HLS or adaptive bitrate streaming, take a look at this series of articles on Internet Video Streaming by Eyevinn Technology: