m3u8-parser
This is a fork (from this repository) with stringifying functionality. You can write the manifest object back to a file.
To see what tags are supported in stringifying see this section. I will develop this package to support more tags in the future. Any PR is welcome.
m3u8 parser
- m3u8-parser
Installation
npm install --save @miadabdi/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",
"#EXTINF:6,",
"2.ts",
"#EXT-X-ENDLIST",
].join("\n");
var parser = new m3u8Parser.Parser();
parser.push(manifest);
parser.end();
var parsedManifest = parser.manifest;
Parsed Output
The parser ouputs a plain javascript object with the following structure:
Manifest {
allowCache: boolean,
endList: boolean,
mediaSequence: number,
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: [
{
byterange: {
length: number,
offset: number
},
duration: 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: {}
}
]
}
Stringify
To stringify a manifest object call stringify
method. You can directly write the string to a file.
const stringified = parser.stringify();
NOTE: encryption for Widevine is not supported in stringifying
Supported Tags
Basic Playlist Tags
Media Segment Tags
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
Master 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
Stringifying supported tag
- #EXTM3U
- #EXT-X-ALLOW-CACHE
- #EXT-X-VERSION
- #EXT-X-MEDIA
- #EXT-X-STREAM-INF
- #EXT-X-TARGETDURATION
- #EXT-X-MEDIA-SEQUENCE
- #EXT-X-PLAYLIST-TYPE
- #EXTINF
- #EXT-X-ENDLIST
- #EXT-X-PROGRAM-DATE-TIME
- #EXT-X-BYTERANGE
- #EXT-X-DISCONTINUITY
- #EXT-X-DISCONTINUITY-SEQUENCE
- #EXT-X-START
- #EXT-X-KEY
- #EXT-X-MAP
- #EXT-X-INDEPENDENT-SEGMENTS
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