Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
m3u8-parser
Advanced tools
The m3u8-parser npm package is a library for parsing M3U8 files, which are used for HTTP Live Streaming (HLS). It allows you to parse M3U8 playlists and extract information such as segments, media sequences, and more.
Parsing M3U8 Playlists
This feature allows you to parse an M3U8 playlist string and convert it into a JavaScript object. The code sample demonstrates how to use the Parser class to parse a simple M3U8 string and log the resulting manifest object.
const { Parser } = require('m3u8-parser');
const parser = new Parser();
const m3u8String = '#EXTM3U\n#EXTINF:10,\nhttp://media.example.com/first.ts\n#EXTINF:10,\nhttp://media.example.com/second.ts\n#EXT-X-ENDLIST';
parser.push(m3u8String);
parser.end();
console.log(parser.manifest);
Extracting Segment Information
This feature allows you to extract information about individual segments from an M3U8 playlist. The code sample demonstrates how to parse an M3U8 string and then iterate over the segments to log their URI and duration.
const { Parser } = require('m3u8-parser');
const parser = new Parser();
const m3u8String = '#EXTM3U\n#EXTINF:10,\nhttp://media.example.com/first.ts\n#EXTINF:10,\nhttp://media.example.com/second.ts\n#EXT-X-ENDLIST';
parser.push(m3u8String);
parser.end();
const segments = parser.manifest.segments;
segments.forEach(segment => {
console.log(`URI: ${segment.uri}, Duration: ${segment.duration}`);
});
Handling Media Sequences
This feature allows you to handle media sequences in an M3U8 playlist. The code sample demonstrates how to parse an M3U8 string and log the media sequence number from the resulting manifest object.
const { Parser } = require('m3u8-parser');
const parser = new Parser();
const m3u8String = '#EXTM3U\n#EXT-X-MEDIA-SEQUENCE:1\n#EXTINF:10,\nhttp://media.example.com/first.ts\n#EXTINF:10,\nhttp://media.example.com/second.ts\n#EXT-X-ENDLIST';
parser.push(m3u8String);
parser.end();
console.log(`Media Sequence: ${parser.manifest.mediaSequence}`);
The hls-parser package is another library for parsing M3U8 playlists. It offers similar functionality to m3u8-parser, allowing you to parse playlists and extract segment information. However, it also provides additional features such as support for writing M3U8 playlists and more detailed error handling.
The m3u8 package is a comprehensive library for working with M3U8 files. It supports both parsing and generating M3U8 playlists, making it a more versatile option compared to m3u8-parser. It also includes features for handling encryption keys and other advanced HLS features.
The hls.js package is a JavaScript library that focuses on playing HLS streams in browsers. While it includes some parsing capabilities, its primary focus is on providing a robust HLS playback experience. It is more feature-rich in terms of playback options compared to m3u8-parser, but less focused on parsing alone.
m3u8 parser
npm install --save m3u8-parser
The npm installation is preferred, but Bower works, too.
bower install --save m3u8-parser
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;
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 using QUERYSTRING
rules with #EXT-X-DEFINE
.options.mainDefinitions
object An object of definitions from the main playlist. This is required if using IMPORT
rules with #EXT-X-DEFINE
.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: {}
}
]
}
m3u8-parser supports 3 additional Media Segment Tags not present in the HLS specification.
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.
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.'
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
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
To include m3u8-parser on your website or web application, use any of the following methods.
<script>
TagThis 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>
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();
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();
});
Apache-2.0. Copyright (c) Brightcove, Inc
FAQs
m3u8 parser
The npm package m3u8-parser receives a total of 282,285 weekly downloads. As such, m3u8-parser popularity was classified as popular.
We found that m3u8-parser demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 22 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.