npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

m3u8-parser

v7.2.0

Published

m3u8 parser

Downloads

2,096,005

Readme

m3u8-parser

Build Status Greenkeeper badge Slack Status

NPM

m3u8 parser

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&param_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.

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

Media Playlist Tags

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