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
:Playlist
EXT-X-VERSION
:Playlist#version
Media Playlist Tags:
EXT-X-TARGETDURATION
:Playlist#target
EXT-X-MEDIA-SEQUENCE
:Playlist#sequence
EXT-X-DISCONTINUITY-SEQUENCE
:Playlist#discontinuity_sequence
EXT-X-ENDLIST
:Playlist.footer
EXT-X-PLAYLIST-TYPE
:Playlist#type
EXT-X-I-FRAMES-ONLY
:Playlist#iframes_only
EXT-X-ALLOW-CACHE
:Playlist#cache
(deprecated in protocol version 7)
Media Segment Tags:
EXTINF
:SegmentItem
EXT-X-BYTERANGE
:ByteRange
EXT-X-DISCONTINUITY
:DiscontinuityItem
EXT-X-KEY
:KeyItem
EXT-X-MAP
:MapItem
EXT-X-PROGRAM-DATE-TIME
:TimeItem
EXT-X-DATERANGE
:DateRangeItem
Master Playlist tags:
EXT-X-MEDIA
:MediaItem
EXT-X-STREAM-INF
:PlaylistItem
withPlaylist#iframe
set tofalse
EXT-X-I-FRAME-STREAM-INF
:PlaylistItem
withPlaylist#iframe
set totrue
EXT-X-SESSION-DATA
:SessionDataItem
EXT-X-SESSION-KEY
:SessionKeyItem
Media or Master Playlist Tags:
EXT-X-INDEPENDENT-SEGMENTS
:Playlist#independent_segments
EXT-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-CACHE
tag 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
Playlist
instance.
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-SEGMENTS
tag. -
#independent_segments=(independent_segments : Bool)
When set to true, the playlist header will include the
EXT-X-INDEPENDENT-SEGMENTS
tag. - #items : Array(Items)
- #items=(items : Array(Items))
- #live : Bool
- #live=(live : Bool)
-
#live?
Returns
true
if the playlist is considered live. - #master : Bool | Nil
- #master=(master : Bool | Nil)
-
#master?
Returns
true
if 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::PlaylistType
error 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
PlaylistItem
and noSegmentItem
entries, it returns false. - If there is at least one
PlaylistItem
entry, 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