Documentation
¶
Overview ¶
This is a most complete opensource library for parsing and generating of M3U8 playlists used in HTTP Live Streaming (Apple HLS) for internet video translations.
M3U8 is simple text format and parsing library for it must be simple too. It did not offer ways to play HLS or handle playlists over HTTP. Library features are:
- Support HLS specs up to version 5 of the protocol.
- Parsing and generation of master-playlists and media-playlists.
- Autodetect input streams as master or media playlists.
- Offer structures for keeping playlists metadata.
- Encryption keys support for usage with DRM systems like Verimatrix (http://verimatrix.com) etc.
- Support for non standard Google Widevine (http://www.widevine.com) tags.
Library coded acordingly with IETF draft http://tools.ietf.org/html/draft-pantos-http-live-streaming
Examples of usage may be found in *_test.go files of a package. Also see below some simple examples.
Create simple media playlist with sliding window of 3 segments and maximum of 50 segments.
p, e := NewMediaPlaylist(3, 50)
if e != nil {
panic(fmt.Sprintf("Create media playlist failed: %s", e))
}
for i := 0; i < 5; i++ {
e = p.Add(fmt.Sprintf("test%d.ts", i), 5.0)
if e != nil {
panic(fmt.Sprintf("Add segment #%d to a media playlist failed: %s", i, e))
}
}
fmt.Println(p.Encode(true).String())
We add 5 testX.ts segments to playlist then encode it to M3U8 format and convert to string.
Next example shows parsing of master playlist:
f, err := os.Open("sample-playlists/master.m3u8")
if err != nil {
fmt.Println(err)
}
p := NewMasterPlaylist()
err = p.Decode(bufio.NewReader(f), false)
if err != nil {
fmt.Println(err)
}
fmt.Printf("Playlist object: %+v\n", p)
We are open playlist from the file and parse it as master playlist.
Index ¶
- Constants
- func Decode(data bytes.Buffer, strict bool) (Playlist, ListType, error)
- func DecodeFrom(reader io.Reader, strict bool) (Playlist, ListType, error)
- type Alternative
- type Key
- type ListType
- type Map
- type MasterPlaylist
- func (p *MasterPlaylist) Append(uri string, chunklist *MediaPlaylist, params VariantParams)
- func (p *MasterPlaylist) Decode(data bytes.Buffer, strict bool) error
- func (p *MasterPlaylist) DecodeFrom(reader io.Reader, strict bool) error
- func (p *MasterPlaylist) Encode() *bytes.Buffer
- func (p *MasterPlaylist) ResetCache()
- func (p *MasterPlaylist) String() string
- type MediaPlaylist
- func (p *MediaPlaylist) Append(uri string, duration float64, title string) error
- func (p *MediaPlaylist) Close()
- func (p *MediaPlaylist) Count() uint
- func (p *MediaPlaylist) Decode(data bytes.Buffer, strict bool) error
- func (p *MediaPlaylist) DecodeFrom(reader io.Reader, strict bool) error
- func (p *MediaPlaylist) DurationAsInt(yes bool)
- func (p *MediaPlaylist) Encode() *bytes.Buffer
- func (p *MediaPlaylist) Remove() (err error)
- func (p *MediaPlaylist) ResetCache()
- func (p *MediaPlaylist) SetDefaultKey(method, uri, iv, keyformat, keyformatversions string) error
- func (p *MediaPlaylist) SetDefaultMap(uri string, limit, offset int64)
- func (p *MediaPlaylist) SetDiscontinuity() error
- func (p *MediaPlaylist) SetIframeOnly()
- func (p *MediaPlaylist) SetKey(method, uri, iv, keyformat, keyformatversions string) error
- func (p *MediaPlaylist) SetMap(uri string, limit, offset int64) error
- func (p *MediaPlaylist) SetProgramDateTime(value time.Time) error
- func (p *MediaPlaylist) SetRange(limit, offset int64) error
- func (p *MediaPlaylist) Slide(uri string, duration float64, title string)
- func (p *MediaPlaylist) String() string
- type MediaSegment
- type MediaType
- type Playlist
- type Variant
- type VariantParams
- type WV
Examples ¶
Constants ¶
const (
DATETIME = time.RFC3339Nano // Format for EXT-X-PROGRAM-DATE-TIME defined in section 3.4.5
)
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Alternative ¶
type Alternative struct {
GroupId string
URI string
Type string
Language string
Name string
Default bool
Autoselect string
Forced string
Characteristics string
Subtitles string
}
This structure represents EXT-X-MEDIA tag in variants.
type Map ¶ added in v0.3.1
type Map struct {
URI string
Limit int64 // <n> is length in bytes for the file under URI
Offset int64 // [@o] is offset from the start of the file under URI
}
It applies to every Media Segment that appears after it in the Playlist until the next EXT-X-MAP tag or until the end of the playlist.
Realizes EXT-MAP tag.
type MasterPlaylist ¶
type MasterPlaylist struct {
Variants []*Variant
Args string // optional arguments placed after URI (URI?Args)
CypherVersion string // non-standard tag for Widevine (see also WV struct)
// contains filtered or unexported fields
}
This structure represents a master playlist which combines media playlists for multiple bitrates. URI lines in the playlist identify media playlists. Sample of Master Playlist file:
#EXTM3U #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1280000 http://example.com/low.m3u8 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2560000 http://example.com/mid.m3u8 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=7680000 http://example.com/hi.m3u8 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=65000,CODECS="mp4a.40.5" http://example.com/audio-only.m3u8
func NewMasterPlaylist ¶
func NewMasterPlaylist() *MasterPlaylist
Create new empty master playlist. Master playlist consists of variants.
func (*MasterPlaylist) Append ¶
func (p *MasterPlaylist) Append(uri string, chunklist *MediaPlaylist, params VariantParams)
Append variant to master playlist. This operation does reset playlist cache.
func (*MasterPlaylist) Decode ¶
func (p *MasterPlaylist) Decode(data bytes.Buffer, strict bool) error
Parse master playlist from the buffer. If `strict` parameter is true then return first syntax error.
func (*MasterPlaylist) DecodeFrom ¶
func (p *MasterPlaylist) DecodeFrom(reader io.Reader, strict bool) error
Parse master playlist from the io.Reader stream. If `strict` parameter is true then return first syntax error.
func (*MasterPlaylist) Encode ¶
func (p *MasterPlaylist) Encode() *bytes.Buffer
Generate output in M3U8 format.
func (*MasterPlaylist) ResetCache ¶
func (p *MasterPlaylist) ResetCache()
func (*MasterPlaylist) String ¶ added in v0.3.1
func (p *MasterPlaylist) String() string
For compatibility with Stringer interface For example fmt.Printf("%s", sampleMediaList) will encode playist and print its string representation.
Example ¶
Create new master playlist Add media playlist Encode structures to HLS
m := NewMasterPlaylist()
p, _ := NewMediaPlaylist(3, 5)
for i := 0; i < 5; i++ {
p.Append(fmt.Sprintf("test%d.ts", i), 5.0, "")
}
m.Append("chunklist1.m3u8", p, VariantParams{ProgramId: 123, Bandwidth: 1500000, Resolution: "576x480"})
m.Append("chunklist2.m3u8", p, VariantParams{ProgramId: 123, Bandwidth: 1500000, Resolution: "576x480"})
fmt.Printf("%s", m)
Output: #EXTM3U #EXT-X-VERSION:3 #EXT-X-STREAM-INF:PROGRAM-ID=123,BANDWIDTH=1500000,RESOLUTION=576x480 chunklist1.m3u8 #EXT-X-STREAM-INF:PROGRAM-ID=123,BANDWIDTH=1500000,RESOLUTION=576x480 chunklist2.m3u8
type MediaPlaylist ¶
type MediaPlaylist struct {
TargetDuration float64
SeqNo uint64 // EXT-X-MEDIA-SEQUENCE
Segments []*MediaSegment
Args string // optional arguments placed after URIs (URI?Args)
Iframe bool // EXT-X-I-FRAMES-ONLY
Closed bool // is this VOD (closed) or Live (sliding) playlist?
MediaType MediaType
Key *Key // EXT-X-KEY is optional encryption key displayed before any segments (default key for the playlist)
Map *Map // EXT-X-MAP is optional tag specifies how to obtain the Media Initialization Section (default map for the playlist)
WV *WV // Widevine related tags outside of M3U8 specs
// contains filtered or unexported fields
}
This structure represents a single bitrate playlist aka media playlist. It related to both a simple media playlists and a sliding window media playlists. URI lines in the Playlist point to media segments.
Simple Media Playlist file sample:
#EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:5220 #EXTINF:5219.2, http://media.example.com/entire.ts #EXT-X-ENDLIST
Sample of Sliding Window Media Playlist, using HTTPS:
#EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:8 #EXT-X-MEDIA-SEQUENCE:2680 #EXTINF:7.975, https://priv.example.com/fileSequence2680.ts #EXTINF:7.941, https://priv.example.com/fileSequence2681.ts #EXTINF:7.975, https://priv.example.com/fileSequence2682.ts
func NewMediaPlaylist ¶
func NewMediaPlaylist(winsize uint, capacity uint) (*MediaPlaylist, error)
Creates new media playlist structure. Winsize defines how much items will displayed on playlist generation. Capacity is total size of a playlist.
func (*MediaPlaylist) Append ¶
func (p *MediaPlaylist) Append(uri string, duration float64, title string) error
Append general chunk to the tail of chunk slice for a media playlist. This operation does reset playlist cache.
func (*MediaPlaylist) Close ¶
func (p *MediaPlaylist) Close()
Close sliding playlist and make them fixed.
func (*MediaPlaylist) Count ¶ added in v0.3.2
func (p *MediaPlaylist) Count() uint
Count tells us the number of items that are currently in the media playlist
func (*MediaPlaylist) Decode ¶
func (p *MediaPlaylist) Decode(data bytes.Buffer, strict bool) error
Parse media playlist from the buffer. If `strict` parameter is true then return first syntax error.
func (*MediaPlaylist) DecodeFrom ¶
func (p *MediaPlaylist) DecodeFrom(reader io.Reader, strict bool) error
Parse media playlist from the io.Reader stream. If `strict` parameter is true then return first syntax error.
func (*MediaPlaylist) DurationAsInt ¶
func (p *MediaPlaylist) DurationAsInt(yes bool)
TargetDuration will be int on Encode
Example ¶
Example of parsing a playlist with EXT-X-DISCONTINIUTY tag and output it with integer segment durations.
f, _ := os.Open("sample-playlists/media-playlist-with-discontinuity.m3u8")
p, _, _ := DecodeFrom(bufio.NewReader(f), true)
pp := p.(*MediaPlaylist)
pp.DurationAsInt(true)
fmt.Printf("%s", pp)
Output: #EXTM3U #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:1 #EXT-X-TARGETDURATION:10 #EXTINF:10, ad0.ts #EXTINF:8, ad1.ts #EXT-X-DISCONTINUITY #EXTINF:10, movieA.ts #EXTINF:10, movieB.ts
func (*MediaPlaylist) Encode ¶
func (p *MediaPlaylist) Encode() *bytes.Buffer
Generate output in M3U8 format. Marshal `winsize` elements from bottom of the `segments` queue.
func (*MediaPlaylist) Remove ¶
func (p *MediaPlaylist) Remove() (err error)
Remove current segment from the head of chunk slice form a media playlist. Useful for sliding playlists. This operation does reset playlist cache.
func (*MediaPlaylist) ResetCache ¶
func (p *MediaPlaylist) ResetCache()
Reset playlist cache. Next called Encode() will regenerate playlist from the chunk slice.
func (*MediaPlaylist) SetDefaultKey ¶
func (p *MediaPlaylist) SetDefaultKey(method, uri, iv, keyformat, keyformatversions string) error
Set encryption key appeared once in header of the playlist (pointer to MediaPlaylist.Key). It useful when keys not changed during playback. Set tag for the whole list.
func (*MediaPlaylist) SetDefaultMap ¶ added in v0.3.1
func (p *MediaPlaylist) SetDefaultMap(uri string, limit, offset int64)
Set map appeared once in header of the playlist (pointer to MediaPlaylist.Key). It useful when map not changed during playback. Set tag for the whole list.
func (*MediaPlaylist) SetDiscontinuity ¶
func (p *MediaPlaylist) SetDiscontinuity() error
Set discontinuity flag for the current media segment. EXT-X-DISCONTINUITY indicates an encoding discontinuity between the media segment that follows it and the one that preceded it (i.e. file format, number and type of tracks, encoding parameters, encoding sequence, timestamp sequence).
func (*MediaPlaylist) SetIframeOnly ¶ added in v0.3.1
func (p *MediaPlaylist) SetIframeOnly()
Mark medialist as consists of only I-frames (Intra frames). Set tag for the whole list.
func (*MediaPlaylist) SetKey ¶
func (p *MediaPlaylist) SetKey(method, uri, iv, keyformat, keyformatversions string) error
Set encryption key for the current segment of media playlist (pointer to Segment.Key)
func (*MediaPlaylist) SetMap ¶ added in v0.3.1
func (p *MediaPlaylist) SetMap(uri string, limit, offset int64) error
Set encryption key for the current segment of media playlist (pointer to Segment.Key)
func (*MediaPlaylist) SetProgramDateTime ¶
func (p *MediaPlaylist) SetProgramDateTime(value time.Time) error
Set program date and time for the current media segment. EXT-X-PROGRAM-DATE-TIME tag associates the first sample of a media segment with an absolute date and/or time. It applies only to the current media segment. Date/time format is YYYY-MM-DDThh:mm:ssZ (ISO8601) and includes time zone.
func (*MediaPlaylist) SetRange ¶
func (p *MediaPlaylist) SetRange(limit, offset int64) error
Set limit and offset for the current media segment (EXT-X-BYTERANGE support for protocol version 4).
func (*MediaPlaylist) Slide ¶
func (p *MediaPlaylist) Slide(uri string, duration float64, title string)
Combines two operations: firstly it removes one chunk from the head of chunk slice and move pointer to next chunk. Secondly it appends one chunk to the tail of chunk slice. Useful for sliding playlists. This operation does reset cache.
func (*MediaPlaylist) String ¶ added in v0.3.1
func (p *MediaPlaylist) String() string
For compatibility with Stringer interface For example fmt.Printf("%s", sampleMediaList) will encode playist and print its string representation.
Example ¶
Create new media playlist Add two segments to media playlist Print it
p, _ := NewMediaPlaylist(1, 2)
p.Append("test01.ts", 5.0, "")
p.Append("test02.ts", 6.0, "")
fmt.Printf("%s\n", p)
Output: #EXTM3U #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:1 #EXT-X-TARGETDURATION:6 #EXTINF:5.000, test01.ts
type MediaSegment ¶
type MediaSegment struct {
SeqId uint64
Title string // optional second parameter for EXTINF tag
URI string
Duration float64 // first parameter for EXTINF tag; duration must be integers if protocol version is less than 3 but we are always keep them float
Limit int64 // EXT-X-BYTERANGE <n> is length in bytes for the file under URI
Offset int64 // EXT-X-BYTERANGE [@o] is offset from the start of the file under URI
Key *Key // EXT-X-KEY displayed before the segment and means changing of encryption key (in theory each segment may have own key)
Map *Map // EXT-X-MAP displayed before the segment
Discontinuity bool // EXT-X-DISCONTINUITY indicates an encoding discontinuity between the media segment that follows it and the one that preceded it (i.e. file format, number and type of tracks, encoding parameters, encoding sequence, timestamp sequence)
ProgramDateTime time.Time // EXT-X-PROGRAM-DATE-TIME tag associates the first sample of a media segment with an absolute date and/or time
}
This structure represents a media segment included in a media playlist. Media segment may be encrypted. Widevine supports own tags for encryption metadata.
type Playlist ¶
type Playlist interface {
Encode() *bytes.Buffer
Decode(bytes.Buffer, bool) error
DecodeFrom(reader io.Reader, strict bool) error
String() string
}
Interface applied to various playlist types.
type Variant ¶
type Variant struct {
URI string
Chunklist *MediaPlaylist
VariantParams
}
This structure represents variants for master playlist. Variants included in a master playlist and point to media playlists.
type VariantParams ¶
type VariantParams struct {
ProgramId uint32
Bandwidth uint32
Codecs string
Resolution string
Audio string // EXT-X-STREAM-INF only
Video string
Subtitles string // EXT-X-STREAM-INF only
Captions string // EXT-X-STREAM-INF only
Name string // EXT-X-STREAM-INF only (non standard Wowza/JWPlayer extension to name the variant/quality in UA)
Iframe bool // EXT-X-I-FRAME-STREAM-INF
Alternatives []*Alternative
}
This stucture represents additional parameters for a variant used in EXT-X-STREAM-INF and EXT-X-I-FRAME-STREAM-INF
type WV ¶
type WV struct {
AudioChannels uint
AudioFormat uint
AudioProfileIDC uint
AudioSampleSize uint
AudioSamplingFrequency uint
CypherVersion string
ECM string
VideoFormat uint
VideoFrameRate uint
VideoLevelIDC uint
VideoProfileIDC uint
VideoResolution string
VideoSAR string
}
This structure represents metadata for Google Widevine playlists. This format not described in IETF draft but provied by Widevine Live Packager as additional tags with #WV-prefix.



