hls

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 31, 2018 License: BSD-3-Clause Imports: 9 Imported by: 0

README

HLS

This is a refactor of the github.com/grafov/m3u8 go library, the original fork is at github.com/ShevaXu/m3u8.

The reasons to refactor are the follows:

The code (the initial commit) is refactored from https://github.com/ShevaXu/m3u8/commit/021378ff0ef3a7ec7aa45e9189ed8d343a33ad11.

Authors

See AUTHORS for the original authors and thanks for their work.

Documentation

Overview

Package hls is parser & generator library for Apple HLS.

Index

Examples

Constants

View Source
const (

	// DateTime is the format for EXT-X-PROGRAM-DATE-TIME defined in section 3.4.5.
	DateTime = time.RFC3339Nano
)

Variables

View Source
var ErrPlaylistFull = errors.New("playlist is full")

ErrPlaylistFull is the error surfaced if a playlist is full. Consider extending the capacity in that situation.

View Source
var TimeParse = FullTimeParse

TimeParse globally apply and/or override Time Parser function. Available variants:

  • FullTimeParse - implements full featured ISO/IEC 8601:2004
  • StrictTimeParse - implements only RFC3339 Nanoseconds format

Functions

func Decode

func Decode(data bytes.Buffer, strict bool) (Playlist, ListType, error)

Decode detects type of playlist and decodes it. It accepts bytes buffer as input.

func DecodeFrom

func DecodeFrom(reader io.Reader, strict bool) (Playlist, ListType, error)

DecodeFrom detects type of playlist and decodes it. It accepts data conformed with io.Reader.

func FullTimeParse

func FullTimeParse(value string) (time.Time, error)

FullTimeParse implements ISO/IEC 8601:2004.

func StrictTimeParse

func StrictTimeParse(value string) (time.Time, error)

StrictTimeParse implements RFC3339 with Nanoseconds accuracy.

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
}

Alternative represents EXT-X-MEDIA tag in variants.

type Key

type Key struct {
	Method            string
	URI               string
	IV                string
	Keyformat         string
	Keyformatversions string
}

Key represents information about stream encryption. It realizes the EXT-X-KEY tag.

type ListType

type ListType int

ListType is the type of playlist parsed.

const (
	// use 0 for not defined type
	ListTypeMaster ListType = iota + 1
	ListTypeMedia
)

List types defined

type Map

type Map struct {
	URI    string
	Limit  int // <n> is length in bytes for the file under URI
	Offset int // [@o] is offset from the start of the file under URI
}

Map represents specifies how to obtain the Media Initialization Section required to parse the applicable Media Segments. 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. It realizes the 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
}

MasterPlaylist 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
Example

Create new master playlist Add media playlist Encode structures to HLS

package main

import (
	"fmt"

	"github.com/ShevaXu/hls"
)

func main() {
	m := hls.NewMasterPlaylist()
	p, _ := hls.NewMediaPlaylist(3, 5)
	for i := 0; i < 5; i++ {
		p.Append(hls.QuickSegment(fmt.Sprintf("test%d.ts", i), "", 5.0))
	}
	m.Append("chunklist1.m3u8", p, hls.VariantParams{ProgramID: 123, Bandwidth: 1500000, Resolution: "576x480"})
	m.Append("chunklist2.m3u8", p, hls.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

func NewMasterPlaylist

func NewMasterPlaylist() *MasterPlaylist

NewMasterPlaylist creates a new empty master playlist.

func (*MasterPlaylist) Append

func (p *MasterPlaylist) Append(uri string, chunklist *MediaPlaylist, params VariantParams)

Append appends variant to master playlist. This operation does reset playlist cache.

func (*MasterPlaylist) Decode

func (p *MasterPlaylist) Decode(data bytes.Buffer, strict bool) error

Decode parses a master playlist passed from the buffer. If `strict` parameter is true then it returns first syntax error.

func (*MasterPlaylist) DecodeFrom

func (p *MasterPlaylist) DecodeFrom(reader io.Reader, strict bool) error

DecodeFrom parses a master playlist passed from the io.Reader stream. If `strict` parameter is true then it returns first syntax error.

func (*MasterPlaylist) Encode

func (p *MasterPlaylist) Encode() *bytes.Buffer

Encode generates the output in M3U8 format.

func (*MasterPlaylist) ResetCache

func (p *MasterPlaylist) ResetCache()

ResetCache resets the underlying bytes buffer.

func (*MasterPlaylist) SetVersion

func (p *MasterPlaylist) SetVersion(ver int)

SetVersion sets the playlist version number, note the version maybe changed automatically by other Set methods.

func (*MasterPlaylist) String

func (p *MasterPlaylist) String() string

String returns the encoded buffer in string format, which implements the Stringer interface for Printf-like func.

func (*MasterPlaylist) Version

func (p *MasterPlaylist) Version() int

Version returns the current playlist version number

type MediaPlaylist

type MediaPlaylist struct {
	TargetDuration float64
	SeqNo          int // 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)
	W   *Widevine // Widevine related tags outside of M3U8 specs
	// contains filtered or unexported fields
}

MediaPlaylist 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
Example

Create new media playlist Add two segments to media playlist Print it

package main

import (
	"fmt"

	"github.com/ShevaXu/hls"
)

func main() {
	p, _ := hls.NewMediaPlaylist(0, 2)
	p.Append(hls.QuickSegment("test01.ts", "", 5.0))
	p.Append(hls.QuickSegment("test02.ts", "", 6.0))
	fmt.Printf("%s\n", p)
}
Output:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-TARGETDURATION:6
#EXTINF:5.000,
test01.ts
#EXTINF:6.000,
test02.ts

func NewMediaPlaylist

func NewMediaPlaylist(winsize, capacity int) (*MediaPlaylist, error)

NewMediaPlaylist creates a new media playlist structure. winsize defines how much items will displayed on playlist generation; capacity is total size of a playlist (and its underlying arrray).

func (*MediaPlaylist) Append

func (p *MediaPlaylist) Append(seg *MediaSegment) error

Append appends a MediaSegment to the tail of chunk slice for a media playlist. This operation does reset playlist cache.

func (*MediaPlaylist) AppendWithAutoExtend

func (p *MediaPlaylist) AppendWithAutoExtend(seg *MediaSegment) error

AppendWithAutoExtend appends a MediaSegment and auto extend the capacity if 2/3 full.

func (*MediaPlaylist) Close

func (p *MediaPlaylist) Close()

Close adds end-list to the playlist.

Example

Create new media playlist Add two segments to media playlist Print it

package main

import (
	"fmt"

	"github.com/ShevaXu/hls"
)

func main() {
	p, _ := hls.NewMediaPlaylist(0, 2)
	p.Append(hls.QuickSegment("test01.ts", "", 5.0))
	p.Append(hls.QuickSegment("test02.ts", "", 6.0))
	p.Close()
	fmt.Printf("%s\n", p)
}
Output:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-TARGETDURATION:6
#EXTINF:5.000,
test01.ts
#EXTINF:6.000,
test02.ts
#EXT-X-ENDLIST

func (*MediaPlaylist) Count

func (p *MediaPlaylist) Count() int

Count returns the number of items that are currently in the media playlist.

func (*MediaPlaylist) Decode

func (p *MediaPlaylist) Decode(data bytes.Buffer, strict bool) error

Decode parses a media playlist passed 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

DecodeFrom parses a media playlist passed from the io.Reader stream. If `strict` parameter is true then it returns first syntax error.

Example
package main

import (
	"bufio"
	"fmt"
	"os"

	"github.com/ShevaXu/hls"
)

func main() {
	f, _ := os.Open("sample-playlists/media-playlist-with-oatcls-scte35.m3u8")
	p, _, _ := hls.DecodeFrom(bufio.NewReader(f), true)
	pp := p.(*hls.MediaPlaylist)
	fmt.Print(pp)
}
Output:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-TARGETDURATION:10
#EXT-OATCLS-SCTE35:/DAlAAAAAAAAAP/wFAUAAAABf+/+ANgNkv4AFJlwAAEBAQAA5xULLA==
#EXT-X-CUE-OUT:15
#EXTINF:8.844,
media0.ts
#EXT-X-CUE-OUT-CONT:ElapsedTime=8.844,Duration=15,SCTE35=/DAlAAAAAAAAAP/wFAUAAAABf+/+ANgNkv4AFJlwAAEBAQAA5xULLA==
#EXTINF:6.156,
media1.ts
#EXT-X-CUE-IN
#EXTINF:3.844,
media2.ts

func (*MediaPlaylist) DurationAsInt

func (p *MediaPlaylist) DurationAsInt(yes bool)

DurationAsInt sets if the TargetDuration should be format to int.

Example

Example of parsing a playlist with EXT-X-DISCONTINIUTY tag and output it with integer segment durations.

package main

import (
	"bufio"
	"fmt"
	"os"

	"github.com/ShevaXu/hls"
)

func main() {
	f, _ := os.Open("sample-playlists/media-playlist-with-discontinuity.m3u8")
	p, _, _ := hls.DecodeFrom(bufio.NewReader(f), true)
	pp := p.(*hls.MediaPlaylist)
	pp.DurationAsInt(true)
	fmt.Printf("%s", pp)
}
Output:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#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

Encode generate output in M3U8 format. It marshals `winsize` elements from bottom of the `segments` queue.

func (*MediaPlaylist) ExtendCapacity

func (p *MediaPlaylist) ExtendCapacity() (err error)

ExtendCapacity extend current capacity to double, and move tail to pos of last end When Generate Vod Playlist, if append failed, can call this extend function to contine

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()

ResetCache resets the playlist cache, so that next call on Encode() will regenerate playlist from the chunk slice.

func (*MediaPlaylist) SetDefaultKey

func (p *MediaPlaylist) SetDefaultKey(method, uri, iv, keyformat, keyformatversions string) error

SetDefaultKey sets the encryption key appeared once in header of the playlist (pointer to MediaPlaylist.Key). The tag set applies for the whole list. It is useful when keys are not changed during playback.

func (*MediaPlaylist) SetDefaultMap

func (p *MediaPlaylist) SetDefaultMap(uri string, limit, offset int)

SetDefaultMap sets the default Media Initialization Section values for playlist (pointer to MediaPlaylist.Map). It sets EXT-X-MAP tag for the whole playlist.

func (*MediaPlaylist) SetDiscontinuity

func (p *MediaPlaylist) SetDiscontinuity() error

SetDiscontinuity sets the 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

func (p *MediaPlaylist) SetIframeOnly()

SetIframeOnly marks medialist as consists of only I-frames (Intra frames). The tag set applies for the whole list.

func (*MediaPlaylist) SetKey

func (p *MediaPlaylist) SetKey(method, uri, iv, keyformat, keyformatversions string) error

SetKey sets a encryption key for the current segment of media playlist (pointer to Segment.Key).

func (*MediaPlaylist) SetMap

func (p *MediaPlaylist) SetMap(uri string, limit, offset int) error

SetMap sets a map for the current segment of media playlist (pointer to Segment.Map).

func (*MediaPlaylist) SetProgramDateTime

func (p *MediaPlaylist) SetProgramDateTime(value time.Time) error

SetProgramDateTime sets the 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 int) error

SetRange sets the limit and offset for the current media segment (EXT-X-BYTERANGE support for protocol version 4).

func (*MediaPlaylist) SetSCTE35

func (p *MediaPlaylist) SetSCTE35(scte35 *SCTE) error

SetSCTE35 sets the SCTE cue format for the current media segment

func (*MediaPlaylist) SetVersion

func (p *MediaPlaylist) SetVersion(ver int)

SetVersion sets the playlist version number, note the version maybe changed automatically by other Set methods.

func (*MediaPlaylist) SetWinSize

func (p *MediaPlaylist) SetWinSize(winsize int) error

SetWinSize overwrites the playlist's window size.

func (*MediaPlaylist) Slide

func (p *MediaPlaylist) Slide(seg *MediaSegment) (err error)

Slide first removes one chunk from the head if winsize full, then appends one chunk to the tail. Useful for sliding/live playlists. This operation does reset cache.

func (*MediaPlaylist) String

func (p *MediaPlaylist) String() string

String returns the encoded buffer in string format, which implements the Stringer interface for Printf-like func.

func (*MediaPlaylist) Version

func (p *MediaPlaylist) Version() int

Version returns the current playlist version number

func (*MediaPlaylist) WinSize

func (p *MediaPlaylist) WinSize() int

WinSize returns the playlist's window size.

type MediaSegment

type MediaSegment struct {
	SeqID           int
	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           int       // EXT-X-BYTERANGE <n> is length in bytes for the file under URI
	Offset          int       // 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)
	SCTE            *SCTE     // SCTE-35 used for Ad signaling in HLS
	ProgramDateTime time.Time // EXT-X-PROGRAM-DATE-TIME tag associates the first sample of a media segment with an absolute date and/or time
}

MediaSegment represents a media segment included in a media playlist. Media segment may be encrypted. Widevine supports own tags for encryption metadata.

func QuickSegment

func QuickSegment(uri, title string, duration float64) *MediaSegment

QuickSegment returns a segment ready to append.

type MediaType

type MediaType int

MediaType is for EXT-X-PLAYLIST-TYPE tag.

const (
	// use 0 for not defined type
	MediaTypeEvent MediaType = iota + 1
	MediaTypeVOD
)

Media types defined

type Playlist

type Playlist interface {
	Encode() *bytes.Buffer
	Decode(bytes.Buffer, bool) error
	DecodeFrom(reader io.Reader, strict bool) error
	String() string
}

Playlist abstracts various playlist types.

type SCTE

type SCTE struct {
	Syntax  SCTE35Syntax  // Syntax defines the format of the SCTE-35 cue tag
	CueType SCTE35CueType // CueType defines whether the cue is a start, mid, end (if applicable)
	Cue     string
	ID      string
	Time    float64
	Elapsed float64
}

SCTE holds custom, non EXT-X-DATERANGE, SCTE-35 tags

type SCTE35CueType

type SCTE35CueType int

SCTE35CueType defines the type of cue point, used by readers and writers to write a different syntax

const (
	SCTE35CueStart SCTE35CueType = iota // SCTE35CueStart indicates an out cue point
	SCTE35CueMid                        // SCTE35CueMid indicates a segment between start and end cue points
	SCTE35CueEnd                        // SCTE35CueEnd indicates an in cue point
)

Cue types defined

type SCTE35Syntax

type SCTE35Syntax int

SCTE35Syntax defines the format of the SCTE-35 cue points which do not use the draft-pantos-http-live-streaming-19 EXT-X-DATERANGE tag and instead have their own custom tags

const (
	// Syntax672014 will be the default due to backwards compatibility reasons.
	// (defined in http://www.scte.org/documents/pdf/standards/SCTE%2067%202014.pdf)
	Syntax672014 SCTE35Syntax = iota
	// SyntaxOATCLS is a non-standard but common format
	SyntaxOATCLS
)

type Variant

type Variant struct {
	URI       string
	Chunklist *MediaPlaylist
	VariantParams
}

Variant represents variants for master playlist. Variants included in a master playlist and point to media playlists.

type VariantParams

type VariantParams struct {
	ProgramID    int
	Bandwidth    int
	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 // EXT-X-MEDIA
}

VariantParams represents additional parameters for a variant used in EXT-X-STREAM-INF and EXT-X-I-FRAME-STREAM-INF

type Widevine

type Widevine struct {
	AudioChannels          int
	AudioFormat            int
	AudioProfileIDC        int
	AudioSampleSize        int
	AudioSamplingFrequency int
	CypherVersion          string
	ECM                    string
	VideoFormat            int
	VideoFrameRate         int
	VideoLevelIDC          int
	VideoProfileIDC        int
	VideoResolution        string
	VideoSAR               string
}

Widevine represents metadata for Google Widevine playlists. This format not described in IETF draft but provied by Widevine Live Packager as additional tags with #Widevine-prefix.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL