Awesome
m3u8-parser
m3u8 parser
<!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->Installation
npm install --save m3u8-parser
The npm installation is preferred, but Bower works, too.
bower install --save m3u8-parser
Usage
var manifest = [
'#EXTM3U',
'#EXT-X-VERSION:3',
'#EXT-X-TARGETDURATION:6',
'#EXT-X-MEDIA-SEQUENCE:0',
'#EXT-X-DISCONTINUITY-SEQUENCE:0',
'#EXTINF:6,',
'0.ts',
'#EXTINF:6,',
'1.ts',
'#EXT-X-PROGRAM-DATE-TIME:2019-02-14T02:14:00.106Z'
'#EXTINF:6,',
'2.ts',
'#EXT-X-ENDLIST'
].join('\n');
var parser = new m3u8Parser.Parser();
parser.push(manifest);
parser.end();
var parsedManifest = parser.manifest;
Constructor Options
The constructor optinally takes an options object with two properties. These are needed when using #EXT-X-DEFINE
for variable replacement.
var parser = new m3u8Parser.Parser({
url: 'https://exmaple.com/video.m3u8?param_a=34¶m_b=abc',
mainDefinitions: {
param_c: 'def'
}
});
options.url
string The URL from which the playlist was fetched. If the request was redirected this should be the final URL. This is required if usingQUERYSTRING
rules with#EXT-X-DEFINE
.options.mainDefinitions
object An object of definitions from the main playlist. This is required if usingIMPORT
rules with#EXT-X-DEFINE
.
Parsed Output
The parser ouputs a plain javascript object with the following structure:
Manifest {
allowCache: boolean,
endList: boolean,
mediaSequence: number,
dateRanges: [],
discontinuitySequence: number,
playlistType: string,
custom: {},
playlists: [
{
attributes: {},
Manifest
}
],
mediaGroups: {
AUDIO: {
'GROUP-ID': {
NAME: {
default: boolean,
autoselect: boolean,
language: string,
uri: string,
instreamId: string,
characteristics: string,
forced: boolean
}
}
},
VIDEO: {},
'CLOSED-CAPTIONS': {},
SUBTITLES: {}
},
dateTimeString: string,
dateTimeObject: Date,
targetDuration: number,
totalDuration: number,
discontinuityStarts: [number],
segments: [
{
title: string,
byterange: {
length: number,
offset: number
},
duration: number,
programDateTime: number,
attributes: {},
discontinuity: number,
uri: string,
timeline: number,
key: {
method: string,
uri: string,
iv: string
},
map: {
uri: string,
byterange: {
length: number,
offset: number
}
},
'cue-out': string,
'cue-out-cont': string,
'cue-in': string,
custom: {}
}
]
}
Supported Tags
Basic Playlist Tags
Media Segment Tags
- EXTINF
- EXT-X-BYTERANGE
- EXT-X-DISCONTINUITY
- EXT-X-KEY
- EXT-X-MAP
- EXT-X-PROGRAM-DATE-TIME
- EXT-X-DATERANGE
- EXT-X-I-FRAMES-ONLY
Media Playlist Tags
- EXT-X-TARGETDURATION
- EXT-X-MEDIA-SEQUENCE
- EXT-X-DISCONTINUITY-SEQUENCE
- EXT-X-ENDLIST
- EXT-X-PLAYLIST-TYPE
- EXT-X-START
- EXT-X-INDEPENDENT-SEGMENTS
- EXT-X-DEFINE
Main Playlist Tags
Experimental Tags
m3u8-parser supports 3 additional Media Segment Tags not present in the HLS specification.
EXT-X-CUE-OUT
The EXT-X-CUE-OUT
indicates that the following media segment is a break in main content and the start of interstitial content. Its format is:
#EXT-X-CUE-OUT:<duration>
where duration
is a decimal-floating-point or decimal-integer number that specifies the total duration of the interstitial in seconds.
EXT-X-CUE-OUT-CONT
The EXT-X-CUE-OUT-CONT
indicates that the following media segment is a part of interstitial content and not the main content. Every media segment following a media segment with an EXT-X-CUE-OUT
tag SHOULD have an EXT-X-CUE-OUT-CONT
applied to it until there is an EXT-X-CUE-IN
tag. A media segment between a EXT-X-CUE-OUT
and EXT-X-CUE-IN
segment without a EXT-X-CUE-OUT-CONT
is assumed to be part of the interstitial. Its format is:
#EXT-X-CUE-OUT-CONT:<n>/<duration>
where n
is a decimal-floating-point or decimal-integer number that specifies the time in seconds the first sample of the media segment lies within the interstitial content and duration
is a decimal-floating-point or decimal-integer number that specifies the total duration of the interstitial in seconds. n
SHOULD be the sum of EXTINF
durations for all preceding media segments up to the EXT-X-CUE-OUT
tag for the current interstitial. duration
SHOULD match the duration
specified in the EXT-X-CUE-OUT
tag for the current interstitial.'
EXT-X-CUE-IN
The EXT-X-CUE-IN
indicates the end of the interstitial and the return of the main content. Its format is:
#EXT-X-CUE-IN
There SHOULD be a closing EXT-X-CUE-IN
tag for every EXT-X-CUE-OUT
tag. If a second EXT-X-CUE-OUT
tag is encountered before an EXT-X-CUE-IN
tag, the client MAY choose to ignore the EXT-X-CUE-OUT
and treat it as part of the interstitial, or reject the playlist.
Example media playlist using EXT-X-CUE-
tags.
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXTINF:10,
0.ts
#EXTINF:10,
1.ts
#EXT-X-CUE-OUT:30
#EXTINF:10,
2.ts
#EXT-X-CUE-OUT-CONT:10/30
#EXTINF:10,
3.ts
#EXT-X-CUE-OUT-CONT:20/30
#EXTINF:10,
4.ts
#EXT-X-CUE-IN
#EXTINF:10,
5.ts
#EXTINF:10,
6.ts
#EXT-X-ENDLIST
Not Yet Supported
Custom Parsers
To add a parser for a non-standard tag the parser object allows for the specification of custom tags using regular expressions. If a custom parser is specified, a custom
object is appended to the manifest object.
const manifest = [
'#EXTM3U',
'#EXT-X-VERSION:3',
'#VOD-FRAMERATE:29.97',
''
].join('\n');
const parser = new m3u8Parser.Parser();
parser.addParser({
expression: /^#VOD-FRAMERATE/,
customType: 'framerate'
});
parser.push(manifest);
parser.end();
parser.manifest.custom.framerate // "#VOD-FRAMERATE:29.97"
Custom parsers may additionally be provided a data parsing function that take a line and return a value.
const manifest = [
'#EXTM3U',
'#EXT-X-VERSION:3',
'#VOD-FRAMERATE:29.97',
''
].join('\n');
const parser = new m3u8Parser.Parser();
parser.addParser({
expression: /^#VOD-FRAMERATE/,
customType: 'framerate',
dataParser: function(line) {
return parseFloat(line.split(':')[1]);
}
});
parser.push(manifest);
parser.end();
parser.manifest.custom.framerate // 29.97
Custom parsers may also extract data at a segment level by passing segment: true
to the options object. Having a segment level custom parser will add a custom
object to the segment data.
const manifest = [
'#EXTM3U',
'#VOD-TIMING:1511816599485',
'#EXTINF:8.0,',
'ex1.ts',
''
].join('\n');
const parser = new m3u8Parser.Parser();
parser.addParser({
expression: /#VOD-TIMING/,
customType: 'vodTiming',
segment: true
});
parser.push(manifest);
parser.end();
parser.manifest.segments[0].custom.vodTiming // #VOD-TIMING:1511816599485
Custom parsers may also map a tag to another tag. The old tag will not be replaced and all matching registered mappers and parsers will be executed.
const manifest = [
'#EXTM3U',
'#EXAMPLE',
'#EXTINF:8.0,',
'ex1.ts',
''
].join('\n');
const parser = new m3u8Parser.Parser();
parser.addTagMapper({
expression: /#EXAMPLE/,
map(line) {
return `#NEW-TAG:123`;
}
});
parser.addParser({
expression: /#NEW-TAG/,
customType: 'mappingExample',
segment: true
});
parser.push(manifest);
parser.end();
parser.manifest.segments[0].custom.mappingExample // #NEW-TAG:123
Including the Parser
To include m3u8-parser on your website or web application, use any of the following methods.
<script>
Tag
This is the simplest case. Get the script in whatever way you prefer and include it on your page.
<script src="//path/to/m3u8-parser.min.js"></script>
<script>
var parser = new m3u8Parser.Parser();
</script>
Browserify
When using with Browserify, install m3u8-parser via npm and require
the parser as you would any other module.
var m3u8Parser = require('m3u8-parser');
var parser = new m3u8Parser.Parser();
With ES6:
import { Parser } from 'm3u8-parser';
const parser = new Parser();
RequireJS/AMD
When using with RequireJS (or another AMD library), get the script in whatever way you prefer and require
the parser as you normally would:
require(['m3u8-parser'], function(m3u8Parser) {
var parser = new m3u8Parser.Parser();
});
License
Apache-2.0. Copyright (c) Brightcove, Inc