1
0
forked from jchomaz/Vulture

Tracking de l'application VApp (IHM du jeu)

This commit is contained in:
2025-05-11 18:04:12 +02:00
commit 89e9db9b62
17763 changed files with 3718499 additions and 0 deletions

269
VApp/node_modules/m3u8-parser/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,269 @@
<a name="7.2.0"></a>
# [7.2.0](https://github.com/videojs/m3u8-parser/compare/v7.1.0...v7.2.0) (2024-08-21)
### Features
* add support for #EXT-X-DEFINE ([#185](https://github.com/videojs/m3u8-parser/issues/185)) ([ba6e7cb](https://github.com/videojs/m3u8-parser/commit/ba6e7cb))
* add support for #EXT-X-I-FRAME-STREAM-INF ([#171](https://github.com/videojs/m3u8-parser/issues/171)) ([990c6ce](https://github.com/videojs/m3u8-parser/commit/990c6ce)), closes [/datatracker.ietf.org/doc/html/rfc8216#section-4](https://github.com//datatracker.ietf.org/doc/html/rfc8216/issues/section-4) [/datatracker.ietf.org/doc/html/rfc8216#section-4](https://github.com//datatracker.ietf.org/doc/html/rfc8216/issues/section-4)
* add support for #EXT-X-I-FRAMES-ONLY ([#173](https://github.com/videojs/m3u8-parser/issues/173)) ([e5dbdb6](https://github.com/videojs/m3u8-parser/commit/e5dbdb6)), closes [/datatracker.ietf.org/doc/html/rfc8216#section-4](https://github.com//datatracker.ietf.org/doc/html/rfc8216/issues/section-4) [#171](https://github.com/videojs/m3u8-parser/issues/171)
### Chores
* add content-steering tag to readme ([#177](https://github.com/videojs/m3u8-parser/issues/177)) ([f8c9817](https://github.com/videojs/m3u8-parser/commit/f8c9817))
* update vhs-utils dependency ([#182](https://github.com/videojs/m3u8-parser/issues/182)) ([c060bc7](https://github.com/videojs/m3u8-parser/commit/c060bc7))
<a name="7.1.0"></a>
# [7.1.0](https://github.com/videojs/m3u8-parser/compare/v7.0.0...v7.1.0) (2023-08-07)
### Features
* parse content steering tags and attributes ([#176](https://github.com/videojs/m3u8-parser/issues/176)) ([42472c5](https://github.com/videojs/m3u8-parser/commit/42472c5))
### Bug Fixes
* add dateTimeObject and dateTimeString for backward compatibility ([#174](https://github.com/videojs/m3u8-parser/issues/174)) ([6944bb1](https://github.com/videojs/m3u8-parser/commit/6944bb1))
* merge dateRange tags with same IDs and no conflicting attributes ([#175](https://github.com/videojs/m3u8-parser/issues/175)) ([73d934c](https://github.com/videojs/m3u8-parser/commit/73d934c))
### Chores
* update v7.0.0 documentation ([#172](https://github.com/videojs/m3u8-parser/issues/172)) ([72da994](https://github.com/videojs/m3u8-parser/commit/72da994))
<a name="7.0.0"></a>
# [7.0.0](https://github.com/videojs/m3u8-parser/compare/v6.2.0...v7.0.0) (2023-07-10)
### Features
* Add PDT to each segment ([#168](https://github.com/videojs/m3u8-parser/issues/168)) ([e7c683f](https://github.com/videojs/m3u8-parser/commit/e7c683f))
* output segment title from EXTINF ([#158](https://github.com/videojs/m3u8-parser/issues/158)) ([4adaa2c](https://github.com/videojs/m3u8-parser/commit/4adaa2c))
### Documentation
* correct `customType` option name ([#147](https://github.com/videojs/m3u8-parser/issues/147)) ([4d3e6ce](https://github.com/videojs/m3u8-parser/commit/4d3e6ce))
### BREAKING CHANGES
* rename `daterange` to `dateRanges`
* remove `dateTimeObject` and `dateTimeString` from parsed segment and replaces it with `programDateTime` which represents the timestamp in milliseconds
<a name="6.2.0"></a>
# [6.2.0](https://github.com/videojs/m3u8-parser/compare/v6.1.0...v6.2.0) (2023-05-25)
### Features
* add independent-segments support ([#165](https://github.com/videojs/m3u8-parser/issues/165)) ([8c47d81](https://github.com/videojs/m3u8-parser/commit/8c47d81))
<a name="6.1.0"></a>
# [6.1.0](https://github.com/videojs/m3u8-parser/compare/v6.0.0...v6.1.0) (2023-05-12)
<a name="6.0.0"></a>
# [6.0.0](https://github.com/videojs/m3u8-parser/compare/v5.0.0...v6.0.0) (2022-09-27)
### Bug Fixes
* non standard tag match ([#156](https://github.com/videojs/m3u8-parser/issues/156)) ([8d56f30](https://github.com/videojs/m3u8-parser/commit/8d56f30)), closes [#22](https://github.com/videojs/m3u8-parser/issues/22)
### Chores
* don't run tests on version ([b84575f](https://github.com/videojs/m3u8-parser/commit/b84575f))
### BREAKING CHANGES
* Missing colon (:) tag delimiters are no longer supported
<a name="5.0.0"></a>
# [5.0.0](https://github.com/videojs/m3u8-parser/compare/v4.7.1...v5.0.0) (2022-08-19)
### Features
* parse FRAME-RATE as a number ([#150](https://github.com/videojs/m3u8-parser/issues/150)) ([d51e93f](https://github.com/videojs/m3u8-parser/commit/d51e93f))
### Chores
* do not run es-check on publish ([#153](https://github.com/videojs/m3u8-parser/issues/153)) ([4e0bc63](https://github.com/videojs/m3u8-parser/commit/4e0bc63))
* remove IE11 support ([#152](https://github.com/videojs/m3u8-parser/issues/152)) ([fc12241](https://github.com/videojs/m3u8-parser/commit/fc12241))
### BREAKING CHANGES
* Internet Explorer is no longer supported.
* parser changes an output type for 'FRAME-RATE'
attribute from a string to a number.
<a name="4.7.1"></a>
## [4.7.1](https://github.com/videojs/m3u8-parser/compare/v4.7.0...v4.7.1) (2022-04-05)
### Bug Fixes
* EXT-X-KEY support playready keyformat ([#143](https://github.com/videojs/m3u8-parser/issues/143)) ([4e7c9eb](https://github.com/videojs/m3u8-parser/commit/4e7c9eb))
* update vhs-utils to 3.0.5 for tizen 2.4 support ([#149](https://github.com/videojs/m3u8-parser/issues/149)) ([efce797](https://github.com/videojs/m3u8-parser/commit/efce797))
<a name="4.7.0"></a>
# [4.7.0](https://github.com/videojs/m3u8-parser/compare/v4.6.0...v4.7.0) (2021-05-19)
### Features
* add key property to init segment/map ([#141](https://github.com/videojs/m3u8-parser/issues/141)) ([ae5fa64](https://github.com/videojs/m3u8-parser/commit/ae5fa64))
### Bug Fixes
* ignore fairplay content protection ([#140](https://github.com/videojs/m3u8-parser/issues/140)) ([9f62c85](https://github.com/videojs/m3u8-parser/commit/9f62c85))
<a name="4.6.0"></a>
# [4.6.0](https://github.com/videojs/m3u8-parser/compare/v4.5.2...v4.6.0) (2021-03-04)
### Features
* add support for #EXT-X-PART ([#127](https://github.com/videojs/m3u8-parser/issues/127)) ([9f5a224](https://github.com/videojs/m3u8-parser/commit/9f5a224)), closes [/developer.apple.com/documentation/http_live_streaming/enabling_low-latency_hls#3282436](https://github.com//developer.apple.com/documentation/http_live_streaming/enabling_low-latency_hls/issues/3282436) [/tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-4](https://github.com//tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08/issues/section-4)
* add support for #EXT-X-PART-INF ([#126](https://github.com/videojs/m3u8-parser/issues/126)) ([985ab68](https://github.com/videojs/m3u8-parser/commit/985ab68)), closes [/developer.apple.com/documentation/http_live_streaming/enabling_low-latency_hls#3282434](https://github.com//developer.apple.com/documentation/http_live_streaming/enabling_low-latency_hls/issues/3282434) [/tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-4](https://github.com//tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08/issues/section-4)
* add support for #EXT-X-PRELOAD-HINT ([#123](https://github.com/videojs/m3u8-parser/issues/123)) ([4fd693a](https://github.com/videojs/m3u8-parser/commit/4fd693a)), closes [/developer.apple.com/documentation/http_live_streaming/enabling_low-latency_hls#3526694](https://github.com//developer.apple.com/documentation/http_live_streaming/enabling_low-latency_hls/issues/3526694) [/tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-4](https://github.com//tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08/issues/section-4)
* add support for #EXT-X-RENDITION-REPORT ([#124](https://github.com/videojs/m3u8-parser/issues/124)) ([03f4345](https://github.com/videojs/m3u8-parser/commit/03f4345)), closes [/developer.apple.com/documentation/http_live_streaming/enabling_low-latency_hls#3282435](https://github.com//developer.apple.com/documentation/http_live_streaming/enabling_low-latency_hls/issues/3282435) [/tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-4](https://github.com//tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08/issues/section-4)
* add support for #EXT-X-SERVER-CONTROL ([#121](https://github.com/videojs/m3u8-parser/issues/121)) ([7f82f53](https://github.com/videojs/m3u8-parser/commit/7f82f53)), closes [/developer.apple.com/documentation/http_live_streaming/enabling_low-latency_hls#3281374](https://github.com//developer.apple.com/documentation/http_live_streaming/enabling_low-latency_hls/issues/3281374) [/tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-4](https://github.com//tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08/issues/section-4)
* add support for #EXT-X-SKIP ([#122](https://github.com/videojs/m3u8-parser/issues/122)) ([9cebc86](https://github.com/videojs/m3u8-parser/commit/9cebc86)), closes [/developer.apple.com/documentation/http_live_streaming/enabling_low-latency_hls#3282433](https://github.com//developer.apple.com/documentation/http_live_streaming/enabling_low-latency_hls/issues/3282433) [/tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-4](https://github.com//tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08/issues/section-4)
* add version parsing and remove totalduration ([#135](https://github.com/videojs/m3u8-parser/issues/135)) ([98f0421](https://github.com/videojs/m3u8-parser/commit/98f0421))
* add warn/info triggers and defaults for ll-hls tags ([#131](https://github.com/videojs/m3u8-parser/issues/131)) ([4f4da3d](https://github.com/videojs/m3u8-parser/commit/4f4da3d))
* **llhls:** preloadSegment, associate parts/preloadHints with segments, unify byterange handling ([#137](https://github.com/videojs/m3u8-parser/issues/137)) ([2c2dffe](https://github.com/videojs/m3u8-parser/commit/2c2dffe))
### Chores
* lint fixtures ([#134](https://github.com/videojs/m3u8-parser/issues/134)) ([e09c7ed](https://github.com/videojs/m3u8-parser/commit/e09c7ed))
* remove unused and non-standard tag #ZEN-TOTAL-DURATION ([#133](https://github.com/videojs/m3u8-parser/issues/133)) ([fb3b629](https://github.com/videojs/m3u8-parser/commit/fb3b629))
* switch to rollup-plugin-data-files ([#130](https://github.com/videojs/m3u8-parser/issues/130)) ([8f69b45](https://github.com/videojs/m3u8-parser/commit/8f69b45))
### Code Refactoring
* llhls attributes to camel case ([#138](https://github.com/videojs/m3u8-parser/issues/138)) ([31ed052](https://github.com/videojs/m3u8-parser/commit/31ed052))
### Tests
* add llhls manifests for incoming features ([#125](https://github.com/videojs/m3u8-parser/issues/125)) ([0823ea8](https://github.com/videojs/m3u8-parser/commit/0823ea8))
* move tests around ([#129](https://github.com/videojs/m3u8-parser/issues/129)) ([e86dcae](https://github.com/videojs/m3u8-parser/commit/e86dcae))
<a name="4.5.2"></a>
## [4.5.2](https://github.com/videojs/m3u8-parser/compare/v4.5.1...v4.5.2) (2021-01-12)
### Bug Fixes
* cjs dist should import only cjs ([#120](https://github.com/videojs/m3u8-parser/issues/120)) ([a58149d](https://github.com/videojs/m3u8-parser/commit/a58149d))
<a name="4.5.1"></a>
## [4.5.1](https://github.com/videojs/m3u8-parser/compare/v4.5.0...v4.5.1) (2021-01-11)
### Chores
* update to vhs-utils[@3](https://github.com/3) ([#118](https://github.com/videojs/m3u8-parser/issues/118)) ([f701c0f](https://github.com/videojs/m3u8-parser/commit/f701c0f))
<a name="4.5.0"></a>
# [4.5.0](https://github.com/videojs/m3u8-parser/compare/v4.4.3...v4.5.0) (2020-11-03)
### Chores
* **package:** update to vhs-utils[@2](https://github.com/2) ([#117](https://github.com/videojs/m3u8-parser/issues/117)) ([57ac9d2](https://github.com/videojs/m3u8-parser/commit/57ac9d2))
<a name="4.4.3"></a>
## [4.4.3](https://github.com/videojs/m3u8-parser/compare/v4.4.2...v4.4.3) (2020-08-12)
### Bug Fixes
* fix default EXT-X-BYTERANGE offset to start after the previous segment ([#98](https://github.com/videojs/m3u8-parser/issues/98)) ([08aca73](https://github.com/videojs/m3u8-parser/commit/08aca73))
### Tests
* run tests on node ([#97](https://github.com/videojs/m3u8-parser/issues/97)) ([4ad5c2d](https://github.com/videojs/m3u8-parser/commit/4ad5c2d))
<a name="4.4.2"></a>
## [4.4.2](https://github.com/videojs/m3u8-parser/compare/v4.4.1...v4.4.2) (2019-08-30)
### Chores
* **package:** update [@videojs](https://github.com/videojs)/vhs-utils ([651b4ae](https://github.com/videojs/m3u8-parser/commit/651b4ae))
<a name="4.4.1"></a>
## [4.4.1](https://github.com/videojs/m3u8-parser/compare/v4.4.0...v4.4.1) (2019-08-21)
### Chores
* update generator version and use [@videojs](https://github.com/videojs)/vhs-utils ([#95](https://github.com/videojs/m3u8-parser/issues/95)) ([7985794](https://github.com/videojs/m3u8-parser/commit/7985794))
<a name="4.4.0"></a>
# [4.4.0](https://github.com/videojs/m3u8-parser/compare/v4.3.0...v4.4.0) (2019-06-25)
### Features
* parse key attributes for Widevine HLS ([#88](https://github.com/videojs/m3u8-parser/issues/88)) ([d835fa8](https://github.com/videojs/m3u8-parser/commit/d835fa8))
### Chores
* **package:** update all dev dependencies ([#89](https://github.com/videojs/m3u8-parser/issues/89)) ([e991447](https://github.com/videojs/m3u8-parser/commit/e991447))
<a name="4.3.0"></a>
# [4.3.0](https://github.com/videojs/m3u8-parser/compare/v4.2.0...v4.3.0) (2019-01-10)
### Features
* custom tag mapping ([#73](https://github.com/videojs/m3u8-parser/issues/73)) ([0ef040a](https://github.com/videojs/m3u8-parser/commit/0ef040a))
### Chores
* Update to plugin generator 7 standards ([#53](https://github.com/videojs/m3u8-parser/issues/53)) ([35ff471](https://github.com/videojs/m3u8-parser/commit/35ff471))
* **package:** update rollup to version 0.66.0 ([#55](https://github.com/videojs/m3u8-parser/issues/55)) ([2407466](https://github.com/videojs/m3u8-parser/commit/2407466))
* Update videojs-generate-karma-config to the latest version 🚀 ([#59](https://github.com/videojs/m3u8-parser/issues/59)) ([023c6c9](https://github.com/videojs/m3u8-parser/commit/023c6c9))
* Update videojs-generate-karma-config to the latest version 🚀 ([#60](https://github.com/videojs/m3u8-parser/issues/60)) ([2773819](https://github.com/videojs/m3u8-parser/commit/2773819))
* Update videojs-generate-rollup-config to the latest version 🚀 ([#58](https://github.com/videojs/m3u8-parser/issues/58)) ([8c28a8b](https://github.com/videojs/m3u8-parser/commit/8c28a8b))
<a name="4.2.0"></a>
# [4.2.0](https://github.com/videojs/m3u8-parser/compare/v4.1.0...v4.2.0) (2018-02-23)
### Features
* add program-date-time tag info to parsed segments ([#27](https://github.com/videojs/m3u8-parser/issues/27)) ([44fc6f8](https://github.com/videojs/m3u8-parser/commit/44fc6f8))
<a name="4.1.0"></a>
# [4.1.0](https://github.com/videojs/m3u8-parser/compare/v4.0.0...v4.1.0) (2018-01-24)
<a name="4.0.0"></a>
# [4.0.0](https://github.com/videojs/m3u8-parser/compare/v3.0.0...v4.0.0) (2017-11-21)
### Features
* added ability to parse EXT-X-START tags [#31](https://github.com/videojs/m3u8-parser/pull/31)
### BREAKING CHANGES
* camel case module name in rollup config to work with latest rollup [#32](https://github.com/videojs/m3u8-parser/pull/32)
<a name="3.0.0"></a>
# 3.0.0 (2017-06-09)
### Features
* Rollup ([#24](https://github.com/videojs/m3u8-parser/issues/24)) ([47ef11f](https://github.com/videojs/m3u8-parser/commit/47ef11f))
### BREAKING CHANGES
* drop bower support.
## 2.1.0 (2017-02-23)
* parse FORCED attribute of media-groups [#15](https://github.com/videojs/m3u8-parser/pull/15)
* Pass any CHARACTERISTICS value of a track with the track object [#14](https://github.com/videojs/m3u8-parser/pull/14)
## 2.0.1 (2017-01-20)
* Fix: Include the babel ES3 tranform to support IE8 [#13](https://github.com/videojs/m3u8-parser/pull/13)
## 2.0.0 (2017-01-13)
* Manifest object is now initialized with an empty segments arrays
* moved to latest videojs-standard version, brought code into
compliance with the latest eslint rules.
## 1.0.2 (2016-06-07)
* fix the build pipeline
* removed video.js css/js inclusion during tests
## 1.0.1 (2016-06-07)
* remove dependence on video.js
* added contributors to package.json
## 1.0.0 (2016-06-03)
Initial Release

30
VApp/node_modules/m3u8-parser/CONTRIBUTING.md generated vendored Normal file
View File

@@ -0,0 +1,30 @@
# CONTRIBUTING
We welcome contributions from everyone!
## Getting Started
Make sure you have Node.js 4.8 or higher and npm installed.
1. Fork this repository and clone your fork
1. Install dependencies: `npm install`
1. Run a development server: `npm start`
### Making Changes
Refer to the [video.js plugin conventions][conventions] for more detail on best practices and tooling for video.js plugin authorship.
When you've made your changes, push your commit(s) to your fork and issue a pull request against the original repository.
### Running Tests
Testing is a crucial part of any software project. For all but the most trivial changes (typos, etc) test cases are expected. Tests are run in actual browsers using [Karma][karma].
- In all available and supported browsers: `npm test`
- In a specific browser: `npm run test:chrome`, `npm run test:firefox`, etc.
- While development server is running (`npm start`), navigate to [`http://localhost:9999/test/`][local]
[karma]: http://karma-runner.github.io/
[local]: http://localhost:9999/test/
[conventions]: https://github.com/videojs/generator-videojs-plugin/blob/master/docs/conventions.md

13
VApp/node_modules/m3u8-parser/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,13 @@
Copyright Brightcove, Inc
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

411
VApp/node_modules/m3u8-parser/README.md generated vendored Normal file
View File

@@ -0,0 +1,411 @@
# m3u8-parser
[![Build Status](https://travis-ci.org/videojs/m3u8-parser.svg?branch=master)](https://travis-ci.org/videojs/m3u8-parser)
[![Greenkeeper badge](https://badges.greenkeeper.io/videojs/m3u8-parser.svg)](https://greenkeeper.io/)
[![Slack Status](http://slack.videojs.com/badge.svg)](http://slack.videojs.com)
[![NPM](https://nodei.co/npm/m3u8-parser.png?downloads=true&downloadRank=true)](https://nodei.co/npm/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 -->
- [Installation](#installation)
- [Usage](#usage)
- [Constructor Options](#constructor-options)
- [Parsed Output](#parsed-output)
- [Supported Tags](#supported-tags)
- [Basic Playlist Tags](#basic-playlist-tags)
- [Media Segment Tags](#media-segment-tags)
- [Media Playlist Tags](#media-playlist-tags)
- [Main Playlist Tags](#main-playlist-tags)
- [Experimental Tags](#experimental-tags)
- [EXT-X-CUE-OUT](#ext-x-cue-out)
- [EXT-X-CUE-OUT-CONT](#ext-x-cue-out-cont)
- [EXT-X-CUE-IN](#ext-x-cue-in)
- [Not Yet Supported](#not-yet-supported)
- [Custom Parsers](#custom-parsers)
- [Including the Parser](#including-the-parser)
- [`<script>` Tag](#script-tag)
- [Browserify](#browserify)
- [RequireJS/AMD](#requirejsamd)
- [License](#license)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Installation
```sh
npm install --save m3u8-parser
```
The npm installation is preferred, but Bower works, too.
```sh
bower install --save m3u8-parser
```
## Usage
```js
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.
```js
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:
```js
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
* [EXTM3U](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.1.1)
* [EXT-X-VERSION](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.1.2)
### Media Segment Tags
* [EXTINF](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.2.1)
* [EXT-X-BYTERANGE](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.2.2)
* [EXT-X-DISCONTINUITY](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.2.3)
* [EXT-X-KEY](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.2.4)
* [EXT-X-MAP](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.2.5)
* [EXT-X-PROGRAM-DATE-TIME](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.2.6)
* [EXT-X-DATERANGE](https://datatracker.ietf.org/doc/html/draft-pantos-http-live-streaming-23#section-4.3.2.7)
* [EXT-X-I-FRAMES-ONLY](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.3.6)
### Media Playlist Tags
* [EXT-X-TARGETDURATION](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.3.1)
* [EXT-X-MEDIA-SEQUENCE](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.3.2)
* [EXT-X-DISCONTINUITY-SEQUENCE](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.3.3)
* [EXT-X-ENDLIST](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.3.4)
* [EXT-X-PLAYLIST-TYPE](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.3.5)
* [EXT-X-START](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.5.2)
* [EXT-X-INDEPENDENT-SEGMENTS](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.5.1)
* [EXT-X-DEFINE](https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis#section-4.4.2.3)
### Main Playlist Tags
* [EXT-X-MEDIA](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.4.1)
* [EXT-X-STREAM-INF](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.4.2)
* [EXT-X-I-FRAME-STREAM-INF](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.4.3)
* [EXT-X-CONTENT-STEERING](https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis#section-4.4.6.6)
* [EXT-X-DEFINE](https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis#section-4.4.2.3)
### 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
* [EXT-X-SESSION-DATA](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.4.4)
* [EXT-X-SESSION-KEY](http://tools.ietf.org/html/draft-pantos-http-live-streaming#section-4.3.4.5)
### 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.
```js
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.
```js
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.
```js
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.
```js
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.
```html
<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.
```js
var m3u8Parser = require('m3u8-parser');
var parser = new m3u8Parser.Parser();
```
With ES6:
```js
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:
```js
require(['m3u8-parser'], function(m3u8Parser) {
var parser = new m3u8Parser.Parser();
});
```
## License
Apache-2.0. Copyright (c) Brightcove, Inc

1907
VApp/node_modules/m3u8-parser/dist/m3u8-parser.cjs.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

1895
VApp/node_modules/m3u8-parser/dist/m3u8-parser.es.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

2059
VApp/node_modules/m3u8-parser/dist/m3u8-parser.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

15
VApp/node_modules/m3u8-parser/index.html generated vendored Normal file
View File

@@ -0,0 +1,15 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>m3u8-parser Demo</title>
</head>
<body>
<p>Open dev tools to try it out</p>
<ul>
<li><a href="test/debug.html">Run unit tests in browser.</a></li>
<li><a href="docs/api/">Read generated docs.</a></li>
</ul>
<script src="dist/m3u8-parser.js"></script>
</body>
</html>

95
VApp/node_modules/m3u8-parser/package.json generated vendored Normal file
View File

@@ -0,0 +1,95 @@
{
"name": "m3u8-parser",
"version": "7.2.0",
"description": "m3u8 parser",
"main": "dist/m3u8-parser.cjs.js",
"module": "dist/m3u8-parser.es.js",
"repository": {
"type": "git",
"url": "git@github.com:videojs/m3u8-parser.git"
},
"contributors": [
{
"name": "gkatsev",
"github": "https://github.com/gkatsev"
},
{
"name": "imbcmdth",
"github": "https://github.com/imbcmdth"
},
{
"name": "dmlap",
"github": "https://github.com/dmlap"
}
],
"scripts": {
"build-test": "cross-env-shell TEST_BUNDLE_ONLY=1 'npm run build'",
"build-prod": "cross-env-shell NO_TEST_BUNDLE=1 'npm run build'",
"build": "npm-run-all -s clean -p build:*",
"build:js": "rollup -c scripts/rollup.config.js",
"clean": "shx rm -rf ./dist ./test/dist && shx mkdir -p ./dist ./test/dist",
"lint": "vjsstandard",
"prepublishOnly": "npm-run-all build-prod && vjsverify --verbose --skip-es-check",
"start": "npm-run-all -p server watch",
"server": "karma start scripts/karma.conf.js --singleRun=false --auto-watch",
"test": "npm-run-all lint build-test test:*",
"test:browser": "karma start scripts/karma.conf.js",
"test:node": "qunit test/dist/bundle.js",
"posttest": "shx cat test/dist/coverage/text.txt",
"version": "is-prerelease || npm run update-changelog && git add CHANGELOG.md",
"update-changelog": "conventional-changelog -p videojs -i CHANGELOG.md -s",
"watch": "npm-run-all -p watch:*",
"watch:js": "npm run build:js -- -w"
},
"keywords": [
"videojs",
"videojs-plugin"
],
"author": "Brightcove, Inc",
"license": "Apache-2.0",
"vjsstandard": {
"ignore": [
"dist",
"docs",
"test/dist"
]
},
"files": [
"CONTRIBUTING.md",
"dist/",
"docs/",
"index.html",
"scripts/",
"src/",
"test/"
],
"dependencies": {
"@babel/runtime": "^7.12.5",
"@videojs/vhs-utils": "^4.1.1",
"global": "^4.4.0"
},
"devDependencies": {
"@rollup/plugin-replace": "^2.3.4",
"@videojs/generator-helpers": "~2.0.1",
"karma": "^5.2.3",
"rollup": "^2.38.0",
"rollup-plugin-data-files": "^0.1.0",
"sinon": "^9.2.3",
"videojs-generate-karma-config": "^8.0.1",
"videojs-generate-rollup-config": "~7.0.0",
"videojs-generator-verify": "~3.0.1",
"videojs-standard": "^8.0.4"
},
"generator-videojs-plugin": {
"version": "7.7.3"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.js": "vjsstandard --fix",
"README.md": "doctoc --notitle"
}
}

12
VApp/node_modules/m3u8-parser/scripts/karma.conf.js generated vendored Normal file
View File

@@ -0,0 +1,12 @@
const generate = require('videojs-generate-karma-config');
module.exports = function(config) {
// see https://github.com/videojs/videojs-generate-karma-config
// for options
const options = {};
config = generate(config, options);
// any other custom stuff not supported by options here!
};

47
VApp/node_modules/m3u8-parser/scripts/rollup.config.js generated vendored Normal file
View File

@@ -0,0 +1,47 @@
const generate = require('videojs-generate-rollup-config');
const replace = require('@rollup/plugin-replace');
const dataFiles = require('rollup-plugin-data-files');
// see https://github.com/videojs/videojs-generate-rollup-config
// for options
const options = {
input: 'src/index.js',
externals(defaults) {
defaults.module.push('@videojs/vhs-utils');
return defaults;
},
primedPlugins(defaults) {
// when using "require" rather than import
// require cjs module
defaults.replace = replace({
// single quote replace
"require('@videojs/vhs-utils/es": "require('@videojs/vhs-utils/cjs",
// double quote replace
'require("@videojs/vhs-utils/es': 'require("@videojs/vhs-utils/cjs'
});
defaults.dataFiles = dataFiles({
expecteds: {include: 'test/fixtures/integration/*.js', transform: 'js', extensions: false},
manifests: {include: 'test/fixtures/integration/*.m3u8', transform: 'string', extensions: false}
});
return defaults;
},
plugins(defaults) {
defaults.module.unshift('replace');
defaults.test.unshift('dataFiles');
return defaults;
}
};
const config = generate(options);
if (config.builds.test) {
config.builds.test.output[0].format = 'umd';
}
// Add additonal builds/customization here!
// export the builds to rollup
export default Object.values(config.builds);

19
VApp/node_modules/m3u8-parser/src/index.js generated vendored Normal file
View File

@@ -0,0 +1,19 @@
/**
* @file m3u8/index.js
*
* Utilities for parsing M3U8 files. If the entire manifest is available,
* `Parser` will create an object representation with enough detail for managing
* playback. `ParseStream` and `LineStream` are lower-level parsing primitives
* that do not assume the entirety of the manifest is ready and expose a
* ReadableStream-like interface.
*/
import LineStream from './line-stream';
import ParseStream from './parse-stream';
import Parser from './parser';
export {
LineStream,
ParseStream,
Parser
};

35
VApp/node_modules/m3u8-parser/src/line-stream.js generated vendored Normal file
View File

@@ -0,0 +1,35 @@
/**
* @file m3u8/line-stream.js
*/
import Stream from '@videojs/vhs-utils/es/stream.js';
/**
* A stream that buffers string input and generates a `data` event for each
* line.
*
* @class LineStream
* @extends Stream
*/
export default class LineStream extends Stream {
constructor() {
super();
this.buffer = '';
}
/**
* Add new data to be parsed.
*
* @param {string} data the text to process
*/
push(data) {
let nextNewline;
this.buffer += data;
nextNewline = this.buffer.indexOf('\n');
for (; nextNewline > -1; nextNewline = this.buffer.indexOf('\n')) {
this.trigger('data', this.buffer.substring(0, nextNewline));
this.buffer = this.buffer.substring(nextNewline + 1);
}
}
}

761
VApp/node_modules/m3u8-parser/src/parse-stream.js generated vendored Normal file
View File

@@ -0,0 +1,761 @@
/**
* @file m3u8/parse-stream.js
*/
import Stream from '@videojs/vhs-utils/es/stream.js';
const TAB = String.fromCharCode(0x09);
const parseByterange = function(byterangeString) {
// optionally match and capture 0+ digits before `@`
// optionally match and capture 0+ digits after `@`
const match = /([0-9.]*)?@?([0-9.]*)?/.exec(byterangeString || '');
const result = {};
if (match[1]) {
result.length = parseInt(match[1], 10);
}
if (match[2]) {
result.offset = parseInt(match[2], 10);
}
return result;
};
/**
* "forgiving" attribute list psuedo-grammar:
* attributes -> keyvalue (',' keyvalue)*
* keyvalue -> key '=' value
* key -> [^=]*
* value -> '"' [^"]* '"' | [^,]*
*/
const attributeSeparator = function() {
const key = '[^=]*';
const value = '"[^"]*"|[^,]*';
const keyvalue = '(?:' + key + ')=(?:' + value + ')';
return new RegExp('(?:^|,)(' + keyvalue + ')');
};
/**
* Parse attributes from a line given the separator
*
* @param {string} attributes the attribute line to parse
*/
const parseAttributes = function(attributes) {
const result = {};
if (!attributes) {
return result;
}
// split the string using attributes as the separator
const attrs = attributes.split(attributeSeparator());
let i = attrs.length;
let attr;
while (i--) {
// filter out unmatched portions of the string
if (attrs[i] === '') {
continue;
}
// split the key and value
attr = (/([^=]*)=(.*)/).exec(attrs[i]).slice(1);
// trim whitespace and remove optional quotes around the value
attr[0] = attr[0].replace(/^\s+|\s+$/g, '');
attr[1] = attr[1].replace(/^\s+|\s+$/g, '');
attr[1] = attr[1].replace(/^['"](.*)['"]$/g, '$1');
result[attr[0]] = attr[1];
}
return result;
};
/**
* Converts a string into a resolution object
*
* @param {string} resolution a string such as 3840x2160
*
* @return {Object} An object representing the resolution
*
*/
const parseResolution = (resolution) => {
const split = resolution.split('x');
const result = {};
if (split[0]) {
result.width = parseInt(split[0], 10);
}
if (split[1]) {
result.height = parseInt(split[1], 10);
}
return result;
};
/**
* A line-level M3U8 parser event stream. It expects to receive input one
* line at a time and performs a context-free parse of its contents. A stream
* interpretation of a manifest can be useful if the manifest is expected to
* be too large to fit comfortably into memory or the entirety of the input
* is not immediately available. Otherwise, it's probably much easier to work
* with a regular `Parser` object.
*
* Produces `data` events with an object that captures the parser's
* interpretation of the input. That object has a property `tag` that is one
* of `uri`, `comment`, or `tag`. URIs only have a single additional
* property, `line`, which captures the entirety of the input without
* interpretation. Comments similarly have a single additional property
* `text` which is the input without the leading `#`.
*
* Tags always have a property `tagType` which is the lower-cased version of
* the M3U8 directive without the `#EXT` or `#EXT-X-` prefix. For instance,
* `#EXT-X-MEDIA-SEQUENCE` becomes `media-sequence` when parsed. Unrecognized
* tags are given the tag type `unknown` and a single additional property
* `data` with the remainder of the input.
*
* @class ParseStream
* @extends Stream
*/
export default class ParseStream extends Stream {
constructor() {
super();
this.customParsers = [];
this.tagMappers = [];
}
/**
* Parses an additional line of input.
*
* @param {string} line a single line of an M3U8 file to parse
*/
push(line) {
let match;
let event;
// strip whitespace
line = line.trim();
if (line.length === 0) {
// ignore empty lines
return;
}
// URIs
if (line[0] !== '#') {
this.trigger('data', {
type: 'uri',
uri: line
});
return;
}
// map tags
const newLines = this.tagMappers.reduce((acc, mapper) => {
const mappedLine = mapper(line);
// skip if unchanged
if (mappedLine === line) {
return acc;
}
return acc.concat([mappedLine]);
}, [line]);
newLines.forEach(newLine => {
for (let i = 0; i < this.customParsers.length; i++) {
if (this.customParsers[i].call(this, newLine)) {
return;
}
}
// Comments
if (newLine.indexOf('#EXT') !== 0) {
this.trigger('data', {
type: 'comment',
text: newLine.slice(1)
});
return;
}
// strip off any carriage returns here so the regex matching
// doesn't have to account for them.
newLine = newLine.replace('\r', '');
// Tags
match = (/^#EXTM3U/).exec(newLine);
if (match) {
this.trigger('data', {
type: 'tag',
tagType: 'm3u'
});
return;
}
match = (/^#EXTINF:([0-9\.]*)?,?(.*)?$/).exec(newLine);
if (match) {
event = {
type: 'tag',
tagType: 'inf'
};
if (match[1]) {
event.duration = parseFloat(match[1]);
}
if (match[2]) {
event.title = match[2];
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-TARGETDURATION:([0-9.]*)?/).exec(newLine);
if (match) {
event = {
type: 'tag',
tagType: 'targetduration'
};
if (match[1]) {
event.duration = parseInt(match[1], 10);
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-VERSION:([0-9.]*)?/).exec(newLine);
if (match) {
event = {
type: 'tag',
tagType: 'version'
};
if (match[1]) {
event.version = parseInt(match[1], 10);
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-MEDIA-SEQUENCE:(\-?[0-9.]*)?/).exec(newLine);
if (match) {
event = {
type: 'tag',
tagType: 'media-sequence'
};
if (match[1]) {
event.number = parseInt(match[1], 10);
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-DISCONTINUITY-SEQUENCE:(\-?[0-9.]*)?/).exec(newLine);
if (match) {
event = {
type: 'tag',
tagType: 'discontinuity-sequence'
};
if (match[1]) {
event.number = parseInt(match[1], 10);
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-PLAYLIST-TYPE:(.*)?$/).exec(newLine);
if (match) {
event = {
type: 'tag',
tagType: 'playlist-type'
};
if (match[1]) {
event.playlistType = match[1];
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-BYTERANGE:(.*)?$/).exec(newLine);
if (match) {
event = Object.assign(parseByterange(match[1]), {
type: 'tag',
tagType: 'byterange'
});
this.trigger('data', event);
return;
}
match = (/^#EXT-X-ALLOW-CACHE:(YES|NO)?/).exec(newLine);
if (match) {
event = {
type: 'tag',
tagType: 'allow-cache'
};
if (match[1]) {
event.allowed = !(/NO/).test(match[1]);
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-MAP:(.*)$/).exec(newLine);
if (match) {
event = {
type: 'tag',
tagType: 'map'
};
if (match[1]) {
const attributes = parseAttributes(match[1]);
if (attributes.URI) {
event.uri = attributes.URI;
}
if (attributes.BYTERANGE) {
event.byterange = parseByterange(attributes.BYTERANGE);
}
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-STREAM-INF:(.*)$/).exec(newLine);
if (match) {
event = {
type: 'tag',
tagType: 'stream-inf'
};
if (match[1]) {
event.attributes = parseAttributes(match[1]);
if (event.attributes.RESOLUTION) {
event.attributes.RESOLUTION = parseResolution(event.attributes.RESOLUTION);
}
if (event.attributes.BANDWIDTH) {
event.attributes.BANDWIDTH = parseInt(event.attributes.BANDWIDTH, 10);
}
if (event.attributes['FRAME-RATE']) {
event.attributes['FRAME-RATE'] = parseFloat(event.attributes['FRAME-RATE']);
}
if (event.attributes['PROGRAM-ID']) {
event.attributes['PROGRAM-ID'] = parseInt(event.attributes['PROGRAM-ID'], 10);
}
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-MEDIA:(.*)$/).exec(newLine);
if (match) {
event = {
type: 'tag',
tagType: 'media'
};
if (match[1]) {
event.attributes = parseAttributes(match[1]);
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-ENDLIST/).exec(newLine);
if (match) {
this.trigger('data', {
type: 'tag',
tagType: 'endlist'
});
return;
}
match = (/^#EXT-X-DISCONTINUITY/).exec(newLine);
if (match) {
this.trigger('data', {
type: 'tag',
tagType: 'discontinuity'
});
return;
}
match = (/^#EXT-X-PROGRAM-DATE-TIME:(.*)$/).exec(newLine);
if (match) {
event = {
type: 'tag',
tagType: 'program-date-time'
};
if (match[1]) {
event.dateTimeString = match[1];
event.dateTimeObject = new Date(match[1]);
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-KEY:(.*)$/).exec(newLine);
if (match) {
event = {
type: 'tag',
tagType: 'key'
};
if (match[1]) {
event.attributes = parseAttributes(match[1]);
// parse the IV string into a Uint32Array
if (event.attributes.IV) {
if (event.attributes.IV.substring(0, 2).toLowerCase() === '0x') {
event.attributes.IV = event.attributes.IV.substring(2);
}
event.attributes.IV = event.attributes.IV.match(/.{8}/g);
event.attributes.IV[0] = parseInt(event.attributes.IV[0], 16);
event.attributes.IV[1] = parseInt(event.attributes.IV[1], 16);
event.attributes.IV[2] = parseInt(event.attributes.IV[2], 16);
event.attributes.IV[3] = parseInt(event.attributes.IV[3], 16);
event.attributes.IV = new Uint32Array(event.attributes.IV);
}
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-START:(.*)$/).exec(newLine);
if (match) {
event = {
type: 'tag',
tagType: 'start'
};
if (match[1]) {
event.attributes = parseAttributes(match[1]);
event.attributes['TIME-OFFSET'] = parseFloat(event.attributes['TIME-OFFSET']);
event.attributes.PRECISE = (/YES/).test(event.attributes.PRECISE);
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-CUE-OUT-CONT:(.*)?$/).exec(newLine);
if (match) {
event = {
type: 'tag',
tagType: 'cue-out-cont'
};
if (match[1]) {
event.data = match[1];
} else {
event.data = '';
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-CUE-OUT:(.*)?$/).exec(newLine);
if (match) {
event = {
type: 'tag',
tagType: 'cue-out'
};
if (match[1]) {
event.data = match[1];
} else {
event.data = '';
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-CUE-IN:?(.*)?$/).exec(newLine);
if (match) {
event = {
type: 'tag',
tagType: 'cue-in'
};
if (match[1]) {
event.data = match[1];
} else {
event.data = '';
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-SKIP:(.*)$/).exec(newLine);
if (match && match[1]) {
event = {
type: 'tag',
tagType: 'skip'
};
event.attributes = parseAttributes(match[1]);
if (event.attributes.hasOwnProperty('SKIPPED-SEGMENTS')) {
event.attributes['SKIPPED-SEGMENTS'] = parseInt(event.attributes['SKIPPED-SEGMENTS'], 10);
}
if (event.attributes.hasOwnProperty('RECENTLY-REMOVED-DATERANGES')) {
event.attributes['RECENTLY-REMOVED-DATERANGES'] =
event.attributes['RECENTLY-REMOVED-DATERANGES'].split(TAB);
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-PART:(.*)$/).exec(newLine);
if (match && match[1]) {
event = {
type: 'tag',
tagType: 'part'
};
event.attributes = parseAttributes(match[1]);
['DURATION'].forEach(function(key) {
if (event.attributes.hasOwnProperty(key)) {
event.attributes[key] = parseFloat(event.attributes[key]);
}
});
['INDEPENDENT', 'GAP'].forEach(function(key) {
if (event.attributes.hasOwnProperty(key)) {
event.attributes[key] = (/YES/).test(event.attributes[key]);
}
});
if (event.attributes.hasOwnProperty('BYTERANGE')) {
event.attributes.byterange = parseByterange(event.attributes.BYTERANGE);
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-SERVER-CONTROL:(.*)$/).exec(newLine);
if (match && match[1]) {
event = {
type: 'tag',
tagType: 'server-control'
};
event.attributes = parseAttributes(match[1]);
['CAN-SKIP-UNTIL', 'PART-HOLD-BACK', 'HOLD-BACK'].forEach(function(key) {
if (event.attributes.hasOwnProperty(key)) {
event.attributes[key] = parseFloat(event.attributes[key]);
}
});
['CAN-SKIP-DATERANGES', 'CAN-BLOCK-RELOAD'].forEach(function(key) {
if (event.attributes.hasOwnProperty(key)) {
event.attributes[key] = (/YES/).test(event.attributes[key]);
}
});
this.trigger('data', event);
return;
}
match = (/^#EXT-X-PART-INF:(.*)$/).exec(newLine);
if (match && match[1]) {
event = {
type: 'tag',
tagType: 'part-inf'
};
event.attributes = parseAttributes(match[1]);
['PART-TARGET'].forEach(function(key) {
if (event.attributes.hasOwnProperty(key)) {
event.attributes[key] = parseFloat(event.attributes[key]);
}
});
this.trigger('data', event);
return;
}
match = (/^#EXT-X-PRELOAD-HINT:(.*)$/).exec(newLine);
if (match && match[1]) {
event = {
type: 'tag',
tagType: 'preload-hint'
};
event.attributes = parseAttributes(match[1]);
['BYTERANGE-START', 'BYTERANGE-LENGTH'].forEach(function(key) {
if (event.attributes.hasOwnProperty(key)) {
event.attributes[key] = parseInt(event.attributes[key], 10);
const subkey = key === 'BYTERANGE-LENGTH' ? 'length' : 'offset';
event.attributes.byterange = event.attributes.byterange || {};
event.attributes.byterange[subkey] = event.attributes[key];
// only keep the parsed byterange object.
delete event.attributes[key];
}
});
this.trigger('data', event);
return;
}
match = (/^#EXT-X-RENDITION-REPORT:(.*)$/).exec(newLine);
if (match && match[1]) {
event = {
type: 'tag',
tagType: 'rendition-report'
};
event.attributes = parseAttributes(match[1]);
['LAST-MSN', 'LAST-PART'].forEach(function(key) {
if (event.attributes.hasOwnProperty(key)) {
event.attributes[key] = parseInt(event.attributes[key], 10);
}
});
this.trigger('data', event);
return;
}
match = (/^#EXT-X-DATERANGE:(.*)$/).exec(newLine);
if (match && match[1]) {
event = {
type: 'tag',
tagType: 'daterange'
};
event.attributes = parseAttributes(match[1]);
['ID', 'CLASS'].forEach(function(key) {
if (event.attributes.hasOwnProperty(key)) {
event.attributes[key] = String(event.attributes[key]);
}
});
['START-DATE', 'END-DATE'].forEach(function(key) {
if (event.attributes.hasOwnProperty(key)) {
event.attributes[key] = new Date(event.attributes[key]);
}
});
['DURATION', 'PLANNED-DURATION'].forEach(function(key) {
if (event.attributes.hasOwnProperty(key)) {
event.attributes[key] = parseFloat(event.attributes[key]);
}
});
['END-ON-NEXT'].forEach(function(key) {
if (event.attributes.hasOwnProperty(key)) {
event.attributes[key] = (/YES/i).test(event.attributes[key]);
}
});
['SCTE35-CMD', ' SCTE35-OUT', 'SCTE35-IN'].forEach(function(key) {
if (event.attributes.hasOwnProperty(key)) {
event.attributes[key] = event.attributes[key].toString(16);
}
});
const clientAttributePattern = /^X-([A-Z]+-)+[A-Z]+$/;
for (const key in event.attributes) {
if (!clientAttributePattern.test(key)) {
continue;
}
const isHexaDecimal = (/[0-9A-Fa-f]{6}/g).test(event.attributes[key]);
const isDecimalFloating = (/^\d+(\.\d+)?$/).test(event.attributes[key]);
event.attributes[key] = isHexaDecimal ? event.attributes[key].toString(16) : isDecimalFloating ? parseFloat(event.attributes[key]) : String(event.attributes[key]);
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-INDEPENDENT-SEGMENTS/).exec(newLine);
if (match) {
this.trigger('data', {
type: 'tag',
tagType: 'independent-segments'
});
return;
}
match = (/^#EXT-X-I-FRAMES-ONLY/).exec(newLine);
if (match) {
this.trigger('data', {
type: 'tag',
tagType: 'i-frames-only'
});
return;
}
match = (/^#EXT-X-CONTENT-STEERING:(.*)$/).exec(newLine);
if (match) {
event = {
type: 'tag',
tagType: 'content-steering'
};
event.attributes = parseAttributes(match[1]);
this.trigger('data', event);
return;
}
match = (/^#EXT-X-I-FRAME-STREAM-INF:(.*)$/).exec(newLine);
if (match) {
event = {
type: 'tag',
tagType: 'i-frame-playlist'
};
event.attributes = parseAttributes(match[1]);
if (event.attributes.URI) {
event.uri = event.attributes.URI;
}
if (event.attributes.BANDWIDTH) {
event.attributes.BANDWIDTH = parseInt(event.attributes.BANDWIDTH, 10);
}
if (event.attributes.RESOLUTION) {
event.attributes.RESOLUTION = parseResolution(event.attributes.RESOLUTION);
}
if (event.attributes['AVERAGE-BANDWIDTH']) {
event.attributes['AVERAGE-BANDWIDTH'] = parseInt(event.attributes['AVERAGE-BANDWIDTH'], 10);
}
if (event.attributes['FRAME-RATE']) {
event.attributes['FRAME-RATE'] = parseFloat(event.attributes['FRAME-RATE']);
}
this.trigger('data', event);
return;
}
match = (/^#EXT-X-DEFINE:(.*)$/).exec(newLine);
if (match) {
event = {
type: 'tag',
tagType: 'define'
};
event.attributes = parseAttributes(match[1]);
this.trigger('data', event);
return;
}
// unknown tag type
this.trigger('data', {
type: 'tag',
data: newLine.slice(4)
});
});
}
/**
* Add a parser for custom headers
*
* @param {Object} options a map of options for the added parser
* @param {RegExp} options.expression a regular expression to match the custom header
* @param {string} options.customType the custom type to register to the output
* @param {Function} [options.dataParser] function to parse the line into an object
* @param {boolean} [options.segment] should tag data be attached to the segment object
*/
addParser({expression, customType, dataParser, segment}) {
if (typeof dataParser !== 'function') {
dataParser = (line) => line;
}
this.customParsers.push(line => {
const match = expression.exec(line);
if (match) {
this.trigger('data', {
type: 'custom',
data: dataParser(line),
customType,
segment
});
return true;
}
});
}
/**
* Add a custom header mapper
*
* @param {Object} options
* @param {RegExp} options.expression a regular expression to match the custom header
* @param {Function} options.map function to translate tag into a different tag
*/
addTagMapper({expression, map}) {
const mapFn = line => {
if (expression.test(line)) {
return map(line);
}
return line;
};
this.tagMappers.push(mapFn);
}
}

991
VApp/node_modules/m3u8-parser/src/parser.js generated vendored Normal file
View File

@@ -0,0 +1,991 @@
/**
* @file m3u8/parser.js
*/
import Stream from '@videojs/vhs-utils/es/stream.js';
import decodeB64ToUint8Array from '@videojs/vhs-utils/es/decode-b64-to-uint8-array.js';
import LineStream from './line-stream';
import ParseStream from './parse-stream';
const camelCase = (str) => str
.toLowerCase()
.replace(/-(\w)/g, (a) => a[1].toUpperCase());
const camelCaseKeys = function(attributes) {
const result = {};
Object.keys(attributes).forEach(function(key) {
result[camelCase(key)] = attributes[key];
});
return result;
};
// set SERVER-CONTROL hold back based upon targetDuration and partTargetDuration
// we need this helper because defaults are based upon targetDuration and
// partTargetDuration being set, but they may not be if SERVER-CONTROL appears before
// target durations are set.
const setHoldBack = function(manifest) {
const {serverControl, targetDuration, partTargetDuration} = manifest;
if (!serverControl) {
return;
}
const tag = '#EXT-X-SERVER-CONTROL';
const hb = 'holdBack';
const phb = 'partHoldBack';
const minTargetDuration = targetDuration && targetDuration * 3;
const minPartDuration = partTargetDuration && partTargetDuration * 2;
if (targetDuration && !serverControl.hasOwnProperty(hb)) {
serverControl[hb] = minTargetDuration;
this.trigger('info', {
message: `${tag} defaulting HOLD-BACK to targetDuration * 3 (${minTargetDuration}).`
});
}
if (minTargetDuration && serverControl[hb] < minTargetDuration) {
this.trigger('warn', {
message: `${tag} clamping HOLD-BACK (${serverControl[hb]}) to targetDuration * 3 (${minTargetDuration})`
});
serverControl[hb] = minTargetDuration;
}
// default no part hold back to part target duration * 3
if (partTargetDuration && !serverControl.hasOwnProperty(phb)) {
serverControl[phb] = partTargetDuration * 3;
this.trigger('info', {
message: `${tag} defaulting PART-HOLD-BACK to partTargetDuration * 3 (${serverControl[phb]}).`
});
}
// if part hold back is too small default it to part target duration * 2
if (partTargetDuration && serverControl[phb] < (minPartDuration)) {
this.trigger('warn', {
message: `${tag} clamping PART-HOLD-BACK (${serverControl[phb]}) to partTargetDuration * 2 (${minPartDuration}).`
});
serverControl[phb] = minPartDuration;
}
};
/**
* A parser for M3U8 files. The current interpretation of the input is
* exposed as a property `manifest` on parser objects. It's just two lines to
* create and parse a manifest once you have the contents available as a string:
*
* ```js
* var parser = new m3u8.Parser();
* parser.push(xhr.responseText);
* ```
*
* New input can later be applied to update the manifest object by calling
* `push` again.
*
* The parser attempts to create a usable manifest object even if the
* underlying input is somewhat nonsensical. It emits `info` and `warning`
* events during the parse if it encounters input that seems invalid or
* requires some property of the manifest object to be defaulted.
*
* @class Parser
* @param {Object} [opts] Options for the constructor, needed for substitutions
* @param {string} [opts.uri] URL to check for query params
* @param {Object} [opts.mainDefinitions] Definitions on main playlist that can be imported
* @extends Stream
*/
export default class Parser extends Stream {
constructor(opts = {}) {
super();
this.lineStream = new LineStream();
this.parseStream = new ParseStream();
this.lineStream.pipe(this.parseStream);
this.mainDefinitions = opts.mainDefinitions || {};
this.params = new URL(opts.uri, 'https://a.com').searchParams;
this.lastProgramDateTime = null;
/* eslint-disable consistent-this */
const self = this;
/* eslint-enable consistent-this */
const uris = [];
let currentUri = {};
// if specified, the active EXT-X-MAP definition
let currentMap;
// if specified, the active decryption key
let key;
let hasParts = false;
const noop = function() {};
const defaultMediaGroups = {
'AUDIO': {},
'VIDEO': {},
'CLOSED-CAPTIONS': {},
'SUBTITLES': {}
};
// This is the Widevine UUID from DASH IF IOP. The same exact string is
// used in MPDs with Widevine encrypted streams.
const widevineUuid = 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed';
// group segments into numbered timelines delineated by discontinuities
let currentTimeline = 0;
// the manifest is empty until the parse stream begins delivering data
this.manifest = {
allowCache: true,
discontinuityStarts: [],
dateRanges: [],
iFramePlaylists: [],
segments: []
};
// keep track of the last seen segment's byte range end, as segments are not required
// to provide the offset, in which case it defaults to the next byte after the
// previous segment
let lastByterangeEnd = 0;
// keep track of the last seen part's byte range end.
let lastPartByterangeEnd = 0;
const dateRangeTags = {};
this.on('end', () => {
// only add preloadSegment if we don't yet have a uri for it.
// and we actually have parts/preloadHints
if (currentUri.uri || (!currentUri.parts && !currentUri.preloadHints)) {
return;
}
if (!currentUri.map && currentMap) {
currentUri.map = currentMap;
}
if (!currentUri.key && key) {
currentUri.key = key;
}
if (!currentUri.timeline && typeof currentTimeline === 'number') {
currentUri.timeline = currentTimeline;
}
this.manifest.preloadSegment = currentUri;
});
// update the manifest with the m3u8 entry from the parse stream
this.parseStream.on('data', function(entry) {
let mediaGroup;
let rendition;
// Replace variables in uris and attributes as defined in #EXT-X-DEFINE tags
if (self.manifest.definitions) {
for (const def in self.manifest.definitions) {
if (entry.uri) {
entry.uri = entry.uri.replace(`{$${def}}`, self.manifest.definitions[def]);
}
if (entry.attributes) {
for (const attr in entry.attributes) {
if (typeof entry.attributes[attr] === 'string') {
entry.attributes[attr] = entry.attributes[attr].replace(`{$${def}}`, self.manifest.definitions[def]);
}
}
}
}
}
({
tag() {
// switch based on the tag type
(({
version() {
if (entry.version) {
this.manifest.version = entry.version;
}
},
'allow-cache'() {
this.manifest.allowCache = entry.allowed;
if (!('allowed' in entry)) {
this.trigger('info', {
message: 'defaulting allowCache to YES'
});
this.manifest.allowCache = true;
}
},
byterange() {
const byterange = {};
if ('length' in entry) {
currentUri.byterange = byterange;
byterange.length = entry.length;
if (!('offset' in entry)) {
/*
* From the latest spec (as of this writing):
* https://tools.ietf.org/html/draft-pantos-http-live-streaming-23#section-4.3.2.2
*
* Same text since EXT-X-BYTERANGE's introduction in draft 7:
* https://tools.ietf.org/html/draft-pantos-http-live-streaming-07#section-3.3.1)
*
* "If o [offset] is not present, the sub-range begins at the next byte
* following the sub-range of the previous media segment."
*/
entry.offset = lastByterangeEnd;
}
}
if ('offset' in entry) {
currentUri.byterange = byterange;
byterange.offset = entry.offset;
}
lastByterangeEnd = byterange.offset + byterange.length;
},
endlist() {
this.manifest.endList = true;
},
inf() {
if (!('mediaSequence' in this.manifest)) {
this.manifest.mediaSequence = 0;
this.trigger('info', {
message: 'defaulting media sequence to zero'
});
}
if (!('discontinuitySequence' in this.manifest)) {
this.manifest.discontinuitySequence = 0;
this.trigger('info', {
message: 'defaulting discontinuity sequence to zero'
});
}
if (entry.title) {
currentUri.title = entry.title;
}
if (entry.duration > 0) {
currentUri.duration = entry.duration;
}
if (entry.duration === 0) {
currentUri.duration = 0.01;
this.trigger('info', {
message: 'updating zero segment duration to a small value'
});
}
this.manifest.segments = uris;
},
key() {
if (!entry.attributes) {
this.trigger('warn', {
message: 'ignoring key declaration without attribute list'
});
return;
}
// clear the active encryption key
if (entry.attributes.METHOD === 'NONE') {
key = null;
return;
}
if (!entry.attributes.URI) {
this.trigger('warn', {
message: 'ignoring key declaration without URI'
});
return;
}
if (entry.attributes.KEYFORMAT === 'com.apple.streamingkeydelivery') {
this.manifest.contentProtection = this.manifest.contentProtection || {};
// TODO: add full support for this.
this.manifest.contentProtection['com.apple.fps.1_0'] = {
attributes: entry.attributes
};
return;
}
if (entry.attributes.KEYFORMAT === 'com.microsoft.playready') {
this.manifest.contentProtection = this.manifest.contentProtection || {};
// TODO: add full support for this.
this.manifest.contentProtection['com.microsoft.playready'] = {
uri: entry.attributes.URI
};
return;
}
// check if the content is encrypted for Widevine
// Widevine/HLS spec: https://storage.googleapis.com/wvdocs/Widevine_DRM_HLS.pdf
if (entry.attributes.KEYFORMAT === widevineUuid) {
const VALID_METHODS = ['SAMPLE-AES', 'SAMPLE-AES-CTR', 'SAMPLE-AES-CENC'];
if (VALID_METHODS.indexOf(entry.attributes.METHOD) === -1) {
this.trigger('warn', {
message: 'invalid key method provided for Widevine'
});
return;
}
if (entry.attributes.METHOD === 'SAMPLE-AES-CENC') {
this.trigger('warn', {
message: 'SAMPLE-AES-CENC is deprecated, please use SAMPLE-AES-CTR instead'
});
}
if (entry.attributes.URI.substring(0, 23) !== 'data:text/plain;base64,') {
this.trigger('warn', {
message: 'invalid key URI provided for Widevine'
});
return;
}
if (!(entry.attributes.KEYID && entry.attributes.KEYID.substring(0, 2) === '0x')) {
this.trigger('warn', {
message: 'invalid key ID provided for Widevine'
});
return;
}
// if Widevine key attributes are valid, store them as `contentProtection`
// on the manifest to emulate Widevine tag structure in a DASH mpd
this.manifest.contentProtection = this.manifest.contentProtection || {};
this.manifest.contentProtection['com.widevine.alpha'] = {
attributes: {
schemeIdUri: entry.attributes.KEYFORMAT,
// remove '0x' from the key id string
keyId: entry.attributes.KEYID.substring(2)
},
// decode the base64-encoded PSSH box
pssh: decodeB64ToUint8Array(entry.attributes.URI.split(',')[1])
};
return;
}
if (!entry.attributes.METHOD) {
this.trigger('warn', {
message: 'defaulting key method to AES-128'
});
}
// setup an encryption key for upcoming segments
key = {
method: entry.attributes.METHOD || 'AES-128',
uri: entry.attributes.URI
};
if (typeof entry.attributes.IV !== 'undefined') {
key.iv = entry.attributes.IV;
}
},
'media-sequence'() {
if (!isFinite(entry.number)) {
this.trigger('warn', {
message: 'ignoring invalid media sequence: ' + entry.number
});
return;
}
this.manifest.mediaSequence = entry.number;
},
'discontinuity-sequence'() {
if (!isFinite(entry.number)) {
this.trigger('warn', {
message: 'ignoring invalid discontinuity sequence: ' + entry.number
});
return;
}
this.manifest.discontinuitySequence = entry.number;
currentTimeline = entry.number;
},
'playlist-type'() {
if (!(/VOD|EVENT/).test(entry.playlistType)) {
this.trigger('warn', {
message: 'ignoring unknown playlist type: ' + entry.playlist
});
return;
}
this.manifest.playlistType = entry.playlistType;
},
map() {
currentMap = {};
if (entry.uri) {
currentMap.uri = entry.uri;
}
if (entry.byterange) {
currentMap.byterange = entry.byterange;
}
if (key) {
currentMap.key = key;
}
},
'stream-inf'() {
this.manifest.playlists = uris;
this.manifest.mediaGroups =
this.manifest.mediaGroups || defaultMediaGroups;
if (!entry.attributes) {
this.trigger('warn', {
message: 'ignoring empty stream-inf attributes'
});
return;
}
if (!currentUri.attributes) {
currentUri.attributes = {};
}
Object.assign(currentUri.attributes, entry.attributes);
},
media() {
this.manifest.mediaGroups =
this.manifest.mediaGroups || defaultMediaGroups;
if (!(entry.attributes &&
entry.attributes.TYPE &&
entry.attributes['GROUP-ID'] &&
entry.attributes.NAME)) {
this.trigger('warn', {
message: 'ignoring incomplete or missing media group'
});
return;
}
// find the media group, creating defaults as necessary
const mediaGroupType = this.manifest.mediaGroups[entry.attributes.TYPE];
mediaGroupType[entry.attributes['GROUP-ID']] =
mediaGroupType[entry.attributes['GROUP-ID']] || {};
mediaGroup = mediaGroupType[entry.attributes['GROUP-ID']];
// collect the rendition metadata
rendition = {
default: (/yes/i).test(entry.attributes.DEFAULT)
};
if (rendition.default) {
rendition.autoselect = true;
} else {
rendition.autoselect = (/yes/i).test(entry.attributes.AUTOSELECT);
}
if (entry.attributes.LANGUAGE) {
rendition.language = entry.attributes.LANGUAGE;
}
if (entry.attributes.URI) {
rendition.uri = entry.attributes.URI;
}
if (entry.attributes['INSTREAM-ID']) {
rendition.instreamId = entry.attributes['INSTREAM-ID'];
}
if (entry.attributes.CHARACTERISTICS) {
rendition.characteristics = entry.attributes.CHARACTERISTICS;
}
if (entry.attributes.FORCED) {
rendition.forced = (/yes/i).test(entry.attributes.FORCED);
}
// insert the new rendition
mediaGroup[entry.attributes.NAME] = rendition;
},
discontinuity() {
currentTimeline += 1;
currentUri.discontinuity = true;
this.manifest.discontinuityStarts.push(uris.length);
},
'program-date-time'() {
if (typeof this.manifest.dateTimeString === 'undefined') {
// PROGRAM-DATE-TIME is a media-segment tag, but for backwards
// compatibility, we add the first occurence of the PROGRAM-DATE-TIME tag
// to the manifest object
// TODO: Consider removing this in future major version
this.manifest.dateTimeString = entry.dateTimeString;
this.manifest.dateTimeObject = entry.dateTimeObject;
}
currentUri.dateTimeString = entry.dateTimeString;
currentUri.dateTimeObject = entry.dateTimeObject;
const { lastProgramDateTime } = this;
this.lastProgramDateTime = new Date(entry.dateTimeString).getTime();
// We should extrapolate Program Date Time backward only during first program date time occurrence.
// Once we have at least one program date time point, we can always extrapolate it forward using lastProgramDateTime reference.
if (lastProgramDateTime === null) {
// Extrapolate Program Date Time backward
// Since it is first program date time occurrence we're assuming that
// all this.manifest.segments have no program date time info
this.manifest.segments.reduceRight((programDateTime, segment) => {
segment.programDateTime = programDateTime - (segment.duration * 1000);
return segment.programDateTime;
}, this.lastProgramDateTime);
}
},
targetduration() {
if (!isFinite(entry.duration) || entry.duration < 0) {
this.trigger('warn', {
message: 'ignoring invalid target duration: ' + entry.duration
});
return;
}
this.manifest.targetDuration = entry.duration;
setHoldBack.call(this, this.manifest);
},
start() {
if (!entry.attributes || isNaN(entry.attributes['TIME-OFFSET'])) {
this.trigger('warn', {
message: 'ignoring start declaration without appropriate attribute list'
});
return;
}
this.manifest.start = {
timeOffset: entry.attributes['TIME-OFFSET'],
precise: entry.attributes.PRECISE
};
},
'cue-out'() {
currentUri.cueOut = entry.data;
},
'cue-out-cont'() {
currentUri.cueOutCont = entry.data;
},
'cue-in'() {
currentUri.cueIn = entry.data;
},
'skip'() {
this.manifest.skip = camelCaseKeys(entry.attributes);
this.warnOnMissingAttributes_(
'#EXT-X-SKIP',
entry.attributes,
['SKIPPED-SEGMENTS']
);
},
'part'() {
hasParts = true;
// parts are always specifed before a segment
const segmentIndex = this.manifest.segments.length;
const part = camelCaseKeys(entry.attributes);
currentUri.parts = currentUri.parts || [];
currentUri.parts.push(part);
if (part.byterange) {
if (!part.byterange.hasOwnProperty('offset')) {
part.byterange.offset = lastPartByterangeEnd;
}
lastPartByterangeEnd = part.byterange.offset + part.byterange.length;
}
const partIndex = currentUri.parts.length - 1;
this.warnOnMissingAttributes_(
`#EXT-X-PART #${partIndex} for segment #${segmentIndex}`,
entry.attributes,
['URI', 'DURATION']
);
if (this.manifest.renditionReports) {
this.manifest.renditionReports.forEach((r, i) => {
if (!r.hasOwnProperty('lastPart')) {
this.trigger('warn', {
message: `#EXT-X-RENDITION-REPORT #${i} lacks required attribute(s): LAST-PART`
});
}
});
}
},
'server-control'() {
const attrs = this.manifest.serverControl = camelCaseKeys(entry.attributes);
if (!attrs.hasOwnProperty('canBlockReload')) {
attrs.canBlockReload = false;
this.trigger('info', {
message: '#EXT-X-SERVER-CONTROL defaulting CAN-BLOCK-RELOAD to false'
});
}
setHoldBack.call(this, this.manifest);
if (attrs.canSkipDateranges && !attrs.hasOwnProperty('canSkipUntil')) {
this.trigger('warn', {
message: '#EXT-X-SERVER-CONTROL lacks required attribute CAN-SKIP-UNTIL which is required when CAN-SKIP-DATERANGES is set'
});
}
},
'preload-hint'() {
// parts are always specifed before a segment
const segmentIndex = this.manifest.segments.length;
const hint = camelCaseKeys(entry.attributes);
const isPart = hint.type && hint.type === 'PART';
currentUri.preloadHints = currentUri.preloadHints || [];
currentUri.preloadHints.push(hint);
if (hint.byterange) {
if (!hint.byterange.hasOwnProperty('offset')) {
// use last part byterange end or zero if not a part.
hint.byterange.offset = isPart ? lastPartByterangeEnd : 0;
if (isPart) {
lastPartByterangeEnd = hint.byterange.offset + hint.byterange.length;
}
}
}
const index = currentUri.preloadHints.length - 1;
this.warnOnMissingAttributes_(
`#EXT-X-PRELOAD-HINT #${index} for segment #${segmentIndex}`,
entry.attributes,
['TYPE', 'URI']
);
if (!hint.type) {
return;
}
// search through all preload hints except for the current one for
// a duplicate type.
for (let i = 0; i < currentUri.preloadHints.length - 1; i++) {
const otherHint = currentUri.preloadHints[i];
if (!otherHint.type) {
continue;
}
if (otherHint.type === hint.type) {
this.trigger('warn', {
message: `#EXT-X-PRELOAD-HINT #${index} for segment #${segmentIndex} has the same TYPE ${hint.type} as preload hint #${i}`
});
}
}
},
'rendition-report'() {
const report = camelCaseKeys(entry.attributes);
this.manifest.renditionReports = this.manifest.renditionReports || [];
this.manifest.renditionReports.push(report);
const index = this.manifest.renditionReports.length - 1;
const required = ['LAST-MSN', 'URI'];
if (hasParts) {
required.push('LAST-PART');
}
this.warnOnMissingAttributes_(
`#EXT-X-RENDITION-REPORT #${index}`,
entry.attributes,
required
);
},
'part-inf'() {
this.manifest.partInf = camelCaseKeys(entry.attributes);
this.warnOnMissingAttributes_(
'#EXT-X-PART-INF',
entry.attributes,
['PART-TARGET']
);
if (this.manifest.partInf.partTarget) {
this.manifest.partTargetDuration = this.manifest.partInf.partTarget;
}
setHoldBack.call(this, this.manifest);
},
'daterange'() {
this.manifest.dateRanges.push(camelCaseKeys(entry.attributes));
const index = this.manifest.dateRanges.length - 1;
this.warnOnMissingAttributes_(
`#EXT-X-DATERANGE #${index}`,
entry.attributes,
['ID', 'START-DATE']
);
const dateRange = this.manifest.dateRanges[index];
if (dateRange.endDate && dateRange.startDate && new Date(dateRange.endDate) < new Date(dateRange.startDate)) {
this.trigger('warn', {
message: 'EXT-X-DATERANGE END-DATE must be equal to or later than the value of the START-DATE'
});
}
if (dateRange.duration && dateRange.duration < 0) {
this.trigger('warn', {
message: 'EXT-X-DATERANGE DURATION must not be negative'
});
}
if (dateRange.plannedDuration && dateRange.plannedDuration < 0) {
this.trigger('warn', {
message: 'EXT-X-DATERANGE PLANNED-DURATION must not be negative'
});
}
const endOnNextYes = !!dateRange.endOnNext;
if (endOnNextYes && !dateRange.class) {
this.trigger('warn', {
message: 'EXT-X-DATERANGE with an END-ON-NEXT=YES attribute must have a CLASS attribute'
});
}
if (endOnNextYes && (dateRange.duration || dateRange.endDate)) {
this.trigger('warn', {
message: 'EXT-X-DATERANGE with an END-ON-NEXT=YES attribute must not contain DURATION or END-DATE attributes'
});
}
if (dateRange.duration && dateRange.endDate) {
const startDate = dateRange.startDate;
const newDateInSeconds = startDate.getTime() + (dateRange.duration * 1000);
this.manifest.dateRanges[index].endDate = new Date(newDateInSeconds);
}
if (!dateRangeTags[dateRange.id]) {
dateRangeTags[dateRange.id] = dateRange;
} else {
for (const attribute in dateRangeTags[dateRange.id]) {
if (!!dateRange[attribute] && JSON.stringify(dateRangeTags[dateRange.id][attribute]) !== JSON.stringify(dateRange[attribute])) {
this.trigger('warn', {
message: 'EXT-X-DATERANGE tags with the same ID in a playlist must have the same attributes values'
});
break;
}
}
// if tags with the same ID do not have conflicting attributes, merge them
const dateRangeWithSameId = this.manifest.dateRanges.findIndex((dateRangeToFind) => dateRangeToFind.id === dateRange.id);
this.manifest.dateRanges[dateRangeWithSameId] = Object.assign(this.manifest.dateRanges[dateRangeWithSameId], dateRange);
dateRangeTags[dateRange.id] = Object.assign(dateRangeTags[dateRange.id], dateRange);
// after merging, delete the duplicate dateRange that was added last
this.manifest.dateRanges.pop();
}
},
'independent-segments'() {
this.manifest.independentSegments = true;
},
'i-frames-only'() {
this.manifest.iFramesOnly = true;
this.requiredCompatibilityversion(this.manifest.version, 4);
},
'content-steering'() {
this.manifest.contentSteering = camelCaseKeys(entry.attributes);
this.warnOnMissingAttributes_(
'#EXT-X-CONTENT-STEERING',
entry.attributes,
['SERVER-URI']
);
},
/** @this {Parser} */
define() {
this.manifest.definitions = this.manifest.definitions || { };
const addDef = (n, v) => {
if (n in this.manifest.definitions) {
// An EXT-X-DEFINE tag MUST NOT specify the same Variable Name as any other
// EXT-X-DEFINE tag in the same Playlist. Parsers that encounter duplicate
// Variable Name declarations MUST fail to parse the Playlist.
this.trigger('error', {
message: `EXT-X-DEFINE: Duplicate name ${n}`
});
return;
}
this.manifest.definitions[n] = v;
};
if ('QUERYPARAM' in entry.attributes) {
if ('NAME' in entry.attributes || 'IMPORT' in entry.attributes) {
// An EXT-X-DEFINE tag MUST contain either a NAME, an IMPORT, or a
// QUERYPARAM attribute, but only one of the three. Otherwise, the
// client MUST fail to parse the Playlist.
this.trigger('error', {
message: 'EXT-X-DEFINE: Invalid attributes'
});
return;
}
const val = this.params.get(entry.attributes.QUERYPARAM);
if (!val) {
// If the QUERYPARAM attribute value does not match any query parameter in
// the URI or the matching parameter has no associated value, the parser
// MUST fail to parse the Playlist. If more than one parameter matches,
// any of the associated values MAY be used.
this.trigger('error', {
message: `EXT-X-DEFINE: No query param ${entry.attributes.QUERYPARAM}`
});
return;
}
addDef(entry.attributes.QUERYPARAM, decodeURIComponent(val));
return;
}
if ('NAME' in entry.attributes) {
if ('IMPORT' in entry.attributes) {
// An EXT-X-DEFINE tag MUST contain either a NAME, an IMPORT, or a
// QUERYPARAM attribute, but only one of the three. Otherwise, the
// client MUST fail to parse the Playlist.
this.trigger('error', {
message: 'EXT-X-DEFINE: Invalid attributes'
});
return;
}
if (!('VALUE' in entry.attributes) || typeof entry.attributes.VALUE !== 'string') {
// This attribute is REQUIRED if the EXT-X-DEFINE tag has a NAME attribute.
// The quoted-string MAY be empty.
this.trigger('error', {
message: `EXT-X-DEFINE: No value for ${entry.attributes.NAME}`
});
return;
}
addDef(entry.attributes.NAME, entry.attributes.VALUE);
return;
}
if ('IMPORT' in entry.attributes) {
if (!this.mainDefinitions[entry.attributes.IMPORT]) {
// Covers two conditions, as mainDefinitions will always be empty on main
//
// EXT-X-DEFINE tags containing the IMPORT attribute MUST NOT occur in
// Multivariant Playlists; they are only allowed in Media Playlists.
//
// If the IMPORT attribute value does not match any Variable Name in the
// Multivariant Playlist, or if the Media Playlist loaded from a
// Multivariant Playlist, the parser MUST fail the Playlist.
this.trigger('error', {
message: `EXT-X-DEFINE: No value ${entry.attributes.IMPORT} to import, or IMPORT used on main playlist`
});
return;
}
addDef(entry.attributes.IMPORT, this.mainDefinitions[entry.attributes.IMPORT]);
return;
}
// An EXT-X-DEFINE tag MUST contain either a NAME, an IMPORT, or a QUERYPARAM
// attribute, but only one of the three. Otherwise, the client MUST fail to
// parse the Playlist.
this.trigger('error', {
message: 'EXT-X-DEFINE: No attribute'
});
},
'i-frame-playlist'() {
this.manifest.iFramePlaylists.push({
attributes: entry.attributes,
uri: entry.uri,
timeline: currentTimeline
});
this.warnOnMissingAttributes_(
'#EXT-X-I-FRAME-STREAM-INF',
entry.attributes,
['BANDWIDTH', 'URI']
);
}
})[entry.tagType] || noop).call(self);
},
uri() {
currentUri.uri = entry.uri;
uris.push(currentUri);
// if no explicit duration was declared, use the target duration
if (this.manifest.targetDuration && !('duration' in currentUri)) {
this.trigger('warn', {
message: 'defaulting segment duration to the target duration'
});
currentUri.duration = this.manifest.targetDuration;
}
// annotate with encryption information, if necessary
if (key) {
currentUri.key = key;
}
currentUri.timeline = currentTimeline;
// annotate with initialization segment information, if necessary
if (currentMap) {
currentUri.map = currentMap;
}
// reset the last byterange end as it needs to be 0 between parts
lastPartByterangeEnd = 0;
// Once we have at least one program date time we can always extrapolate it forward
if (this.lastProgramDateTime !== null) {
currentUri.programDateTime = this.lastProgramDateTime;
this.lastProgramDateTime += currentUri.duration * 1000;
}
// prepare for the next URI
currentUri = {};
},
comment() {
// comments are not important for playback
},
custom() {
// if this is segment-level data attach the output to the segment
if (entry.segment) {
currentUri.custom = currentUri.custom || {};
currentUri.custom[entry.customType] = entry.data;
// if this is manifest-level data attach to the top level manifest object
} else {
this.manifest.custom = this.manifest.custom || {};
this.manifest.custom[entry.customType] = entry.data;
}
}
})[entry.type].call(self);
});
}
requiredCompatibilityversion(currentVersion, targetVersion) {
if (currentVersion < targetVersion || !currentVersion) {
this.trigger('warn', {
message: `manifest must be at least version ${targetVersion}`
});
}
}
warnOnMissingAttributes_(identifier, attributes, required) {
const missing = [];
required.forEach(function(key) {
if (!attributes.hasOwnProperty(key)) {
missing.push(key);
}
});
if (missing.length) {
this.trigger('warn', {message: `${identifier} lacks required attribute(s): ${missing.join(', ')}`});
}
}
/**
* Parse the input string and update the manifest object.
*
* @param {string} chunk a potentially incomplete portion of the manifest
*/
push(chunk) {
this.lineStream.push(chunk);
}
/**
* Flush any remaining input. This can be handy if the last line of an M3U8
* manifest did not contain a trailing newline but the file has been
* completely received.
*/
end() {
// flush any buffered input
this.lineStream.push('\n');
if (this.manifest.dateRanges.length && this.lastProgramDateTime === null) {
this.trigger('warn', {
message: 'A playlist with EXT-X-DATERANGE tag must contain atleast one EXT-X-PROGRAM-DATE-TIME tag'
});
}
this.lastProgramDateTime = null;
this.trigger('end');
}
/**
* Add an additional parser for non-standard tags
*
* @param {Object} options a map of options for the added parser
* @param {RegExp} options.expression a regular expression to match the custom header
* @param {string} options.customType the custom type to register to the output
* @param {Function} [options.dataParser] function to parse the line into an object
* @param {boolean} [options.segment] should tag data be attached to the segment object
*/
addParser(options) {
this.parseStream.addParser(options);
}
/**
* Add a custom header mapper
*
* @param {Object} options
* @param {RegExp} options.expression a regular expression to match the custom header
* @param {Function} options.map function to translate tag into a different tag
*/
addTagMapper(options) {
this.parseStream.addTagMapper(options);
}
}

View File

@@ -0,0 +1,33 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
{
duration: 10,
timeline: 0,
uri: 'http://example.com/00001.ts'
},
{
duration: 10,
timeline: 0,
uri: 'https://example.com/00002.ts'
},
{
duration: 10,
timeline: 0,
uri: '//example.com/00003.ts'
},
{
duration: 10,
timeline: 0,
uri: 'http://example.com/00004.ts'
}
],
targetDuration: 10,
endList: true,
discontinuitySequence: 0,
discontinuityStarts: []
};

View File

@@ -0,0 +1,12 @@
#EXTM3U
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-TARGETDURATION:10
#EXTINF:10,
http://example.com/00001.ts
#EXTINF:10,
https://example.com/00002.ts
#EXTINF:10,
//example.com/00003.ts
#EXTINF:10,
http://example.com/00004.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,167 @@
module.exports = {
allowCache: true,
iFramePlaylists: [],
mediaSequence: 0,
dateRanges: [],
playlistType: 'VOD',
segments: [
{
byterange: {
length: 522828,
offset: 0
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 587500,
offset: 522828
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 713084,
offset: 1110328
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 476580,
offset: 1823412
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 535612,
offset: 2299992
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 207176,
offset: 2835604
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 455900,
offset: 3042780
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 657248,
offset: 3498680
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 571708,
offset: 4155928
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 485040,
offset: 4727636
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 709136,
offset: 5212676
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 730004,
offset: 5921812
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 456276,
offset: 6651816
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 468684,
offset: 7108092
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 444996,
offset: 7576776
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 331444,
offset: 8021772
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 44556,
offset: 8353216
},
duration: 1.4167,
timeline: 0,
uri: 'hls_450k_video.ts'
}
],
targetDuration: 10,
endList: true,
discontinuitySequence: 0,
discontinuityStarts: [],
version: 4
};

View File

@@ -0,0 +1,58 @@
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:4
#EXT-X-ALLOW-CACHE:YES
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:10,
#EXT-X-BYTERANGE:522828@0
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:587500@522828
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:713084@1110328
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:476580@1823412
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:535612@2299992
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:207176@2835604
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:455900@3042780
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:657248@3498680
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:571708@4155928
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:485040@4727636
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:709136@5212676
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:730004@5921812
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:456276@6651816
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:468684@7108092
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:444996@7576776
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:331444@8021772
hls_450k_video.ts
#EXTINF:1.4167,
#EXT-X-BYTERANGE:44556@8353216
hls_450k_video.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,23 @@
module.exports = {
allowCache: true,
iFramePlaylists: [],
mediaSequence: 0,
dateRanges: [],
playlistType: 'VOD',
segments: [
{
byterange: {
length: 522828,
offset: 0
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
}
],
targetDuration: 10,
endList: true,
discontinuitySequence: 0,
discontinuityStarts: [],
version: 4
};

View File

@@ -0,0 +1,10 @@
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:4
#EXT-X-ALLOW-CACHE:0
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:10,
#EXT-X-BYTERANGE:522828@0
hls_450k_video.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,58 @@
module.exports = {
allowCache: true,
discontinuityStarts: [],
dateRanges: [],
iFramePlaylists: [],
mediaGroups: {
// TYPE
'AUDIO': {
// GROUP-ID
audio: {
// NAME
English: {
language: 'eng',
autoselect: true,
default: true,
uri: 'eng/prog_index.m3u8'
},
// NAME
Français: {
language: 'fre',
autoselect: true,
default: false,
uri: 'fre/prog_index.m3u8'
},
// NAME
Espanol: {
language: 'sp',
autoselect: true,
default: false,
uri: 'sp/prog_index.m3u8'
}
}
},
'VIDEO': {},
'CLOSED-CAPTIONS': {},
'SUBTITLES': {}
},
playlists: [{
attributes: {
'PROGRAM-ID': 1,
'BANDWIDTH': 195023,
'CODECS': 'avc1.42e00a,mp4a.40.2',
'AUDIO': 'audio'
},
timeline: 0,
uri: 'lo/prog_index.m3u8'
}, {
attributes: {
'PROGRAM-ID': 1,
'BANDWIDTH': 591680,
'CODECS': 'avc1.42e01e,mp4a.40.2',
'AUDIO': 'audio'
},
timeline: 0,
uri: 'hi/prog_index.m3u8'
}],
segments: []
};

View File

@@ -0,0 +1,9 @@
#EXTM3U
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",LANGUAGE="eng",NAME="English",AUTOSELECT=YES, DEFAULT=YES,URI="eng/prog_index.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",LANGUAGE="fre",NAME="Français",AUTOSELECT=YES, DEFAULT=NO,URI="fre/prog_index.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",LANGUAGE="sp",NAME="Espanol",AUTOSELECT=YES, DEFAULT=NO,URI="sp/prog_index.m3u8"
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=195023,CODECS="avc1.42e00a,mp4a.40.2",AUDIO="audio"
lo/prog_index.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=591680,CODECS="avc1.42e01e,mp4a.40.2",AUDIO="audio"
hi/prog_index.m3u8

View File

@@ -0,0 +1,50 @@
module.exports = {
allowCache: true,
discontinuityStarts: [],
dateRanges: [],
iFramePlaylists: [],
mediaGroups: {
'AUDIO': {
aac: {
English: {
autoselect: true,
default: true,
language: 'eng',
uri: 'eng/prog_index.m3u8'
}
}
},
'VIDEO': {
'500kbs': {
Angle1: {
autoselect: true,
default: true
},
Angle2: {
autoselect: true,
default: false,
uri: 'Angle2/500kbs/prog_index.m3u8'
},
Angle3: {
autoselect: true,
default: false,
uri: 'Angle3/500kbs/prog_index.m3u8'
}
}
},
'CLOSED-CAPTIONS': {},
'SUBTITLES': {}
},
playlists: [{
attributes: {
'PROGRAM-ID': 1,
'BANDWIDTH': 754857,
'CODECS': 'mp4a.40.2,avc1.4d401e',
'AUDIO': 'aac',
'VIDEO': '500kbs'
},
timeline: 0,
uri: 'Angle1/500kbs/prog_index.m3u8'
}],
segments: []
};

View File

@@ -0,0 +1,8 @@
#EXTM3U
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="500kbs",NAME="Angle1",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="500kbs",NAME="Angle2",AUTOSELECT=YES,DEFAULT=NO,URI="Angle2/500kbs/prog_index.m3u8"
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="500kbs",NAME="Angle3",AUTOSELECT=YES,DEFAULT=NO,URI="Angle3/500kbs/prog_index.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aac",LANGUAGE="eng",NAME="English",AUTOSELECT=YES,DEFAULT=YES,URI="eng/prog_index.m3u8"
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=754857,CODECS="mp4a.40.2,avc1.4d401e",VIDEO="500kbs",AUDIO="aac"
Angle1/500kbs/prog_index.m3u8

View File

@@ -0,0 +1,59 @@
module.exports = {
allowCache: true,
iFramePlaylists: [],
dateRanges: [],
playlists: [
{
attributes: {
'PROGRAM-ID': 1,
'BANDWIDTH': 240000,
'RESOLUTION': {
width: 396,
height: 224
}
},
timeline: 0,
uri: 'http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824686811001&videoId=1824650741001'
},
{
attributes: {
'PROGRAM-ID': 1,
'BANDWIDTH': 40000
},
timeline: 0,
uri: 'http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824683759001&videoId=1824650741001'
},
{
attributes: {
'PROGRAM-ID': 1,
'BANDWIDTH': 440000,
'RESOLUTION': {
width: 396,
height: 224
}
},
timeline: 0,
uri: 'http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824686593001&videoId=1824650741001'
},
{
attributes: {
'PROGRAM-ID': 1,
'BANDWIDTH': 1928000,
'RESOLUTION': {
width: 960,
height: 540
}
},
timeline: 0,
uri: 'http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824687660001&videoId=1824650741001'
}
],
discontinuityStarts: [],
mediaGroups: {
'VIDEO': {},
'AUDIO': {},
'CLOSED-CAPTIONS': {},
'SUBTITLES': {}
},
segments: []
};

View File

@@ -0,0 +1,9 @@
#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=240000,RESOLUTION=396x224
http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824686811001&videoId=1824650741001
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=40000
http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824683759001&videoId=1824650741001
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=440000,RESOLUTION=396x224
http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824686593001&videoId=1824650741001
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1928000,RESOLUTION=960x540
http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824687660001&videoId=1824650741001

View File

@@ -0,0 +1,163 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
{
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 587500,
offset: 522828
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 713084,
offset: 1110328
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video2.ts'
},
{
byterange: {
length: 476580,
offset: 1823412
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 535612,
offset: 2299992
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 207176,
offset: 2835604
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 455900,
offset: 3042780
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 657248,
offset: 3498680
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 571708,
offset: 4155928
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 485040,
offset: 4727636
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 709136,
offset: 5212676
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 730004,
offset: 5921812
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 456276,
offset: 6651816
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 468684,
offset: 7108092
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 444996,
offset: 7576776
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 331444,
offset: 8021772
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 44556,
offset: 8353216
},
duration: 1.4167,
timeline: 0,
uri: 'hls_450k_video.ts'
}
],
targetDuration: 10,
endList: true,
discontinuitySequence: 0,
discontinuityStarts: [],
version: 3
};

View File

@@ -0,0 +1,56 @@
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:10,
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:587500@522828
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:713084
hls_450k_video2.ts
#EXTINF:10,
#EXT-X-BYTERANGE:476580@1823412
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:535612@2299992
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:207176@2835604
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:455900@3042780
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:657248@3498680
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:571708@4155928
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:485040@4727636
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:709136@5212676
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:730004@5921812
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:456276@6651816
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:468684@7108092
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:444996@7576776
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:331444@8021772
hls_450k_video.ts
#EXTINF:1.4167,
#EXT-X-BYTERANGE:44556@8353216
hls_450k_video.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,31 @@
module.exports = {
allowCache: false,
iFramePlaylists: [],
mediaSequence: 0,
dateRanges: [],
playlistType: 'VOD',
segments: [
{
dateTimeString: '2016-06-22T09:20:16.166-04:00',
dateTimeObject: new Date('2016-06-22T09:20:16.166-04:00'),
programDateTime: 1466601616166,
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
dateTimeString: '2016-06-22T09:20:26.166-04:00',
dateTimeObject: new Date('2016-06-22T09:20:26.166-04:00'),
programDateTime: 1466601626166,
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
}
],
targetDuration: 10,
endList: true,
dateTimeString: '2016-06-22T09:20:16.166-04:00',
dateTimeObject: new Date('2016-06-22T09:20:16.166-04:00'),
discontinuitySequence: 0,
discontinuityStarts: []
};

View File

@@ -0,0 +1,12 @@
#EXTM3U
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:NO
#EXT-X-TARGETDURATION:10
#EXT-X-PROGRAM-DATE-TIME:2016-06-22T09:20:16.166-04:00
#EXTINF:10
hls_450k_video.ts
#EXT-X-PROGRAM-DATE-TIME:2016-06-22T09:20:26.166-04:00
#EXTINF:10
hls_450k_video.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,166 @@
module.exports = {
allowCache: true,
discontinuitySequence: 0,
discontinuityStarts: [],
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 7794,
segments: [
{
duration: 2.833,
key: {
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=52'
},
map: {
key: {
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=52'
},
uri: 'http://media.example.com/init52.mp4'
},
timeline: 0,
uri: 'http://media.example.com/fileSequence52-A.m4s'
},
{
duration: 15,
key: {
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=52'
},
map: {
key: {
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=52'
},
uri: 'http://media.example.com/init52.mp4'
},
timeline: 0,
uri: 'http://media.example.com/fileSequence52-B.m4s'
},
{
duration: 13.333,
key: {
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=52'
},
map: {
key: {
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=52'
},
uri: 'http://media.example.com/init52.mp4'
},
timeline: 0,
uri: 'http://media.example.com/fileSequence52-C.m4s'
},
{
duration: 15,
key: {
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=53'
},
map: {
key: {
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=53'
},
uri: 'http://media.example.com/init53-A.mp4'
},
timeline: 0,
uri: 'http://media.example.com/fileSequence53-A.m4s'
},
{
duration: 14,
key: {
iv: new Uint32Array([0, 0, 331, 3063767524]),
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=53'
},
map: {
key: {
iv: new Uint32Array([0, 0, 331, 3063767524]),
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=53'
},
uri: 'http://media.example.com/init53-B.mp4'
},
timeline: 0,
uri: 'http://media.example.com/fileSequence53-B.m4s'
},
{
duration: 12,
key: {
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=54'
},
map: {
uri: 'http://media.example.com/init54-A.mp4'
},
timeline: 0,
uri: 'http://media.example.com/fileSequence54-A.m4s'
},
{
duration: 13,
key: {
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=54'
},
map: {
uri: 'http://media.example.com/init54-A.mp4'
},
timeline: 0,
uri: 'http://media.example.com/fileSequence54-B.m4s'
},
{
duration: 10,
map: {
key: {
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=54'
},
uri: 'http://media.example.com/init54-B.mp4'
},
timeline: 0,
uri: 'http://media.example.com/fileSequence54-A.m4s'
},
{
duration: 11,
map: {
key: {
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=54'
},
uri: 'http://media.example.com/init54-B.mp4'
},
timeline: 0,
uri: 'http://media.example.com/fileSequence54-B.m4s'
},
{
duration: 4,
key: {
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=54-b'
},
map: {
key: {
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=54-a'
},
uri: 'http://media.example.com/init54-D.mp4'
},
timeline: 0,
uri: 'http://media.example.com/fileSequence54-A.m4s'
},
{
duration: 12,
map: {
uri: 'http://media.example.com/init54-E.mp4'
},
timeline: 0,
uri: 'http://media.example.com/fileSequence54-A.m4s'
}
],
targetDuration: 15,
version: 7
};

View File

@@ -0,0 +1,57 @@
#EXTM3U
#EXT-X-VERSION:7
#EXT-X-MEDIA-SEQUENCE:7794
#EXT-X-TARGETDURATION:15
#EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.php?r=52"
#EXT-X-MAP:URI="http://media.example.com/init52.mp4"
#EXTINF:2.833,
http://media.example.com/fileSequence52-A.m4s
#EXTINF:15.0,
http://media.example.com/fileSequence52-B.m4s
#EXTINF:13.333,
http://media.example.com/fileSequence52-C.m4s
#EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.php?r=53"
#EXT-X-MAP:URI="http://media.example.com/init53-A.mp4"
#EXTINF:15.0,
http://media.example.com/fileSequence53-A.m4s
#EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.php?r=53",IV=0x00000000000000000000014BB69D61E4
#EXT-X-MAP:URI="http://media.example.com/init53-B.mp4"
#EXTINF:14.0,
http://media.example.com/fileSequence53-B.m4s
#EXT-X-KEY:METHOD=NONE
#EXT-X-MAP:URI="http://media.example.com/init54-A.mp4"
#EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.php?r=54"
#EXTINF:12.0,
http://media.example.com/fileSequence54-A.m4s
#EXTINF:13.0,
http://media.example.com/fileSequence54-B.m4s
#EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.php?r=54"
#EXT-X-MAP:URI="http://media.example.com/init54-B.mp4"
#EXT-X-KEY:METHOD=NONE
#EXTINF:10.0,
http://media.example.com/fileSequence54-A.m4s
#EXTINF:11.0,
http://media.example.com/fileSequence54-B.m4s
#EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.php?r=54-a"
#EXT-X-MAP:URI="http://media.example.com/init54-D.mp4"
#EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.php?r=54-b"
#EXTINF:4.0,
http://media.example.com/fileSequence54-A.m4s
#EXT-X-KEY:METHOD=NONE
#EXT-X-MAP:URI="http://media.example.com/init54-E.mp4"
#EXTINF:12.0,
http://media.example.com/fileSequence54-A.m4s

View File

@@ -0,0 +1,23 @@
module.exports = {
allowCache: false,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
{
byterange: {
length: 522828,
offset: 0
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
}
],
targetDuration: 10,
endList: true,
discontinuitySequence: 0,
discontinuityStarts: [],
version: 4
};

View File

@@ -0,0 +1,10 @@
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:4
#EXT-X-ALLOW-CACHE:NO
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:10,
#EXT-X-BYTERANGE:522828@0
hls_450k_video.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,38 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
discontinuitySequence: 3,
segments: [
{
duration: 10,
timeline: 3,
uri: '001.ts',
title: '0'
},
{
duration: 19,
timeline: 3,
uri: '002.ts',
title: '0'
},
{
discontinuity: true,
duration: 10,
timeline: 4,
uri: '003.ts',
title: '0'
},
{
duration: 11,
timeline: 4,
uri: '004.ts',
title: '0'
}
],
targetDuration: 19,
endList: true,
discontinuityStarts: [2],
version: 3
};

View File

@@ -0,0 +1,15 @@
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:19
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-DISCONTINUITY-SEQUENCE:3
#EXTINF:10,0
001.ts
#EXTINF:19,0
002.ts
#EXT-X-DISCONTINUITY
#EXTINF:10,0
003.ts
#EXTINF:11,0
004.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,70 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
discontinuitySequence: 0,
segments: [
{
duration: 10,
timeline: 0,
uri: '001.ts',
title: '0'
},
{
duration: 19,
timeline: 0,
uri: '002.ts',
title: '0'
},
{
discontinuity: true,
duration: 10,
timeline: 1,
uri: '003.ts',
title: '0'
},
{
duration: 11,
timeline: 1,
uri: '004.ts',
title: '0'
},
{
discontinuity: true,
duration: 10,
timeline: 2,
uri: '005.ts',
title: '0'
},
{
duration: 10,
timeline: 2,
uri: '006.ts',
title: '0'
},
{
duration: 10,
timeline: 2,
uri: '007.ts',
title: '0'
},
{
discontinuity: true,
duration: 10,
timeline: 3,
uri: '008.ts',
title: '0'
},
{
duration: 16,
timeline: 3,
uri: '009.ts',
title: '0'
}
],
targetDuration: 19,
endList: true,
discontinuityStarts: [2, 4, 7],
version: 3
};

View File

@@ -0,0 +1,26 @@
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:19
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10,0
001.ts
#EXTINF:19,0
002.ts
#EXT-X-DISCONTINUITY
#EXTINF:10,0
003.ts
#EXTINF:11,0
004.ts
#EXT-X-DISCONTINUITY
#EXTINF:10,0
005.ts
#EXTINF:10,0
006.ts
#EXTINF:10,0
007.ts
#EXT-X-DISCONTINUITY
#EXTINF:10,0
008.ts
#EXTINF:16,0
009.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,33 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
{
duration: 10,
timeline: 0,
uri: '/00001.ts'
},
{
duration: 10,
timeline: 0,
uri: '/subdir/00002.ts'
},
{
duration: 10,
timeline: 0,
uri: '/00003.ts'
},
{
duration: 10,
timeline: 0,
uri: '/00004.ts'
}
],
targetDuration: 10,
endList: true,
discontinuitySequence: 0,
discontinuityStarts: []
};

View File

@@ -0,0 +1,12 @@
#EXTM3U
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-TARGETDURATION:10
#EXTINF:10,
/00001.ts
#EXTINF:10,
/subdir/00002.ts
#EXTINF:10,
/00003.ts
#EXTINF:10,
/00004.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,7 @@
module.exports = {
allowCache: true,
dateRanges: [],
discontinuityStarts: [],
iFramePlaylists: [],
segments: []
};

View File

View File

@@ -0,0 +1,23 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
{
byterange: {
length: 522828,
offset: 0
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
}
],
targetDuration: 10,
endList: true,
discontinuitySequence: 0,
discontinuityStarts: [],
version: 4
};

View File

@@ -0,0 +1,10 @@
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:4
#EXT-X-ALLOW-CACHE:
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:10,
#EXT-X-BYTERANGE:522828@0
hls_450k_video.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,37 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
{
duration: 6.64,
timeline: 0,
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts',
title: '{}'
},
{
duration: 6.08,
timeline: 0,
uri: '/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts',
title: '{}'
},
{
duration: 6.6,
timeline: 0,
uri: '/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts',
title: '{}'
},
{
duration: 5,
timeline: 0,
uri: '/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts',
title: '{}'
}
],
targetDuration: 8,
endList: true,
discontinuitySequence: 0,
discontinuityStarts: []
};

View File

@@ -0,0 +1,14 @@
#EXTM3U
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MEDIA-SEQUENCE:
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:8
#EXTINF:6.640,{}
/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts
#EXTINF:6.080,{}
/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts
#EXTINF:6.600,{}
/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts
#EXTINF:5.000,{}
/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,42 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
segments: [
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00001.ts'
},
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00002.ts'
},
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00003.ts'
},
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00004.ts'
},
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00005.ts'
},
{
duration: 8,
timeline: 0,
uri: '/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00006.ts'
}
],
targetDuration: 10,
endList: true,
discontinuitySequence: 0,
discontinuityStarts: []
};

View File

@@ -0,0 +1,16 @@
#EXTM3U
#EXT-X-PLAYLIST-TYPE:
#EXT-X-TARGETDURATION:10
#EXTINF:10,
/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00001.ts
#EXTINF:10,
/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00002.ts
#EXTINF:10,
/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00003.ts
#EXTINF:10,
/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00004.ts
#EXTINF:10,
/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00005.ts
#EXTINF:8,
/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00006.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,59 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
playlists: [
{
attributes: {
'PROGRAM-ID': 1,
'BANDWIDTH': 240000,
'RESOLUTION': {
width: 396,
height: 224
}
},
timeline: 0,
uri: 'http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824686811001&videoId=1824650741001'
},
{
attributes: {
'PROGRAM-ID': 1,
'BANDWIDTH': 40000
},
timeline: 0,
uri: 'http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824683759001&videoId=1824650741001'
},
{
attributes: {
'PROGRAM-ID': 1,
'BANDWIDTH': 440000,
'RESOLUTION': {
width: 396,
height: 224
}
},
timeline: 0,
uri: 'http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824686593001&videoId=1824650741001'
},
{
attributes: {
'PROGRAM-ID': 1,
'BANDWIDTH': 1928000,
'RESOLUTION': {
width: 960,
height: 540
}
},
timeline: 0,
uri: 'http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824687660001&videoId=1824650741001'
}
],
discontinuityStarts: [],
mediaGroups: {
'VIDEO': {},
'AUDIO': {},
'CLOSED-CAPTIONS': {},
'SUBTITLES': {}
},
segments: []
};

View File

@@ -0,0 +1,10 @@
#EXTM3U
#EXT-X-TARGETDURATION:
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=240000,RESOLUTION=396x224
http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824686811001&videoId=1824650741001
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=40000
http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824683759001&videoId=1824650741001
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=440000,RESOLUTION=396x224
http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824686593001&videoId=1824650741001
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1928000,RESOLUTION=960x540
http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824687660001&videoId=1824650741001

View File

@@ -0,0 +1,63 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 7794,
discontinuitySequence: 0,
discontinuityStarts: [],
segments: [
{
duration: 2.833,
timeline: 0,
key: {
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=52'
},
uri: 'http://media.example.com/fileSequence52-A.ts'
},
{
duration: 15,
timeline: 0,
key: {
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=52'
},
uri: 'http://media.example.com/fileSequence52-B.ts'
},
{
duration: 13.333,
timeline: 0,
key: {
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=52'
},
uri: 'http://media.example.com/fileSequence52-C.ts'
},
{
duration: 15,
timeline: 0,
key: {
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=53'
},
uri: 'http://media.example.com/fileSequence53-A.ts'
},
{
duration: 14,
timeline: 0,
key: {
method: 'AES-128',
uri: 'https://priv.example.com/key.php?r=54',
iv: new Uint32Array([0, 0, 331, 3063767524])
},
uri: 'http://media.example.com/fileSequence53-B.ts'
},
{
duration: 15,
timeline: 0,
uri: 'http://media.example.com/fileSequence53-B.ts'
}
],
targetDuration: 15,
version: 3
};

View File

@@ -0,0 +1,28 @@
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:7794
#EXT-X-TARGETDURATION:15
#EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.php?r=52"
#EXTINF:2.833,
http://media.example.com/fileSequence52-A.ts
#EXTINF:15.0,
http://media.example.com/fileSequence52-B.ts
#EXTINF:13.333,
http://media.example.com/fileSequence52-C.ts
#EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.php?r=53"
#EXTINF:15.0,
http://media.example.com/fileSequence53-A.ts
#EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.php?r=54",IV=0x00000000000000000000014BB69D61E4
#EXTINF:14.0,
http://media.example.com/fileSequence53-B.ts
#EXT-X-KEY:METHOD=NONE
#EXTINF:15.0,
http://media.example.com/fileSequence53-B.ts

View File

@@ -0,0 +1,43 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
playlistType: 'EVENT',
segments: [
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00001.ts'
},
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00002.ts'
},
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00003.ts'
},
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00004.ts'
},
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00005.ts'
},
{
duration: 8,
timeline: 0,
uri: '/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00006.ts'
}
],
targetDuration: 10,
endList: true,
discontinuitySequence: 0,
discontinuityStarts: []
};

View File

@@ -0,0 +1,16 @@
#EXTM3U
#EXT-X-PLAYLIST-TYPE:EVENT
#EXT-X-TARGETDURATION:10
#EXTINF:10,
/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00001.ts
#EXTINF:10,
/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00002.ts
#EXTINF:10,
/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00003.ts
#EXTINF:10,
/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00004.ts
#EXTINF:10,
/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00005.ts
#EXTINF:8,
/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00006.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,18 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 1,
segments: [
{
duration: 6.64,
timeline: 0,
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts',
title: '{}'
}
],
targetDuration: 8,
endList: true,
discontinuitySequence: 0,
discontinuityStarts: []
};

View File

@@ -0,0 +1,8 @@
#EXTM3U
#EXT-X-PLAYLIST-TYPE:STRING
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:8
#EXTINF:6.640,{}
/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,168 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
{
byterange: {
length: 522828,
offset: 0
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 587500,
offset: 522828
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts',
title: ';asljasdfii11)))00,'
},
{
byterange: {
length: 713084,
offset: 1110328
},
duration: 5,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 476580,
offset: 1823412
},
duration: 9.7,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 535612,
offset: 2299992
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 207176,
offset: 2835604
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 455900,
offset: 3042780
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 657248,
offset: 3498680
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 571708,
offset: 4155928
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 485040,
offset: 4727636
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 709136,
offset: 5212676
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 730004,
offset: 5921812
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 456276,
offset: 6651816
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 468684,
offset: 7108092
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 444996,
offset: 7576776
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 331444,
offset: 8021772
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 44556,
offset: 8353216
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
}
],
targetDuration: 10,
endList: true,
discontinuitySequence: 0,
discontinuityStarts: [],
version: 3
};

View File

@@ -0,0 +1,57 @@
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:10
#EXT-X-BYTERANGE:522828@0
hls_450k_video.ts
#EXTINF:;asljasdfii11)))00,
#EXT-X-BYTERANGE:587500@522828
hls_450k_video.ts
#EXTINF:5,
#EXT-X-BYTERANGE:713084@1110328
hls_450k_video.ts
#EXTINF:9.7,
#EXT-X-BYTERANGE:476580@1823412
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:535612@2299992
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:207176@2835604
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:455900@3042780
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:657248@3498680
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:571708@4155928
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:485040@4727636
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:709136@5212676
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:730004@5921812
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:456276@6651816
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:468684@7108092
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:444996@7576776
hls_450k_video.ts
#EXTINF:22,
#EXTINF:10,
#EXT-X-BYTERANGE:331444@8021772
hls_450k_video.ts
#EXT-X-BYTERANGE:44556@8353216
hls_450k_video.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,47 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 1,
playlistType: 'VOD',
targetDuration: 6,
discontinuitySequence: 0,
discontinuityStarts: [],
segments: [
{
byterange: {
length: 5666510,
offset: 720
},
duration: 6.006,
timeline: 0,
uri: 'main.mp4',
map: {
byterange: {
length: 720,
offset: 0
},
uri: 'main.mp4'
}
},
{
byterange: {
length: 5861577,
offset: 5667230
},
duration: 6.006,
timeline: 0,
uri: 'main.mp4',
map: {
byterange: {
length: 720,
offset: 0
},
uri: 'main.mp4'
}
}
],
endList: true,
version: 7,
independentSegments: true
};

View File

@@ -0,0 +1,14 @@
#EXTM3U
#EXT-X-TARGETDURATION:6
#EXT-X-VERSION:7
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-MAP:URI="main.mp4",BYTERANGE="720@0"
#EXTINF:6.00600,
#EXT-X-BYTERANGE:5666510@720
main.mp4
#EXTINF:6.00600,
#EXT-X-BYTERANGE:5861577@5667230
main.mp4
#EXT-X-ENDLIST

View File

@@ -0,0 +1,7 @@
module.exports = {
allowCache: true,
dateRanges: [],
discontinuityStarts: [],
iFramePlaylists: [],
segments: []
};

View File

@@ -0,0 +1 @@
#EXTM3U

View File

@@ -0,0 +1,288 @@
module.exports = {
allowCache: true,
dateRanges: [],
discontinuityStarts: [],
iFramePlaylists: [
{
attributes: {
'AVERAGE-BANDWIDTH': 248586,
'BANDWIDTH': 593626,
'CODECS': 'hvc1.2.4.L123.B0',
'HDCP-LEVEL': 'NONE',
'RESOLUTION': { width: 1280, height: 720 },
'URI': 'sdr_720/iframe_index.m3u8',
'VIDEO-RANGE': 'SDR'
},
timeline: 0,
uri: 'sdr_720/iframe_index.m3u8'
},
{
attributes: {
'AVERAGE-BANDWIDTH': 399790,
'BANDWIDTH': 956552,
'CODECS': 'hvc1.2.4.L123.B0',
'HDCP-LEVEL': 'TYPE-0',
'RESOLUTION': { width: 1920, height: 1080 },
'URI': 'sdr_1080/iframe_index.m3u8',
'VIDEO-RANGE': 'SDR'
},
timeline: 0,
uri: 'sdr_1080/iframe_index.m3u8'
},
{
attributes: {
'AVERAGE-BANDWIDTH': 826971,
'BANDWIDTH': 1941397,
'CODECS': 'hvc1.2.4.L150.B0',
'HDCP-LEVEL': 'TYPE-1',
'RESOLUTION': { width: 3840, height: 2160 },
'URI': 'sdr_2160/iframe_index.m3u8',
'VIDEO-RANGE': 'SDR'
},
timeline: 0,
uri: 'sdr_2160/iframe_index.m3u8'
},
{
attributes: {
'AVERAGE-BANDWIDTH': 232253,
'BANDWIDTH': 573073,
'CODECS': 'dvh1.05.01',
'HDCP-LEVEL': 'NONE',
'RESOLUTION': { width: 1280, height: 720 },
'URI': 'dolby_720/iframe_index.m3u8',
'VIDEO-RANGE': 'PQ'
},
timeline: 0,
uri: 'dolby_720/iframe_index.m3u8'
},
{
attributes: {
'AVERAGE-BANDWIDTH': 365337,
'BANDWIDTH': 905037,
'CODECS': 'dvh1.05.03',
'HDCP-LEVEL': 'TYPE-0',
'RESOLUTION': { width: 1920, height: 1080 },
'URI': 'dolby_1080/iframe_index.m3u8',
'VIDEO-RANGE': 'PQ'
},
timeline: 0,
uri: 'dolby_1080/iframe_index.m3u8'
},
{
attributes: {
'AVERAGE-BANDWIDTH': 739114,
'BANDWIDTH': 1893236,
'CODECS': 'dvh1.05.06',
'HDCP-LEVEL': 'TYPE-1',
'RESOLUTION': { width: 3840, height: 2160 },
'URI': 'dolby_2160/iframe_index.m3u8',
'VIDEO-RANGE': 'PQ'
},
timeline: 0,
uri: 'dolby_2160/iframe_index.m3u8'
},
{
attributes: {
'AVERAGE-BANDWIDTH': 232511,
'BANDWIDTH': 572673,
'CODECS': 'hvc1.2.4.L123.B0',
'HDCP-LEVEL': 'NONE',
'RESOLUTION': { width: 1280, height: 720 },
'URI': 'hdr10_720/iframe_index.m3u8',
'VIDEO-RANGE': 'PQ'
},
timeline: 0,
uri: 'hdr10_720/iframe_index.m3u8'
},
{
attributes: {
'AVERAGE-BANDWIDTH': 364552,
'BANDWIDTH': 905053,
'CODECS': 'hvc1.2.4.L123.B0',
'HDCP-LEVEL': 'TYPE-0',
'RESOLUTION': { width: 1920, height: 1080 },
'URI': 'hdr10_1080/iframe_index.m3u8',
'VIDEO-RANGE': 'PQ'
},
timeline: 0,
uri: 'hdr10_1080/iframe_index.m3u8'
},
{
attributes: {
'AVERAGE-BANDWIDTH': 739757,
'BANDWIDTH': 1895477,
'CODECS': 'hvc1.2.4.L150.B0',
'HDCP-LEVEL': 'TYPE-1',
'RESOLUTION': { width: 3840, height: 2160 },
'URI': 'hdr10_2160/iframe_index.m3u8',
'VIDEO-RANGE': 'PQ'
},
timeline: 0,
uri: 'hdr10_2160/iframe_index.m3u8'
}
],
independentSegments: true,
mediaGroups: {
'AUDIO': {},
'CLOSED-CAPTIONS': {},
'SUBTITLES': {},
'VIDEO': {}
},
playlists: [
{
attributes: {
'HDCP-LEVEL': 'NONE',
'CLOSED-CAPTIONS': 'NONE',
'FRAME-RATE': 23.976,
'RESOLUTION': {
width: 1280,
height: 720
},
'CODECS': 'hvc1.2.4.L123.B0',
'VIDEO-RANGE': 'SDR',
'BANDWIDTH': 3971374,
'AVERAGE-BANDWIDTH': '2778321'
},
uri: 'sdr_720/prog_index.m3u8',
timeline: 0
},
{
attributes: {
'HDCP-LEVEL': 'TYPE-0',
'CLOSED-CAPTIONS': 'NONE',
'FRAME-RATE': 23.976,
'RESOLUTION': {
width: 1920,
height: 1080
},
'CODECS': 'hvc1.2.4.L123.B0',
'VIDEO-RANGE': 'SDR',
'BANDWIDTH': 10022043,
'AVERAGE-BANDWIDTH': '6759875'
},
uri: 'sdr_1080/prog_index.m3u8',
timeline: 0
},
{
attributes: {
'HDCP-LEVEL': 'TYPE-1',
'CLOSED-CAPTIONS': 'NONE',
'FRAME-RATE': 23.976,
'RESOLUTION': {
width: 3840,
height: 2160
},
'CODECS': 'hvc1.2.4.L150.B0',
'VIDEO-RANGE': 'SDR',
'BANDWIDTH': 28058971,
'AVERAGE-BANDWIDTH': '20985770'
},
uri: 'sdr_2160/prog_index.m3u8',
timeline: 0
},
{
attributes: {
'HDCP-LEVEL': 'NONE',
'CLOSED-CAPTIONS': 'NONE',
'FRAME-RATE': 23.976,
'RESOLUTION': {
width: 1280,
height: 720
},
'CODECS': 'dvh1.05.01',
'VIDEO-RANGE': 'PQ',
'BANDWIDTH': 5327059,
'AVERAGE-BANDWIDTH': '3385450'
},
uri: 'dolby_720/prog_index.m3u8',
timeline: 0
},
{
attributes: {
'HDCP-LEVEL': 'TYPE-0',
'CLOSED-CAPTIONS': 'NONE',
'FRAME-RATE': 23.976,
'RESOLUTION': {
width: 1920,
height: 1080
},
'CODECS': 'dvh1.05.03',
'VIDEO-RANGE': 'PQ',
'BANDWIDTH': 12876596,
'AVERAGE-BANDWIDTH': '7999361'
},
uri: 'dolby_1080/prog_index.m3u8',
timeline: 0
},
{
attributes: {
'HDCP-LEVEL': 'TYPE-1',
'CLOSED-CAPTIONS': 'NONE',
'FRAME-RATE': 23.976,
'RESOLUTION': {
width: 3840,
height: 2160
},
'CODECS': 'dvh1.05.06',
'VIDEO-RANGE': 'PQ',
'BANDWIDTH': 30041698,
'AVERAGE-BANDWIDTH': '24975091'
},
uri: 'dolby_2160/prog_index.m3u8',
timeline: 0
},
{
attributes: {
'HDCP-LEVEL': 'NONE',
'CLOSED-CAPTIONS': 'NONE',
'FRAME-RATE': 23.976,
'RESOLUTION': {
width: 1280,
height: 720
},
'CODECS': 'hvc1.2.4.L123.B0',
'VIDEO-RANGE': 'PQ',
'BANDWIDTH': 5280654,
'AVERAGE-BANDWIDTH': '3320040'
},
uri: 'hdr10_720/prog_index.m3u8',
timeline: 0
},
{
attributes: {
'HDCP-LEVEL': 'TYPE-0',
'CLOSED-CAPTIONS': 'NONE',
'FRAME-RATE': 23.976,
'RESOLUTION': {
width: 1920,
height: 1080
},
'CODECS': 'hvc1.2.4.L123.B0',
'VIDEO-RANGE': 'PQ',
'BANDWIDTH': 12886714,
'AVERAGE-BANDWIDTH': '7964551'
},
uri: 'hdr10_1080/prog_index.m3u8',
timeline: 0
},
{
attributes: {
'HDCP-LEVEL': 'TYPE-1',
'CLOSED-CAPTIONS': 'NONE',
'FRAME-RATE': 23.976,
'RESOLUTION': {
width: 3840,
height: 2160
},
'CODECS': 'hvc1.2.4.L150.B0',
'VIDEO-RANGE': 'PQ',
'BANDWIDTH': 29983769,
'AVERAGE-BANDWIDTH': '24833402'
},
uri: 'hdr10_2160/prog_index.m3u8',
timeline: 0
}
],
segments: [],
version: 7
};

View File

@@ -0,0 +1,42 @@
#EXTM3U
#EXT-X-VERSION:7
#EXT-X-INDEPENDENT-SEGMENTS
# https://developer.apple.com/documentation/http-live-streaming/hls-authoring-specification-for-apple-devices-appendixes#Example-playlist
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=248586,BANDWIDTH=593626,VIDEO-RANGE=SDR,CODECS="hvc1.2.4.L123.B0",RESOLUTION=1280x720,HDCP-LEVEL=NONE,URI="sdr_720/iframe_index.m3u8"
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=399790,BANDWIDTH=956552,VIDEO-RANGE=SDR,CODECS="hvc1.2.4.L123.B0",RESOLUTION=1920x1080,HDCP-LEVEL=TYPE-0,URI="sdr_1080/iframe_index.m3u8"
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=826971,BANDWIDTH=1941397,VIDEO-RANGE=SDR,CODECS="hvc1.2.4.L150.B0",RESOLUTION=3840x2160,HDCP-LEVEL=TYPE-1,URI="sdr_2160/iframe_index.m3u8"
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=232253,BANDWIDTH=573073,VIDEO-RANGE=PQ,CODECS="dvh1.05.01",RESOLUTION=1280x720,HDCP-LEVEL=NONE,URI="dolby_720/iframe_index.m3u8"
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=365337,BANDWIDTH=905037,VIDEO-RANGE=PQ,CODECS="dvh1.05.03",RESOLUTION=1920x1080,HDCP-LEVEL=TYPE-0,URI="dolby_1080/iframe_index.m3u8"
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=739114,BANDWIDTH=1893236,VIDEO-RANGE=PQ,CODECS="dvh1.05.06",RESOLUTION=3840x2160,HDCP-LEVEL=TYPE-1,URI="dolby_2160/iframe_index.m3u8"
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=232511,BANDWIDTH=572673,VIDEO-RANGE=PQ,CODECS="hvc1.2.4.L123.B0",RESOLUTION=1280x720,HDCP-LEVEL=NONE,URI="hdr10_720/iframe_index.m3u8"
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=364552,BANDWIDTH=905053,VIDEO-RANGE=PQ,CODECS="hvc1.2.4.L123.B0",RESOLUTION=1920x1080,HDCP-LEVEL=TYPE-0,URI="hdr10_1080/iframe_index.m3u8"
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=739757,BANDWIDTH=1895477,VIDEO-RANGE=PQ,CODECS="hvc1.2.4.L150.B0",RESOLUTION=3840x2160,HDCP-LEVEL=TYPE-1,URI="hdr10_2160/iframe_index.m3u8"
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=2778321,BANDWIDTH=3971374,VIDEO-RANGE=SDR,CODECS="hvc1.2.4.L123.B0",RESOLUTION=1280x720,FRAME-RATE=23.976,CLOSED-CAPTIONS=NONE,HDCP-LEVEL=NONE
sdr_720/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=6759875,BANDWIDTH=10022043,VIDEO-RANGE=SDR,CODECS="hvc1.2.4.L123.B0",RESOLUTION=1920x1080,FRAME-RATE=23.976,CLOSED-CAPTIONS=NONE,HDCP-LEVEL=TYPE-0
sdr_1080/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=20985770,BANDWIDTH=28058971,VIDEO-RANGE=SDR,CODECS="hvc1.2.4.L150.B0",RESOLUTION=3840x2160,FRAME-RATE=23.976,CLOSED-CAPTIONS=NONE,HDCP-LEVEL=TYPE-1
sdr_2160/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=3385450,BANDWIDTH=5327059,VIDEO-RANGE=PQ,CODECS="dvh1.05.01",RESOLUTION=1280x720,FRAME-RATE=23.976,CLOSED-CAPTIONS=NONE,HDCP-LEVEL=NONE
dolby_720/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=7999361,BANDWIDTH=12876596,VIDEO-RANGE=PQ,CODECS="dvh1.05.03",RESOLUTION=1920x1080,FRAME-RATE=23.976,CLOSED-CAPTIONS=NONE,HDCP-LEVEL=TYPE-0
dolby_1080/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=24975091,BANDWIDTH=30041698,VIDEO-RANGE=PQ,CODECS="dvh1.05.06",RESOLUTION=3840x2160,FRAME-RATE=23.976,CLOSED-CAPTIONS=NONE,HDCP-LEVEL=TYPE-1
dolby_2160/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=3320040,BANDWIDTH=5280654,VIDEO-RANGE=PQ,CODECS="hvc1.2.4.L123.B0",RESOLUTION=1280x720,FRAME-RATE=23.976,CLOSED-CAPTIONS=NONE,HDCP-LEVEL=NONE
hdr10_720/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=7964551,BANDWIDTH=12886714,VIDEO-RANGE=PQ,CODECS="hvc1.2.4.L123.B0",RESOLUTION=1920x1080,FRAME-RATE=23.976,CLOSED-CAPTIONS=NONE,HDCP-LEVEL=TYPE-0
hdr10_1080/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=24833402,BANDWIDTH=29983769,VIDEO-RANGE=PQ,CODECS="hvc1.2.4.L150.B0",RESOLUTION=3840x2160,FRAME-RATE=23.976,CLOSED-CAPTIONS=NONE,HDCP-LEVEL=TYPE-1
hdr10_2160/prog_index.m3u8

View File

@@ -0,0 +1,45 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
iFramesOnly: true,
mediaSequence: 0,
playlistType: 'VOD',
segments: [
{
duration: 2.002,
timeline: 0,
uri: '001.ts'
},
{
duration: 2.002,
timeline: 0,
uri: '002.ts'
},
{
duration: 2.002,
timeline: 0,
uri: '003.ts'
},
{
duration: 2.002,
timeline: 0,
uri: '004.ts'
},
{
duration: 2.002,
timeline: 0,
uri: '005.ts'
},
{
duration: 2.002,
timeline: 0,
uri: '006.ts'
}
],
targetDuration: 3,
endList: true,
discontinuitySequence: 0,
discontinuityStarts: [],
version: 4
};

View File

@@ -0,0 +1,19 @@
#EXTM3U
#EXT-X-VERSION:4
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-TARGETDURATION:3
#EXT-X-I-FRAMES-ONLY
#EXTINF:2.002,
001.ts
#EXTINF:2.002,
002.ts
#EXTINF:2.002,
003.ts
#EXTINF:2.002,
004.ts
#EXTINF:2.002,
005.ts
#EXTINF:2.002,
006.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,23 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
{
byterange: {
length: 522828,
offset: 0
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
}
],
targetDuration: 10,
endList: true,
discontinuitySequence: 0,
discontinuityStarts: [],
version: 4
};

View File

@@ -0,0 +1,10 @@
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:4
#EXT-X-ALLOW-CACHE:MAYBE
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:10,
#EXT-X-BYTERANGE:522828@0
hls_450k_video.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,37 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
{
duration: 6.64,
timeline: 0,
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts',
title: '{}'
},
{
duration: 6.08,
timeline: 0,
uri: '/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts',
title: '{}'
},
{
duration: 6.6,
timeline: 0,
uri: '/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts',
title: '{}'
},
{
duration: 5,
timeline: 0,
uri: '/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts',
title: '{}'
}
],
targetDuration: 8,
endList: true,
discontinuitySequence: 0,
discontinuityStarts: []
};

View File

@@ -0,0 +1,14 @@
#EXTM3U
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MEDIA-SEQUENCE:gobblegobble
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:8
#EXTINF:6.640,{}
/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts
#EXTINF:6.080,{}
/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts
#EXTINF:6.600,{}
/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts
#EXTINF:5.000,{}
/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,42 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
segments: [
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00001.ts'
},
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00002.ts'
},
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00003.ts'
},
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00004.ts'
},
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00005.ts'
},
{
duration: 8,
timeline: 0,
uri: '/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00006.ts'
}
],
targetDuration: 10,
endList: true,
discontinuitySequence: 0,
discontinuityStarts: []
};

View File

@@ -0,0 +1,16 @@
#EXTM3U
#EXT-X-PLAYLIST-TYPE:asdRASDfasdR
#EXT-X-TARGETDURATION:10
#EXTINF:10,
/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00001.ts
#EXTINF:10,
/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00002.ts
#EXTINF:10,
/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00003.ts
#EXTINF:10,
/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00004.ts
#EXTINF:10,
/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00005.ts
#EXTINF:8,
/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00006.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,166 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
{
byterange: {
length: 522828,
offset: 0
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 587500,
offset: 522828
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 713084,
offset: 1110328
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 476580,
offset: 1823412
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 535612,
offset: 2299992
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 207176,
offset: 2835604
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 455900,
offset: 3042780
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 657248,
offset: 3498680
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 571708,
offset: 4155928
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 485040,
offset: 4727636
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 709136,
offset: 5212676
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 730004,
offset: 5921812
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 456276,
offset: 6651816
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 468684,
offset: 7108092
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 444996,
offset: 7576776
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 331444,
offset: 8021772
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 44556,
offset: 8353216
},
duration: 1.4167,
timeline: 0,
uri: 'hls_450k_video.ts'
}
],
endList: true,
discontinuitySequence: 0,
discontinuityStarts: [],
version: 4
};

View File

@@ -0,0 +1,57 @@
#EXTM3U
#EXT-X-TARGETDURATION:NaN
#EXT-X-VERSION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:10,
#EXT-X-BYTERANGE:522828@0
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:587500@522828
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:713084@1110328
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:476580@1823412
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:535612@2299992
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:207176@2835604
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:455900@3042780
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:657248@3498680
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:571708@4155928
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:485040@4727636
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:709136@5212676
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:730004@5921812
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:456276@6651816
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:468684@7108092
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:444996@7576776
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:331444@8021772
hls_450k_video.ts
#EXTINF:1.4167,
#EXT-X-BYTERANGE:44556@8353216
hls_450k_video.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,28 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
{
duration: 6.64,
timeline: 0,
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts',
title: '{}'
},
{
duration: 8,
timeline: 0,
uri: '/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts'
},
{
duration: 8,
timeline: 0,
uri: '/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts'
}
],
targetDuration: 8,
discontinuitySequence: 0,
discontinuityStarts: []
};

View File

@@ -0,0 +1,9 @@
#EXTM3U
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:8
#EXTINF:6.640,{}
/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts
/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts
/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts

View File

@@ -0,0 +1,65 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
segments: [
{
duration: 10,
timeline: 0,
uri: '001.ts',
title: '0'
},
{
duration: 19,
timeline: 0,
uri: '002.ts',
title: '0'
},
{
duration: 10,
timeline: 0,
uri: '003.ts',
title: '0'
},
{
duration: 11,
timeline: 0,
uri: '004.ts',
title: '0'
},
{
duration: 10,
timeline: 0,
uri: '005.ts',
title: '0'
},
{
duration: 10,
timeline: 0,
uri: '006.ts',
title: '0'
},
{
duration: 10,
timeline: 0,
uri: '007.ts',
title: '0'
},
{
duration: 10,
timeline: 0,
uri: '008.ts',
title: '0'
},
{
duration: 16,
timeline: 0,
uri: '009.ts',
title: '0'
}
],
targetDuration: 10,
discontinuitySequence: 0,
discontinuityStarts: []
};

View File

@@ -0,0 +1,22 @@
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:10
#EXTINF:10,0
001.ts
#EXTINF:19,0
002.ts
#EXTINF:10,0
003.ts
#EXTINF:11,0
004.ts
#EXTINF:10,0
005.ts
#EXTINF:10,0
006.ts
#EXTINF:10,0
007.ts
#EXTINF:10,0
008.ts
#EXTINF:16,0
009.ts

View File

@@ -0,0 +1,255 @@
module.exports = {
allowCache: true,
dateRanges: [],
discontinuitySequence: 0,
discontinuityStarts: [],
iFramePlaylists: [],
mediaSequence: 0,
playlistType: 'VOD',
preloadSegment: {
preloadHints: [
{
type: 'PART',
uri: 'filePart273.1.mp4',
byterange: {
length: 2000,
offset: 0
}
},
{
type: 'MAP',
uri: 'file-init.mp4',
byterange: {
length: 5000,
offset: 8355216
}
},
{
type: 'FOO',
uri: 'foo.mp4',
byterange: {
length: 5000,
offset: 0
}
}
],
timeline: 0
},
segments: [
{
byterange: {
length: 587500,
offset: 0
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 587500,
offset: 522828
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 713084,
offset: 1110328
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video2.ts'
},
{
byterange: {
length: 476580,
offset: 1823412
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 535612,
offset: 2299992
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 207176,
offset: 2835604
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 455900,
offset: 3042780
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 657248,
offset: 3498680
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 571708,
offset: 4155928
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 485040,
offset: 4727636
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 709136,
offset: 5212676
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 730004,
offset: 5921812
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 456276,
offset: 6651816
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 468684,
offset: 7108092
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 444996,
offset: 7576776
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 331444,
offset: 8021772
},
duration: 10,
parts: [
{
duration: 0.33334,
uri: 'hls_450k_video.part.ts',
byterange: {
length: 45553,
offset: 0
}
},
{
duration: 0.33334,
uri: 'hls_450k_video.part.ts',
byterange: {
length: 28823,
offset: 7622329
}
},
{
duration: 0.33334,
uri: 'hls_450k_video.part.ts',
byterange: {
length: 22444,
offset: 7651152
}
},
{
duration: 0.33334,
uri: 'hls_450k_video.part.ts',
byterange: {
length: 22444,
offset: 7673596
}
}
],
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 44556,
offset: 8353216
},
duration: 1.4167,
parts: [
{
duration: 0.33334,
uri: 'hls_450k_video.ts',
byterange: {
length: 45553,
offset: 8021772
}
},
{
duration: 0.33334,
uri: 'hls_450k_video.ts',
byterange: {
length: 28823,
offset: 8067325
}
},
{
duration: 0.33334,
uri: 'hls_450k_video.ts',
byterange: {
length: 22444,
offset: 8096148
}
}
],
timeline: 0,
uri: 'hls_450k_video.ts'
}
],
targetDuration: 10,
version: 3
};

View File

@@ -0,0 +1,66 @@
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:10,
#EXT-X-BYTERANGE:587500@
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:587500@522828
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:713084
hls_450k_video2.ts
#EXTINF:10,
#EXT-X-BYTERANGE:476580@1823412
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:535612@2299992
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:207176@2835604
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:455900@3042780
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:657248@3498680
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:571708@4155928
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:485040@4727636
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:709136@5212676
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:730004@5921812
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:456276@6651816
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:468684@7108092
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:444996@7576776
hls_450k_video.ts
#EXT-X-PART:DURATION=0.33334,URI="hls_450k_video.part.ts",BYTERANGE=45553
#EXT-X-PART:DURATION=0.33334,URI="hls_450k_video.part.ts",BYTERANGE=28823@7622329
#EXT-X-PART:DURATION=0.33334,URI="hls_450k_video.part.ts",BYTERANGE=22444
#EXT-X-PART:DURATION=0.33334,URI="hls_450k_video.part.ts",BYTERANGE=22444
#EXTINF:10,
#EXT-X-BYTERANGE:331444@8021772
hls_450k_video.ts
#EXT-X-PART:DURATION=0.33334,URI="hls_450k_video.ts",BYTERANGE=45553@8021772
#EXT-X-PART:DURATION=0.33334,URI="hls_450k_video.ts",BYTERANGE=28823
#EXT-X-PART:DURATION=0.33334,URI="hls_450k_video.ts",BYTERANGE=22444
#EXTINF:1.4167,
#EXT-X-BYTERANGE:44556@8353216
hls_450k_video.ts
#EXT-X-PRELOAD-HINT:TYPE=PART,URI="filePart273.1.mp4",BYTERANGE-LENGTH=2000
#EXT-X-PRELOAD-HINT:TYPE=MAP,URI="file-init.mp4",BYTERANGE-LENGTH=5000,BYTERANGE-START=8355216
#EXT-X-PRELOAD-HINT:TYPE=FOO,URI="foo.mp4",BYTERANGE-LENGTH=5000

View File

@@ -0,0 +1,151 @@
module.exports = {
allowCache: true,
dateRanges: [],
discontinuitySequence: 0,
discontinuityStarts: [],
iFramePlaylists: [],
mediaSequence: 0,
playlistType: 'VOD',
preloadSegment: {
parts: [
{
duration: 0.33334,
uri: 'hls_450k_video.ts',
byterange: {
length: 22444,
offset: 0
}
}
],
preloadHints: [
{
type: 'PART',
uri: 'filePart273.1.mp4',
byterange: {
length: 2000,
offset: 22444
}
},
{
type: 'MAP',
uri: 'file-init.mp4',
byterange: {
length: 5000,
offset: 8377660
}
},
{
type: 'FOO',
uri: 'foo.mp4',
byterange: {
length: 5000,
offset: 0
}
}
],
timeline: 0
},
segments: [
{
byterange: {
length: 468684,
offset: 7108092
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 444996,
offset: 7576776
},
duration: 10,
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 331444,
offset: 8021772
},
duration: 10,
parts: [
{
duration: 0.33334,
uri: 'hls_450k_video.ts',
byterange: {
length: 45553,
offset: 0
}
},
{
duration: 0.33334,
uri: 'hls_450k_video.ts',
byterange: {
length: 28823,
offset: 7622329
}
},
{
duration: 0.33334,
uri: 'hls_450k_video.ts',
byterange: {
length: 22444,
offset: 7651152
}
},
{
duration: 0.33334,
uri: 'hls_450k_video.ts',
byterange: {
length: 22444,
offset: 7673596
}
}
],
timeline: 0,
uri: 'hls_450k_video.ts'
},
{
byterange: {
length: 44556,
offset: 8353216
},
duration: 1.4167,
parts: [
{
duration: 0.33334,
uri: 'hls_450k_video.ts',
byterange: {
length: 45553,
offset: 8021772
}
},
{
duration: 0.33334,
uri: 'hls_450k_video.ts',
byterange: {
length: 28823,
offset: 8067325
}
},
{
duration: 0.33334,
uri: 'hls_450k_video.ts',
byterange: {
length: 22444,
offset: 8096148
}
}
],
timeline: 0,
uri: 'hls_450k_video.ts'
}
],
skip: {
skippedSegments: 3
},
targetDuration: 10,
version: 3
};

View File

@@ -0,0 +1,30 @@
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:10,
#EXT-X-SKIP:SKIPPED-SEGMENTS=3
#EXTINF:10,
#EXT-X-BYTERANGE:468684@7108092
hls_450k_video.ts
#EXTINF:10,
#EXT-X-BYTERANGE:444996@7576776
hls_450k_video.ts
#EXT-X-PART:DURATION=0.33334,URI="hls_450k_video.ts",BYTERANGE=45553
#EXT-X-PART:DURATION=0.33334,URI="hls_450k_video.ts",BYTERANGE=28823@7622329
#EXT-X-PART:DURATION=0.33334,URI="hls_450k_video.ts",BYTERANGE=22444
#EXT-X-PART:DURATION=0.33334,URI="hls_450k_video.ts",BYTERANGE=22444
#EXTINF:10,
#EXT-X-BYTERANGE:331444@8021772
hls_450k_video.ts
#EXT-X-PART:DURATION=0.33334,URI="hls_450k_video.ts",BYTERANGE=45553@8021772
#EXT-X-PART:DURATION=0.33334,URI="hls_450k_video.ts",BYTERANGE=28823
#EXT-X-PART:DURATION=0.33334,URI="hls_450k_video.ts",BYTERANGE=22444
#EXTINF:1.4167,
#EXT-X-BYTERANGE:44556@8353216
hls_450k_video.ts
#EXT-X-PART:DURATION=0.33334,URI="hls_450k_video.ts",BYTERANGE=22444
#EXT-X-PRELOAD-HINT:TYPE=PART,URI="filePart273.1.mp4",BYTERANGE-LENGTH=2000
#EXT-X-PRELOAD-HINT:TYPE=MAP,URI="file-init.mp4",BYTERANGE-LENGTH=5000,BYTERANGE-START=8377660
#EXT-X-PRELOAD-HINT:TYPE=FOO,URI="foo.mp4",BYTERANGE-LENGTH=5000

View File

@@ -0,0 +1,223 @@
module.exports = {
allowCache: true,
dateTimeObject: new Date('2019-02-14T02:13:36.106Z'),
dateTimeString: '2019-02-14T02:13:36.106Z',
dateRanges: [],
discontinuitySequence: 0,
discontinuityStarts: [],
iFramePlaylists: [],
mediaSequence: 266,
preloadSegment: {
map: {uri: 'init.mp4'},
parts: [
{
duration: 0.33334,
independent: true,
uri: 'filePart273.0.mp4'
},
{
duration: 0.33334,
uri: 'filePart273.1.mp4'
},
{
duration: 0.33334,
uri: 'filePart273.2.mp4'
}
],
preloadHints: [
{type: 'PART', uri: 'filePart273.3.mp4'},
{type: 'MAP', uri: 'file-init.mp4'}
],
timeline: 0
},
renditionReports: [
{lastMsn: 273, lastPart: 2, uri: '../1M/waitForMSN.php'},
{lastMsn: 273, lastPart: 1, uri: '../4M/waitForMSN.php'}
],
partInf: {
partTarget: 0.33334
},
partTargetDuration: 0.33334,
segments: [
{
dateTimeObject: new Date('2019-02-14T02:13:36.106Z'),
dateTimeString: '2019-02-14T02:13:36.106Z',
programDateTime: 1550110416106,
duration: 4.00008,
map: {
uri: 'init.mp4'
},
timeline: 0,
uri: 'fileSequence266.mp4'
},
{
duration: 4.00008,
map: {
uri: 'init.mp4'
},
programDateTime: 1550110420106.08,
timeline: 0,
uri: 'fileSequence267.mp4'
},
{
duration: 4.00008,
map: {
uri: 'init.mp4'
},
programDateTime: 1550110424106.1602,
timeline: 0,
uri: 'fileSequence268.mp4'
},
{
duration: 4.00008,
map: {
uri: 'init.mp4'
},
programDateTime: 1550110428106.2402,
timeline: 0,
uri: 'fileSequence269.mp4'
},
{
duration: 4.00008,
map: {
uri: 'init.mp4'
},
programDateTime: 1550110432106.3203,
timeline: 0,
uri: 'fileSequence270.mp4'
},
{
duration: 4.00008,
map: {
uri: 'init.mp4'
},
programDateTime: 1550110436106.4004,
timeline: 0,
uri: 'fileSequence271.mp4',
parts: [
{
duration: 0.33334,
uri: 'filePart271.0.mp4'
},
{
duration: 0.33334,
uri: 'filePart271.1.mp4'
},
{
duration: 0.33334,
uri: 'filePart271.2.mp4'
},
{
duration: 0.33334,
uri: 'filePart271.3.mp4'
},
{
duration: 0.33334,
independent: true,
uri: 'filePart271.4.mp4'
},
{
duration: 0.33334,
uri: 'filePart271.5.mp4'
},
{
duration: 0.33334,
uri: 'filePart271.6.mp4'
},
{
duration: 0.33334,
uri: 'filePart271.7.mp4'
},
{
duration: 0.33334,
independent: true,
uri: 'filePart271.8.mp4'
},
{
duration: 0.33334,
uri: 'filePart271.9.mp4'
},
{
duration: 0.33334,
uri: 'filePart271.10.mp4'
},
{
duration: 0.33334,
uri: 'filePart271.11.mp4'
}
]
},
{
dateTimeObject: new Date('2019-02-14T02:14:00.106Z'),
dateTimeString: '2019-02-14T02:14:00.106Z',
duration: 4.00008,
map: {
uri: 'init.mp4'
},
programDateTime: 1550110440106,
timeline: 0,
uri: 'fileSequence272.mp4',
parts: [
{
duration: 0.33334,
gap: true,
uri: 'filePart272.a.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.b.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.c.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.d.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.e.mp4'
},
{
duration: 0.33334,
independent: true,
uri: 'filePart272.f.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.g.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.h.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.i.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.j.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.k.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.l.mp4'
}
]
}
],
serverControl: {
canSkipDateranges: true,
canBlockReload: true,
canSkipUntil: 12,
partHoldBack: 1,
holdBack: 12
},
targetDuration: 4,
version: 6
};

View File

@@ -0,0 +1,56 @@
#EXTM3U
# This Playlist is a response to: GET https://example.com/2M/waitForMSN.php?_HLS_msn=273&_HLS_part=2
#EXT-X-TARGETDURATION:4
#EXT-X-VERSION:6
#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES,CAN-SKIP-DATERANGES=YES,PART-HOLD-BACK=1.0,CAN-SKIP-UNTIL=12.0,HOLD-BACK=12.0
#EXT-X-PART-INF:PART-TARGET=0.33334
#EXT-X-MEDIA-SEQUENCE:266
#EXT-X-PROGRAM-DATE-TIME:2019-02-14T02:13:36.106Z
#EXT-X-MAP:URI="init.mp4"
#EXTINF:4.00008,
fileSequence266.mp4
#EXTINF:4.00008,
fileSequence267.mp4
#EXTINF:4.00008,
fileSequence268.mp4
#EXTINF:4.00008,
fileSequence269.mp4
#EXTINF:4.00008,
fileSequence270.mp4
#EXT-X-PART:DURATION=0.33334,URI="filePart271.0.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.1.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.2.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.3.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.4.mp4",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.33334,URI="filePart271.5.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.6.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.7.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.8.mp4",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.33334,URI="filePart271.9.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.10.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.11.mp4"
#EXTINF:4.00008,
fileSequence271.mp4
#EXT-X-PROGRAM-DATE-TIME:2019-02-14T02:14:00.106Z
#EXT-X-PART:GAP=YES,DURATION=0.33334,URI="filePart272.a.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.b.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.c.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.d.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.e.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.f.mp4",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.33334,URI="filePart272.g.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.h.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.i.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.j.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.k.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.l.mp4"
#EXTINF:4.00008,
fileSequence272.mp4
#EXT-X-PART:DURATION=0.33334,URI="filePart273.0.mp4",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.33334,URI="filePart273.1.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart273.2.mp4"
#EXT-X-PRELOAD-HINT:TYPE=PART,URI="filePart273.3.mp4"
#EXT-X-PRELOAD-HINT:TYPE=MAP,URI="file-init.mp4"
#EXT-X-RENDITION-REPORT:URI="../1M/waitForMSN.php",LAST-MSN=273,LAST-PART=2
#EXT-X-RENDITION-REPORT:URI="../4M/waitForMSN.php",LAST-MSN=273,LAST-PART=1

View File

@@ -0,0 +1,192 @@
module.exports = {
allowCache: true,
dateTimeObject: new Date('2019-02-14T02:14:00.106Z'),
dateTimeString: '2019-02-14T02:14:00.106Z',
dateRanges: [],
discontinuitySequence: 0,
discontinuityStarts: [],
iFramePlaylists: [],
mediaSequence: 266,
preloadSegment: {
timeline: 0,
preloadHints: [
{type: 'PART', uri: 'filePart273.4.mp4'},
{type: 'MAP', uri: 'file-init.mp4'}
],
parts: [
{
duration: 0.33334,
independent: true,
uri: 'filePart273.0.mp4'
},
{
duration: 0.33334,
uri: 'filePart273.1.mp4'
},
{
duration: 0.33334,
uri: 'filePart273.2.mp4'
},
{
duration: 0.33334,
uri: 'filePart273.3.mp4'
}
]
},
renditionReports: [
{lastMsn: 273, lastPart: 3, uri: '../1M/waitForMSN.php'},
{lastMsn: 273, lastPart: 3, uri: '../4M/waitForMSN.php'}
],
partInf: {
partTarget: 0.33334
},
partTargetDuration: 0.33334,
segments: [
{
duration: 4.00008,
programDateTime: 1550110428105.7598,
timeline: 0,
uri: 'fileSequence269.mp4'
},
{
duration: 4.00008,
programDateTime: 1550110432105.8398,
timeline: 0,
uri: 'fileSequence270.mp4'
},
{
duration: 4.00008,
programDateTime: 1550110436105.92,
timeline: 0,
uri: 'fileSequence271.mp4',
parts: [
{
duration: 0.33334,
uri: 'filePart271.0.mp4'
},
{
duration: 0.33334,
uri: 'filePart271.1.mp4'
},
{
duration: 0.33334,
uri: 'filePart271.2.mp4'
},
{
duration: 0.33334,
uri: 'filePart271.3.mp4'
},
{
duration: 0.33334,
independent: true,
uri: 'filePart271.4.mp4'
},
{
duration: 0.33334,
uri: 'filePart271.5.mp4'
},
{
duration: 0.33334,
uri: 'filePart271.6.mp4'
},
{
duration: 0.33334,
uri: 'filePart271.7.mp4'
},
{
duration: 0.33334,
independent: true,
uri: 'filePart271.8.mp4'
},
{
duration: 0.33334,
uri: 'filePart271.9.mp4'
},
{
duration: 0.33334,
uri: 'filePart271.10.mp4'
},
{
duration: 0.33334,
uri: 'filePart271.11.mp4'
}
]
},
{
dateTimeObject: new Date('2019-02-14T02:14:00.106Z'),
dateTimeString: '2019-02-14T02:14:00.106Z',
duration: 4.00008,
programDateTime: 1550110440106,
timeline: 0,
uri: 'fileSequence272.mp4',
parts: [
{
duration: 0.33334,
gap: true,
uri: 'filePart272.a.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.b.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.c.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.d.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.e.mp4'
},
{
duration: 0.33334,
independent: true,
uri: 'filePart272.f.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.g.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.h.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.i.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.j.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.k.mp4'
},
{
duration: 0.33334,
uri: 'filePart272.l.mp4'
}
]
}
],
skip: {
skippedSegments: 3,
recentlyRemovedDateranges: [
'foo',
'bar'
]
},
serverControl: {
canSkipDateranges: true,
canBlockReload: true,
canSkipUntil: 12,
partHoldBack: 1,
holdBack: 12
},
targetDuration: 4,
version: 9
};

View File

@@ -0,0 +1,50 @@
#EXTM3U
# Following the example above, this Playlist is a response to: GET https://example.com/2M/waitForMSN.php?_HLS_msn=273&_HLS_part=3 &_HLS_skip=YES
#EXT-X-TARGETDURATION:4
#EXT-X-VERSION:9
#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES,CAN-SKIP-DATERANGES=YES,PART-HOLD-BACK=1.0,CAN-SKIP-UNTIL=12.0,HOLD-BACK=12.0
#EXT-X-PART-INF:PART-TARGET=0.33334
#EXT-X-MEDIA-SEQUENCE:266
#EXT-X-SKIP:SKIPPED-SEGMENTS=3,RECENTLY-REMOVED-DATERANGES=foo bar
#EXTINF:4.00008,
fileSequence269.mp4
#EXTINF:4.00008,
fileSequence270.mp4
#EXT-X-PART:DURATION=0.33334,URI="filePart271.0.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.1.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.2.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.3.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.4.mp4",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.33334,URI="filePart271.5.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.6.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.7.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.8.mp4",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.33334,URI="filePart271.9.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.10.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.11.mp4"
#EXTINF:4.00008,
fileSequence271.mp4
#EXT-X-PROGRAM-DATE-TIME:2019-02-14T02:14:00.106Z
#EXT-X-PART:GAP=YES,DURATION=0.33334,URI="filePart272.a.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.b.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.c.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.d.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.e.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.f.mp4",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.33334,URI="filePart272.g.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.h.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.i.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.j.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.k.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.l.mp4"
#EXTINF:4.00008,
fileSequence272.mp4
#EXT-X-PART:DURATION=0.33334,URI="filePart273.0.mp4",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.33334,URI="filePart273.1.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart273.2.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart273.3.mp4"
#EXT-X-PRELOAD-HINT:TYPE=PART,URI="filePart273.4.mp4"
#EXT-X-PRELOAD-HINT:TYPE=MAP,URI="file-init.mp4"
#EXT-X-RENDITION-REPORT:URI="../1M/waitForMSN.php",LAST-MSN=273,LAST-PART=3
#EXT-X-RENDITION-REPORT:URI="../4M/waitForMSN.php",LAST-MSN=273,LAST-PART=3

View File

@@ -0,0 +1,16 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
segments: [
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/gogo/00001.ts'
}
],
endList: true,
discontinuitySequence: 0,
discontinuityStarts: []
};

View File

@@ -0,0 +1,5 @@
#EXTM3U
#EXT-X-TARGETDURATION:-10
#EXTINF:10,
/test/ts-files/zencoder/gogo/00001.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,37 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
segments: [
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/gogo/00001.ts'
},
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/gogo/00002.ts'
},
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/gogo/00003.ts'
},
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/gogo/00004.ts'
},
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/gogo/00005.ts'
}
],
targetDuration: 10,
endList: true,
discontinuitySequence: 0,
discontinuityStarts: []
};

View File

@@ -0,0 +1,14 @@
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXTINF:10,
/test/ts-files/zencoder/gogo/00001.ts
#EXTINF:10,
/test/ts-files/zencoder/gogo/00002.ts
#EXTINF:10,
/test/ts-files/zencoder/gogo/00003.ts
#EXT-X-ENDLIST
#EXTINF:10,
/test/ts-files/zencoder/gogo/00004.ts
#EXTINF:10,
/test/ts-files/zencoder/gogo/00005.ts

View File

@@ -0,0 +1,17 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
segments: [
{
duration: 10,
timeline: 0,
uri: '/test/ts-files/zencoder/gogo/00001.ts'
}
],
targetDuration: 10,
endList: true,
discontinuitySequence: 0,
discontinuityStarts: []
};

View File

@@ -0,0 +1,4 @@
#EXT-X-TARGETDURATION:10
#EXTINF:10,
/test/ts-files/zencoder/gogo/00001.ts
#EXT-X-ENDLIST

View File

@@ -0,0 +1,553 @@
module.exports = {
allowCache: true,
dateRanges: [],
discontinuityStarts: [],
iFramePlaylists: [
{
attributes: {
'AVERAGE-BANDWIDTH': 163198,
'BANDWIDTH': 166942,
'CODECS': 'avc1.64002a',
'RESOLUTION': {
height: 1080,
width: 1920
},
'URI': 'v6/iframe_index.m3u8'
},
timeline: 0,
uri: 'v6/iframe_index.m3u8'
},
{
attributes: {
'AVERAGE-BANDWIDTH': 131314,
'BANDWIDTH': 139041,
'CODECS': 'avc1.640020',
'RESOLUTION': {
height: 720,
width: 1280
},
'URI': 'v5/iframe_index.m3u8'
},
timeline: 0,
uri: 'v5/iframe_index.m3u8'
},
{
attributes: {
'AVERAGE-BANDWIDTH': 100233,
'BANDWIDTH': 101724,
'CODECS': 'avc1.640020',
'RESOLUTION': {
height: 540,
width: 960
},
'URI': 'v4/iframe_index.m3u8'
},
timeline: 0,
uri: 'v4/iframe_index.m3u8'
},
{
attributes: {
'AVERAGE-BANDWIDTH': 81002,
'BANDWIDTH': 84112,
'CODECS': 'avc1.64001e',
'RESOLUTION': {
height: 432,
width: 768
},
'URI': 'v3/iframe_index.m3u8'
},
timeline: 0,
uri: 'v3/iframe_index.m3u8'
},
{
attributes: {
'AVERAGE-BANDWIDTH': 64987,
'BANDWIDTH': 65835,
'CODECS': 'avc1.64001e',
'RESOLUTION': {
height: 360,
width: 640
},
'URI': 'v2/iframe_index.m3u8'
},
timeline: 0,
uri: 'v2/iframe_index.m3u8'
},
{
attributes: {
'AVERAGE-BANDWIDTH': 41547,
'BANDWIDTH': 42106,
'CODECS': 'avc1.640015',
'RESOLUTION': {
height: 270,
width: 480
},
'URI': 'v1/iframe_index.m3u8'
},
timeline: 0,
uri: 'v1/iframe_index.m3u8'
}
],
mediaGroups: {
'AUDIO': {
aud1: {
English: {
autoselect: true,
default: true,
language: 'eng',
uri: 'a1/prog_index.m3u8'
}
},
aud2: {
English: {
autoselect: true,
default: true,
language: 'eng',
uri: 'a2/prog_index.m3u8'
}
},
aud3: {
English: {
autoselect: true,
default: true,
language: 'eng',
uri: 'a3/prog_index.m3u8'
}
}
},
'VIDEO': {},
'CLOSED-CAPTIONS': {
cc1: {
English: {
autoselect: true,
default: true,
language: 'eng',
instreamId: 'CC1'
}
}
},
'SUBTITLES': {
sub1: {
English: {
autoselect: true,
default: true,
language: 'eng',
uri: 's1/eng/prog_index.m3u8',
forced: false
}
}
}
},
playlists: [{
attributes: {
'AVERAGE-BANDWIDTH': '2165224',
'BANDWIDTH': 2215219,
'CODECS': 'avc1.640020,mp4a.40.2',
'RESOLUTION': {
width: 960,
height: 540
},
'FRAME-RATE': 59.940,
'CLOSED-CAPTIONS': 'cc1',
'AUDIO': 'aud1',
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v4/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud1',
'AVERAGE-BANDWIDTH': '7962844',
'BANDWIDTH': 7976430,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.64002a,mp4a.40.2',
'FRAME-RATE': 59.940,
'RESOLUTION': {
height: 1080,
width: 1920
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v8/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud1',
'AVERAGE-BANDWIDTH': '6165024',
'BANDWIDTH': 6181885,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.64002a,mp4a.40.2',
'FRAME-RATE': 59.940,
'RESOLUTION': {
height: 1080,
width: 1920
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v7/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud1',
'AVERAGE-BANDWIDTH': '4664459',
'BANDWIDTH': 4682666,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.64002a,mp4a.40.2',
'FRAME-RATE': 59.940,
'RESOLUTION': {
height: 1080,
width: 1920
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v6/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud1',
'AVERAGE-BANDWIDTH': '3164759',
'BANDWIDTH': 3170746,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.640020,mp4a.40.2',
'FRAME-RATE': 59.940,
'RESOLUTION': {
height: 720,
width: 1280
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v5/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud1',
'AVERAGE-BANDWIDTH': '1262552',
'BANDWIDTH': 1276223,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.64001e,mp4a.40.2',
'FRAME-RATE': 29.970,
'RESOLUTION': {
height: 432,
width: 768
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v3/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud1',
'AVERAGE-BANDWIDTH': '893243',
'BANDWIDTH': 904744,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.64001e,mp4a.40.2',
'FRAME-RATE': 29.970,
'RESOLUTION': {
height: 360,
width: 640
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v2/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud1',
'AVERAGE-BANDWIDTH': '527673',
'BANDWIDTH': 538201,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.640015,mp4a.40.2',
'FRAME-RATE': 29.970,
'RESOLUTION': {
height: 270,
width: 480
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v1/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud2',
'AVERAGE-BANDWIDTH': '2390334',
'BANDWIDTH': 2440329,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.640020,ac-3',
'FRAME-RATE': 59.940,
'RESOLUTION': {
height: 540,
width: 960
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v4/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud2',
'AVERAGE-BANDWIDTH': '8187954',
'BANDWIDTH': 8201540,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.64002a,ac-3',
'FRAME-RATE': 59.940,
'RESOLUTION': {
height: 1080,
width: 1920
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v8/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud2',
'AVERAGE-BANDWIDTH': '6390134',
'BANDWIDTH': 6406995,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.64002a,ac-3',
'FRAME-RATE': 59.940,
'RESOLUTION': {
height: 1080,
width: 1920
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v7/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud2',
'AVERAGE-BANDWIDTH': '4889569',
'BANDWIDTH': 4907776,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.64002a,ac-3',
'FRAME-RATE': 59.940,
'RESOLUTION': {
height: 1080,
width: 1920
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v6/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud2',
'AVERAGE-BANDWIDTH': '3389869',
'BANDWIDTH': 3395856,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.640020,ac-3',
'FRAME-RATE': 59.940,
'RESOLUTION': {
height: 720,
width: 1280
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v5/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud2',
'AVERAGE-BANDWIDTH': '1487662',
'BANDWIDTH': 1501333,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.64001e,ac-3',
'FRAME-RATE': 29.970,
'RESOLUTION': {
height: 432,
width: 768
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v3/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud2',
'AVERAGE-BANDWIDTH': '1118353',
'BANDWIDTH': 1129854,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.64001e,ac-3',
'FRAME-RATE': 29.970,
'RESOLUTION': {
height: 360,
width: 640
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v2/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud2',
'AVERAGE-BANDWIDTH': '752783',
'BANDWIDTH': 763311,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.640015,ac-3',
'FRAME-RATE': 29.970,
'RESOLUTION': {
height: 270,
width: 480
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v1/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud3',
'AVERAGE-BANDWIDTH': '2198334',
'BANDWIDTH': 2248329,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.640020,ec-3',
'FRAME-RATE': 59.940,
'RESOLUTION': {
height: 540,
width: 960
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v4/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud3',
'AVERAGE-BANDWIDTH': '7995954',
'BANDWIDTH': 8009540,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.64002a,ec-3',
'FRAME-RATE': 59.940,
'RESOLUTION': {
height: 1080,
width: 1920
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v8/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud3',
'AVERAGE-BANDWIDTH': '6198134',
'BANDWIDTH': 6214995,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.64002a,ec-3',
'FRAME-RATE': 59.940,
'RESOLUTION': {
height: 1080,
width: 1920
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v7/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud3',
'AVERAGE-BANDWIDTH': '4697569',
'BANDWIDTH': 4715776,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.64002a,ec-3',
'FRAME-RATE': 59.940,
'RESOLUTION': {
height: 1080,
width: 1920
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v6/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud3',
'AVERAGE-BANDWIDTH': '3197869',
'BANDWIDTH': 3203856,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.640020,ec-3',
'FRAME-RATE': 59.940,
'RESOLUTION': {
height: 720,
width: 1280
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v5/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud3',
'AVERAGE-BANDWIDTH': '1295662',
'BANDWIDTH': 1309333,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.64001e,ec-3',
'FRAME-RATE': 29.970,
'RESOLUTION': {
height: 432,
width: 768
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v3/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud3',
'AVERAGE-BANDWIDTH': '926353',
'BANDWIDTH': 937854,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.64001e,ec-3',
'FRAME-RATE': 29.970,
'RESOLUTION': {
height: 360,
width: 640
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v2/prog_index.m3u8'
},
{
attributes: {
'AUDIO': 'aud3',
'AVERAGE-BANDWIDTH': '560783',
'BANDWIDTH': 571311,
'CLOSED-CAPTIONS': 'cc1',
'CODECS': 'avc1.640015,ec-3',
'FRAME-RATE': 29.970,
'RESOLUTION': {
height: 270,
width: 480
},
'SUBTITLES': 'sub1'
},
timeline: 0,
uri: 'v1/prog_index.m3u8'
}],
segments: [],
version: 6,
independentSegments: true
};

View File

@@ -0,0 +1,76 @@
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud1",LANGUAGE="eng",NAME="English",AUTOSELECT=YES,DEFAULT=YES,URI="a1/prog_index.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud2",LANGUAGE="eng",NAME="English",AUTOSELECT=YES,DEFAULT=YES,URI="a2/prog_index.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud3",LANGUAGE="eng",NAME="English",AUTOSELECT=YES,DEFAULT=YES,URI="a3/prog_index.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="sub1",NAME="English",LANGUAGE="eng",DEFAULT=YES,AUTOSELECT=YES,FORCED=NO,URI="s1/eng/prog_index.m3u8"
#EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS,GROUP-ID="cc1",NAME="English",LANGUAGE="eng",DEFAULT=YES,AUTOSELECT=YES,INSTREAM-ID="CC1"
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=163198,BANDWIDTH=166942,CODECS="avc1.64002a",RESOLUTION=1920x1080,URI="v6/iframe_index.m3u8"
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=131314,BANDWIDTH=139041,CODECS="avc1.640020",RESOLUTION=1280x720,URI="v5/iframe_index.m3u8"
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=100233,BANDWIDTH=101724,CODECS="avc1.640020",RESOLUTION=960x540,URI="v4/iframe_index.m3u8"
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=81002,BANDWIDTH=84112,CODECS="avc1.64001e",RESOLUTION=768x432,URI="v3/iframe_index.m3u8"
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=64987,BANDWIDTH=65835,CODECS="avc1.64001e",RESOLUTION=640x360,URI="v2/iframe_index.m3u8"
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=41547,BANDWIDTH=42106,CODECS="avc1.640015",RESOLUTION=480x270,URI="v1/iframe_index.m3u8"
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=2165224,BANDWIDTH=2215219,CODECS="avc1.640020,mp4a.40.2",RESOLUTION=960x540,FRAME-RATE=59.940,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
v4/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=7962844,BANDWIDTH=7976430,CODECS="avc1.64002a,mp4a.40.2",RESOLUTION=1920x1080,FRAME-RATE=59.940,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
v8/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=6165024,BANDWIDTH=6181885,CODECS="avc1.64002a,mp4a.40.2",RESOLUTION=1920x1080,FRAME-RATE=59.940,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
v7/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=4664459,BANDWIDTH=4682666,CODECS="avc1.64002a,mp4a.40.2",RESOLUTION=1920x1080,FRAME-RATE=59.940,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
v6/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=3164759,BANDWIDTH=3170746,CODECS="avc1.640020,mp4a.40.2",RESOLUTION=1280x720,FRAME-RATE=59.940,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
v5/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=1262552,BANDWIDTH=1276223,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=768x432,FRAME-RATE=29.970,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
v3/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=893243,BANDWIDTH=904744,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,FRAME-RATE=29.970,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
v2/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=527673,BANDWIDTH=538201,CODECS="avc1.640015,mp4a.40.2",RESOLUTION=480x270,FRAME-RATE=29.970,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
v1/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=2390334,BANDWIDTH=2440329,CODECS="avc1.640020,ac-3",RESOLUTION=960x540,FRAME-RATE=59.940,CLOSED-CAPTIONS="cc1",AUDIO="aud2",SUBTITLES="sub1"
v4/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=8187954,BANDWIDTH=8201540,CODECS="avc1.64002a,ac-3",RESOLUTION=1920x1080,FRAME-RATE=59.940,CLOSED-CAPTIONS="cc1",AUDIO="aud2",SUBTITLES="sub1"
v8/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=6390134,BANDWIDTH=6406995,CODECS="avc1.64002a,ac-3",RESOLUTION=1920x1080,FRAME-RATE=59.940,CLOSED-CAPTIONS="cc1",AUDIO="aud2",SUBTITLES="sub1"
v7/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=4889569,BANDWIDTH=4907776,CODECS="avc1.64002a,ac-3",RESOLUTION=1920x1080,FRAME-RATE=59.940,CLOSED-CAPTIONS="cc1",AUDIO="aud2",SUBTITLES="sub1"
v6/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=3389869,BANDWIDTH=3395856,CODECS="avc1.640020,ac-3",RESOLUTION=1280x720,FRAME-RATE=59.940,CLOSED-CAPTIONS="cc1",AUDIO="aud2",SUBTITLES="sub1"
v5/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=1487662,BANDWIDTH=1501333,CODECS="avc1.64001e,ac-3",RESOLUTION=768x432,FRAME-RATE=29.970,CLOSED-CAPTIONS="cc1",AUDIO="aud2",SUBTITLES="sub1"
v3/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=1118353,BANDWIDTH=1129854,CODECS="avc1.64001e,ac-3",RESOLUTION=640x360,FRAME-RATE=29.970,CLOSED-CAPTIONS="cc1",AUDIO="aud2",SUBTITLES="sub1"
v2/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=752783,BANDWIDTH=763311,CODECS="avc1.640015,ac-3",RESOLUTION=480x270,FRAME-RATE=29.970,CLOSED-CAPTIONS="cc1",AUDIO="aud2",SUBTITLES="sub1"
v1/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=2198334,BANDWIDTH=2248329,CODECS="avc1.640020,ec-3",RESOLUTION=960x540,FRAME-RATE=59.940,CLOSED-CAPTIONS="cc1",AUDIO="aud3",SUBTITLES="sub1"
v4/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=7995954,BANDWIDTH=8009540,CODECS="avc1.64002a,ec-3",RESOLUTION=1920x1080,FRAME-RATE=59.940,CLOSED-CAPTIONS="cc1",AUDIO="aud3",SUBTITLES="sub1"
v8/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=6198134,BANDWIDTH=6214995,CODECS="avc1.64002a,ec-3",RESOLUTION=1920x1080,FRAME-RATE=59.940,CLOSED-CAPTIONS="cc1",AUDIO="aud3",SUBTITLES="sub1"
v7/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=4697569,BANDWIDTH=4715776,CODECS="avc1.64002a,ec-3",RESOLUTION=1920x1080,FRAME-RATE=59.940,CLOSED-CAPTIONS="cc1",AUDIO="aud3",SUBTITLES="sub1"
v6/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=3197869,BANDWIDTH=3203856,CODECS="avc1.640020,ec-3",RESOLUTION=1280x720,FRAME-RATE=59.940,CLOSED-CAPTIONS="cc1",AUDIO="aud3",SUBTITLES="sub1"
v5/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=1295662,BANDWIDTH=1309333,CODECS="avc1.64001e,ec-3",RESOLUTION=768x432,FRAME-RATE=29.970,CLOSED-CAPTIONS="cc1",AUDIO="aud3",SUBTITLES="sub1"
v3/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=926353,BANDWIDTH=937854,CODECS="avc1.64001e,ec-3",RESOLUTION=640x360,FRAME-RATE=29.970,CLOSED-CAPTIONS="cc1",AUDIO="aud3",SUBTITLES="sub1"
v2/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=560783,BANDWIDTH=571311,CODECS="avc1.640015,ec-3",RESOLUTION=480x270,FRAME-RATE=29.970,CLOSED-CAPTIONS="cc1",AUDIO="aud3",SUBTITLES="sub1"
v1/prog_index.m3u8

View File

@@ -0,0 +1,59 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
playlists: [
{
attributes: {
'PROGRAM-ID': 1,
'BANDWIDTH': 240000,
'RESOLUTION': {
width: 396,
height: 224
}
},
timeline: 0,
uri: 'media.m3u8'
},
{
attributes: {
'PROGRAM-ID': 1,
'BANDWIDTH': 40000
},
timeline: 0,
uri: 'media1.m3u8'
},
{
attributes: {
'PROGRAM-ID': 1,
'BANDWIDTH': 440000,
'RESOLUTION': {
width: 396,
height: 224
}
},
timeline: 0,
uri: 'media2.m3u8'
},
{
attributes: {
'PROGRAM-ID': 1,
'BANDWIDTH': 1928000,
'RESOLUTION': {
width: 960,
height: 540
}
},
timeline: 0,
uri: 'media3.m3u8'
}
],
discontinuityStarts: [],
mediaGroups: {
'VIDEO': {},
'AUDIO': {},
'CLOSED-CAPTIONS': {},
'SUBTITLES': {}
},
segments: []
};

View File

@@ -0,0 +1,10 @@
# A simple master playlist with multiple variant streams
#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=240000,RESOLUTION=396x224
media.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=40000
media1.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=440000,RESOLUTION=396x224
media2.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1928000,RESOLUTION=960x540
media3.m3u8

View File

@@ -0,0 +1,33 @@
module.exports = {
allowCache: true,
dateRanges: [],
iFramePlaylists: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
{
duration: 10,
timeline: 0,
uri: 'media-00001.ts'
},
{
duration: 10,
timeline: 0,
uri: 'media-00002.ts'
},
{
duration: 10,
timeline: 0,
uri: 'media-00003.ts'
},
{
duration: 10,
timeline: 0,
uri: 'media-00004.ts'
}
],
targetDuration: 10,
endList: true,
discontinuitySequence: 0,
discontinuityStarts: []
};

View File

@@ -0,0 +1,12 @@
#EXTM3U
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-TARGETDURATION:10
#EXTINF:10,
media-00001.ts
#EXTINF:10,
media-00002.ts
#EXTINF:10,
media-00003.ts
#EXTINF:10,
media-00004.ts
#EXT-X-ENDLIST

Some files were not shown because too many files have changed in this diff Show More