class M3U8::Playlist
- M3U8::Playlist
- Reference
- Object
Overview
Playlist represents an m3u8 playlist, which can be either a Master Playlist or a Media Playlist.
In an HLS playlist, as defined in RFC 8216,
the file begins with the EXTM3U tag and may
contain a variety of global and segment-specific tags. A Master Playlist includes entries
for different Variant Streams (using EXT-X-STREAM-INF or EXT-X-I-FRAME-STREAM-INF tags),
while a Media Playlist lists the media segments (with EXTINF, EXT-X-BYTERANGE, etc.).
Basic Tags:
EXTM3U:PlaylistEXT-X-VERSION:Playlist#version
Media Playlist Tags:
EXT-X-TARGETDURATION:Playlist#targetEXT-X-MEDIA-SEQUENCE:Playlist#sequenceEXT-X-DISCONTINUITY-SEQUENCE:Playlist#discontinuity_sequenceEXT-X-ENDLIST:Playlist.footerEXT-X-PLAYLIST-TYPE:Playlist#typeEXT-X-I-FRAMES-ONLY:Playlist#iframes_onlyEXT-X-ALLOW-CACHE:Playlist#cache(deprecated in protocol version 7)
Media Segment Tags:
EXTINF:SegmentItemEXT-X-BYTERANGE:ByteRangeEXT-X-DISCONTINUITY:DiscontinuityItemEXT-X-KEY:KeyItemEXT-X-MAP:MapItemEXT-X-PROGRAM-DATE-TIME:TimeItemEXT-X-DATERANGE:DateRangeItem
Master Playlist tags:
EXT-X-MEDIA:MediaItemEXT-X-STREAM-INF:PlaylistItemwithPlaylist#iframeset tofalseEXT-X-I-FRAME-STREAM-INF:PlaylistItemwithPlaylist#iframeset totrueEXT-X-SESSION-DATA:SessionDataItemEXT-X-SESSION-KEY:SessionKeyItem
Media or Master Playlist Tags:
EXT-X-INDEPENDENT-SEGMENTS:Playlist#independent_segmentsEXT-X-START:PlaybackStart
This class maintains various playlist-wide properties:
- master: Indicates whether the playlist is a Master Playlist.
- version: The protocol compatibility version (EXT-X-VERSION).
- cache: Whether caching is allowed (
EXT-X-ALLOW-CACHEtag was removed in protocol version 7). - discontinuity_sequence: The discontinuity sequence number (EXT-X-DISCONTINUITY-SEQUENCE).
- type: The playlist type (e.g., VOD or EVENT, from EXT-X-PLAYLIST-TYPE).
- target: The target duration for media segments (EXT-X-TARGETDURATION).
- sequence: The Media Sequence Number (EXT-X-MEDIA-SEQUENCE).
- iframes_only: Indicates if the playlist is an I-frame only playlist (EXT-X-I-FRAMES-ONLY).
- independent_segments: Flag indicating if segments can be independently decoded (
EXT-X-INDEPENDENT-SEGMENTS). - live: A boolean flag indicating whether the playlist is live (no endlist tag).
- items: An array of playlist items (which can be SegmentItem, PlaylistItem, etc.).
The class provides methods to create a new Playlist, to parse a playlist
from a string input, and to generate the complete playlist as a string by combining #header, #body,
and #footer components.
Examples:
Creating a new Playlist with specific parameters:
options = {
version: 7,
cache: false,
target: 12,
sequence: 1,
discontinuity_sequence: 2,
type: "VOD",
independent_segments: true,
}
playlist = Playlist.new(options)
playlist.items << SegmentItem.new(duration: 10.991, segment: "test_01.ts")
playlist.items << SegmentItem.new(duration: 9.891, segment: "test_02.ts")
playlist.items << SegmentItem.new(duration: 10.556, segment: "test_03.ts")
playlist.items << SegmentItem.new(duration: 8.790, segment: "test_04.ts")
playlist.duration # => 40.227999999999994
playlist.to_s
# => "#EXTM3U\n" +
# "#EXT-X-PLAYLIST-TYPE:VOD\n" +
# "#EXT-X-VERSION:7\n" +
# "#EXT-X-INDEPENDENT-SEGMENTS\n" +
# "#EXT-X-MEDIA-SEQUENCE:1\n" +
# "#EXT-X-DISCONTINUITY-SEQUENCE:2\n" +
# "#EXT-X-ALLOW-CACHE:NO\n" +
# "#EXT-X-TARGETDURATION:12\n" +
# "#EXTINF:10.991,\n" +
# "test_01.ts\n" +
# "#EXTINF:9.891,\n" +
# "test_02.ts\n" +
# "#EXTINF:10.556,\n" +
# "test_03.ts\n" +
# "#EXTINF:8.79,\n" +
# "test_04.ts\n" +
# "#EXT-X-ENDLIST\n"
Parsing a complete playlist string:
m3u8_string = "#EXTM3U\n#EXT-X-VERSION:7\n#EXT-X-TARGETDURATION:12\n..."
Playlist.parse(m3u8_string)
# => #<M3U8::Playlist ...>
Included Modules
- M3U8::Concern
Extended Modules
- M3U8::Concern
Defined in:
m3u8/playlist.crConstructors
-
.new(params : NamedTuple = NamedTuple.new)
-
.new(master : Bool | Nil = nil, version : Int32 | Nil = nil, cache : Bool | Nil = nil, discontinuity_sequence : Int32 | Nil = nil, type : Nil | String = nil, target = nil, sequence = nil, iframes_only = nil, independent_segments = nil, live = nil, items = nil)
Initializes a new Playlist instance.
Class Method Summary
-
.codecs(options = NamedTuple.new)
Generates the CODECS attribute string for the playlist.
-
.parse(input)
Parses a playlist string into a
Playlistinstance.
Instance Method Summary
-
#body
Returns the body section of the playlist as a string.
- #cache : Bool | Nil
- #cache=(cache : Bool | Nil)
- #discontinuity_sequence : Int32 | Nil
- #discontinuity_sequence=(discontinuity_sequence : Int32 | Nil)
-
#duration
Calculates the total duration of the playlist by summing the durations of all
SegmentItems. -
#footer
Returns the footer section of the playlist as a string.
-
#header
Returns the header section of the playlist as a string.
-
#iframes_only : Bool
Specifies whether the playlist is an I-frame only playlist.
-
#iframes_only=(iframes_only : Bool)
Specifies whether the playlist is an I-frame only playlist.
-
#independent_segments : Bool
When set to true, the playlist header will include the
EXT-X-INDEPENDENT-SEGMENTStag. -
#independent_segments=(independent_segments : Bool)
When set to true, the playlist header will include the
EXT-X-INDEPENDENT-SEGMENTStag. - #items : Array(Items)
- #items=(items : Array(Items))
- #live : Bool
- #live=(live : Bool)
-
#live?
Returns
trueif the playlist is considered live. - #master : Bool | Nil
- #master=(master : Bool | Nil)
-
#master?
Returns
trueif the playlist is a Master Playlist. - #sequence : Int32
- #sequence=(sequence : Int32)
- #target : Float64
- #target=(target : Float64)
-
#to_s
Returns the complete playlist as a string.
- #type : String | Nil
- #type=(type : String | Nil)
-
#valid!
Validates the playlist and raises an
Error::PlaylistTypeerror if it is invalid. -
#valid?
Validates the playlist.
- #version : Int32 | Nil
- #version=(version : Int32 | Nil)
Constructor Detail
Constructs a new Playlist instance from a NamedTuple of parameters.
The NamedTuple may include keys for properties such as:
:master, :version, :cache, :discontinuity_sequence, :type,
:target, :sequence, :iframes_only, :independent_segments, :live, and :items.
Example:
options = { version: 7, cache: false, target: 12, sequence: 1, discontinuity_sequence: 2, type: "VOD", independent_segments: true, } Playlist.new(options)
=> #<M3U8::Playlist:0x79adbb379540
@cache=false,
@discontinuity_sequence=2,
@iframes_only=false,
@independent_segments=true,
@items=[],
@live=false,
@master=nil,
@sequence=1,
@target=12.0,
@type="VOD",
@version=7>
Initializes a new Playlist instance.
Example:
Playlist.new(
version: 7,
cache: false,
target: 12,
sequence: 1,
discontinuity_sequence: 2,
type: "VOD",
independent_segments: true,
)
# => #<M3U8::Playlist:0x78d37cb334d0
# @cache=false,
# @discontinuity_sequence=2,
# @iframes_only=false,
# @independent_segments=true,
# @items=[],
# @live=false,
# @master=nil,
# @sequence=1,
# @target=12.0,
# @type="VOD",
# @version=7>
Class Method Detail
Generates the CODECS attribute string for the playlist.
This method instantiates a Codecs object with the given options and returns its
string representation. The CODECS attribute lists the codecs used in the media, such as
"avc1.66.30,mp4a.40.2". For details on how the codecs are determined, refer to the Codecs class.
Example:
options = {
profile: "baseline",
level: 3.0,
audio_codec: "aac-lc",
}
Playlist.codecs(options) # => "avc1.66.30,mp4a.40.2"
Parses a playlist string into a Playlist instance.
Example:
m3u8_string = "#EXTM3U\n#EXT-X-VERSION:7\n#EXT-X-TARGETDURATION:12\n..."
Playlist.parse(m3u8_string)
# => #<M3U8::Playlist ...>
Instance Method Detail
Returns the body section of the playlist as a string.
The body consists of all the items (segments or playlist entries) that have been added.
Examples:
playlist = Playlist.new(version: 6, independent_segments: true)
playlist.items << SegmentItem.new(duration: 10.991, segment: "test.ts")
playlist.body
# => "#EXTINF:10.991,\n"
# "test.ts"
Calculates the total duration of the playlist by summing the durations of all SegmentItems.
Examples:
playlist = Playlist.new
playlist.items << SegmentItem.new(duration: 10.991, segment: "test_01.ts")
playlist.items << SegmentItem.new(duration: 9.891, segment: "test_02.ts")
playlist.items << SegmentItem.new(duration: 10.556, segment: "test_03.ts")
playlist.items << SegmentItem.new(duration: 8.790, segment: "test_04.ts")
playlist.duration # => 40.227999999999994
playlist.duration.round(3) # => 40.228
Returns the header section of the playlist as a string.
The header tags based on whether the playlist is a Master or Media Playlist.
Examples:
playlist = Playlist.new(master: true, version: 6, independent_segments: true)
playlist.header
# => "#EXTM3U\n" \
# "#EXT-X-VERSION:6\n" \
# "#EXT-X-INDEPENDENT-SEGMENTS"
playlist = Playlist.new(version: 6, independent_segments: true)
playlist.header
# => "#EXTM3U\n" \
# "#EXT-X-VERSION:6\n" \
# "#EXT-X-INDEPENDENT-SEGMENTS\n" \
# "#EXT-X-MEDIA-SEQUENCE:0\n" \
# "#EXT-X-TARGETDURATION:10"
Specifies whether the playlist is an I-frame only playlist.
If set to true, the playlist header will include the EXT-X-I-FRAMES-ONLY tag,
indicating that the playlist contains only I-frame segments (useful for trick play).
Examples:
playlist = Playlist.new
playlist.iframes_only = true
playlist.header
# => "#EXTM3U\n" +
# "#EXT-X-I-FRAMES-ONLY\n" +
# "#EXT-X-MEDIA-SEQUENCE:0\n" +
# "#EXT-X-TARGETDURATION:10"
playlist.iframes_only = false
playlist.header
# => "#EXTM3U\n" +
# "#EXT-X-MEDIA-SEQUENCE:0\n" +
# "#EXT-X-TARGETDURATION:10"
playlist.iframes_only = nil
playlist.header
# => "#EXTM3U\n" +
# "#EXT-X-MEDIA-SEQUENCE:0\n" +
# "#EXT-X-TARGETDURATION:10"
Specifies whether the playlist is an I-frame only playlist.
If set to true, the playlist header will include the EXT-X-I-FRAMES-ONLY tag,
indicating that the playlist contains only I-frame segments (useful for trick play).
Examples:
playlist = Playlist.new
playlist.iframes_only = true
playlist.header
# => "#EXTM3U\n" +
# "#EXT-X-I-FRAMES-ONLY\n" +
# "#EXT-X-MEDIA-SEQUENCE:0\n" +
# "#EXT-X-TARGETDURATION:10"
playlist.iframes_only = false
playlist.header
# => "#EXTM3U\n" +
# "#EXT-X-MEDIA-SEQUENCE:0\n" +
# "#EXT-X-TARGETDURATION:10"
playlist.iframes_only = nil
playlist.header
# => "#EXTM3U\n" +
# "#EXT-X-MEDIA-SEQUENCE:0\n" +
# "#EXT-X-TARGETDURATION:10"
When set to true, the playlist header will include the EXT-X-INDEPENDENT-SEGMENTS tag.
This tag indicates that each Media Segment in the playlist can be independently decoded, which is important for certain playback scenarios in HLS.
If the property is false or nil, the EXT-X-INDEPENDENT-SEGMENTS tag will not be output.
Example:
playlist = Playlist.new
playlist.independent_segments = true
playlist.header
# => "#EXTM3U\n" +
# "#EXT-X-INDEPENDENT-SEGMENTS\n" +
# "#EXT-X-MEDIA-SEQUENCE:0\n" +
# "#EXT-X-TARGETDURATION:10"
playlist.independent_segments = false
playlist.header
# => "#EXTM3U\n" +
# "#EXT-X-MEDIA-SEQUENCE:0\n" +
# "#EXT-X-TARGETDURATION:10"
playlist.independent_segments = nil
playlist.header
# => "#EXTM3U\n" +
# "#EXT-X-MEDIA-SEQUENCE:0\n" +
# "#EXT-X-TARGETDURATION:10"
When set to true, the playlist header will include the EXT-X-INDEPENDENT-SEGMENTS tag.
This tag indicates that each Media Segment in the playlist can be independently decoded, which is important for certain playback scenarios in HLS.
If the property is false or nil, the EXT-X-INDEPENDENT-SEGMENTS tag will not be output.
Example:
playlist = Playlist.new
playlist.independent_segments = true
playlist.header
# => "#EXTM3U\n" +
# "#EXT-X-INDEPENDENT-SEGMENTS\n" +
# "#EXT-X-MEDIA-SEQUENCE:0\n" +
# "#EXT-X-TARGETDURATION:10"
playlist.independent_segments = false
playlist.header
# => "#EXTM3U\n" +
# "#EXT-X-MEDIA-SEQUENCE:0\n" +
# "#EXT-X-TARGETDURATION:10"
playlist.independent_segments = nil
playlist.header
# => "#EXTM3U\n" +
# "#EXT-X-MEDIA-SEQUENCE:0\n" +
# "#EXT-X-TARGETDURATION:10"
Returns true if the playlist is considered live.
- For a Master Playlist, live is always false.
- For a Media Playlist, the live property is determined by the parsed content.
Example:
playlist = Playlist.new(live: true)
playlist.items << SegmentItem.new(duration: 10.991, segment: "test_01.ts")
playlist.live? # => true
Returns true if the playlist is a Master Playlist.
If the #master property is explicitly set (i.e. not nil), its value is returned.
Otherwise, the playlist type is inferred based on the items it contains:
- If there are no
PlaylistItemand noSegmentItementries, it returns false. - If there is at least one
PlaylistItementry, the playlist is considered a Master Playlist.
Examples:
playlist = Playlist.new(master: true)
playlist.master? # => true
playlist = Playlist.new
playlist.master? # => false
playlist = Playlist.new
playlist.items << PlaylistItem.new(program_id: 1, width: 1920, height: 1080, codecs: "avc", bandwidth: 540, uri: "test.url")
playlist.master? # => true
playlist = Playlist.new
playlist.items << SegmentItem.new(duration: 10.991, segment: "test.ts")
playlist.master? # => false
Returns the complete playlist as a string.
The output is generated by concatenating the #header, #body, and #footer sections
of the playlist, separated by newline characters.
Examples:
playlist = Playlist.new
playlist.items << PlaylistItem.new(program_id: "1", uri: "playlist_url", bandwidth: 6400, audio_codec: "mp3")
playlist.to_s
# => "#EXTM3U\n" +
# "#EXT-X-STREAM-INF:PROGRAM-ID=1,CODECS=\"mp4a.40.34\",BANDWIDTH=6400\n" +
# "playlist_url\n"
Validates the playlist and raises an Error::PlaylistType error if it is invalid.
Examples:
playlist = Playlist.new
playlist.items << PlaylistItem.new(program_id: 1, width: 1920, height: 1080, codecs: "avc", bandwidth: 540, uri: "test.url")
playlist.valid! # => nil
playlist.items << SegmentItem.new(duration: 10.991, segment: "test.ts")
playlist.valid! # => raises M3U8::Error::PlaylistType
Validates the playlist.
Returns true if either the number of PlaylistItem entries or SegmentItem entries is zero.
Otherwise, it returns false, indicating a potential mismatch in playlist types.
Example:
playlist = Playlist.new
playlist.items << PlaylistItem.new(program_id: 1, width: 1920, height: 1080, codecs: "avc", bandwidth: 540, uri: "test.url")
playlist.valid? # => true
playlist.items << SegmentItem.new(duration: 10.991, segment: "test.ts")
playlist.valid? # => false