These files should not be added
This commit is contained in:
168
build/javascript/node_modules/mpd-parser/CHANGELOG.md
generated
vendored
168
build/javascript/node_modules/mpd-parser/CHANGELOG.md
generated
vendored
@@ -1,168 +0,0 @@
|
||||
<a name="0.12.0"></a>
|
||||
# [0.12.0](https://github.com/videojs/mpd-parser/compare/v0.11.0...v0.12.0) (2020-09-03)
|
||||
|
||||
### Features
|
||||
|
||||
* remove default value of 0 for minimumUpdatePeriod ([#103](https://github.com/videojs/mpd-parser/issues/103)) ([38ca9ad](https://github.com/videojs/mpd-parser/commit/38ca9ad))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* The minimumUpdatePeriod property is now omitted from parsed output if it is not present in the manifest, rather than using a default value of 0. This is to allow differentiation between cases when a value of 0 is present in the manifest and when no value is provided.
|
||||
|
||||
<a name="0.11.0"></a>
|
||||
# [0.11.0](https://github.com/videojs/mpd-parser/compare/v0.10.1...v0.11.0) (2020-08-12)
|
||||
|
||||
### Features
|
||||
|
||||
* parse out Location elements ([#102](https://github.com/videojs/mpd-parser/issues/102)) ([967e5e6](https://github.com/videojs/mpd-parser/commit/967e5e6))
|
||||
|
||||
<a name="0.10.1"></a>
|
||||
## [0.10.1](https://github.com/videojs/mpd-parser/compare/v0.10.0...v0.10.1) (2020-03-31)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* don't adjust mediaPresentationDuration by timescale for segment duration when using SegmentBase ([#94](https://github.com/videojs/mpd-parser/issues/94)) ([40cdd00](https://github.com/videojs/mpd-parser/commit/40cdd00))
|
||||
|
||||
<a name="0.10.0"></a>
|
||||
# [0.10.0](https://github.com/videojs/mpd-parser/compare/v0.9.0...v0.10.0) (2020-02-04)
|
||||
|
||||
### Features
|
||||
|
||||
* expose suggestPresentationDelay if the type is dynamic ([#82](https://github.com/videojs/mpd-parser/issues/82)) ([cd27003](https://github.com/videojs/mpd-parser/commit/cd27003))
|
||||
|
||||
<a name="0.9.0"></a>
|
||||
# [0.9.0](https://github.com/videojs/mpd-parser/compare/v0.8.2...v0.9.0) (2019-08-30)
|
||||
|
||||
### Features
|
||||
|
||||
* node support ([#75](https://github.com/videojs/mpd-parser/issues/75)) ([58b43b0](https://github.com/videojs/mpd-parser/commit/58b43b0))
|
||||
|
||||
<a name="0.8.2"></a>
|
||||
## [0.8.2](https://github.com/videojs/mpd-parser/compare/v0.8.1...v0.8.2) (2019-08-22)
|
||||
|
||||
### Chores
|
||||
|
||||
* update generator and use [@videojs](https://github.com/videojs)/vhs-utils ([#76](https://github.com/videojs/mpd-parser/issues/76)) ([1238749](https://github.com/videojs/mpd-parser/commit/1238749))
|
||||
|
||||
<a name="0.8.1"></a>
|
||||
## [0.8.1](https://github.com/videojs/mpd-parser/compare/v0.8.0...v0.8.1) (2019-05-01)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* skip playlists without sidx ([#73](https://github.com/videojs/mpd-parser/issues/73)) ([67d2bad](https://github.com/videojs/mpd-parser/commit/67d2bad)), closes [videojs/video.js#5289](https://github.com/videojs/video.js/issues/5289)
|
||||
|
||||
<a name="0.8.0"></a>
|
||||
# [0.8.0](https://github.com/videojs/mpd-parser/compare/v0.7.0...v0.8.0) (2019-04-11)
|
||||
|
||||
### Features
|
||||
|
||||
* add sidx information to segment base playlists ([#41](https://github.com/videojs/mpd-parser/issues/41)) ([1176109](https://github.com/videojs/mpd-parser/commit/1176109))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* make byteRange.length inclusive ([#43](https://github.com/videojs/mpd-parser/issues/43)) ([28d217a](https://github.com/videojs/mpd-parser/commit/28d217a))
|
||||
|
||||
### Chores
|
||||
|
||||
* add netlify for testing ([#45](https://github.com/videojs/mpd-parser/issues/45)) ([a78a7be](https://github.com/videojs/mpd-parser/commit/a78a7be))
|
||||
* Update videojs-generate-karma-config to the latest version 🚀 ([#37](https://github.com/videojs/mpd-parser/issues/37)) ([a18c660](https://github.com/videojs/mpd-parser/commit/a18c660))
|
||||
* Update videojs-generate-karma-config to the latest version 🚀 ([#38](https://github.com/videojs/mpd-parser/issues/38)) ([3aaabac](https://github.com/videojs/mpd-parser/commit/3aaabac))
|
||||
* Update videojs-generate-rollup-config to the latest version 🚀 ([#36](https://github.com/videojs/mpd-parser/issues/36)) ([3f6ccbd](https://github.com/videojs/mpd-parser/commit/3f6ccbd))
|
||||
* **package:** update videojs-generate-karma-config to 5.0.2 ([#54](https://github.com/videojs/mpd-parser/issues/54)) ([fcbabc3](https://github.com/videojs/mpd-parser/commit/fcbabc3))
|
||||
* **package:** videojs-generate-karma-config[@4](https://github.com/4).0.0 does not exist ([#44](https://github.com/videojs/mpd-parser/issues/44)) ([bc361b5](https://github.com/videojs/mpd-parser/commit/bc361b5))
|
||||
|
||||
<a name="0.7.0"></a>
|
||||
# [0.7.0](https://github.com/videojs/mpd-parser/compare/v0.6.1...v0.7.0) (2018-10-24)
|
||||
|
||||
### Features
|
||||
|
||||
* limited multiperiod support ([#35](https://github.com/videojs/mpd-parser/issues/35)) ([aee87a0](https://github.com/videojs/mpd-parser/commit/aee87a0))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fixed segment timeline parsing when duration is present ([#34](https://github.com/videojs/mpd-parser/issues/34)) ([90feb2d](https://github.com/videojs/mpd-parser/commit/90feb2d))
|
||||
* Remove the postinstall script to prevent install issues ([#29](https://github.com/videojs/mpd-parser/issues/29)) ([ae458f4](https://github.com/videojs/mpd-parser/commit/ae458f4))
|
||||
|
||||
### Chores
|
||||
|
||||
* Update to generator-videojs-plugin[@7](https://github.com/7).2.0 ([#28](https://github.com/videojs/mpd-parser/issues/28)) ([909cf08](https://github.com/videojs/mpd-parser/commit/909cf08))
|
||||
* **package:** Update dependencies to enable Greenkeeper 🌴 ([#30](https://github.com/videojs/mpd-parser/issues/30)) ([0593c2c](https://github.com/videojs/mpd-parser/commit/0593c2c))
|
||||
|
||||
<a name="0.6.1"></a>
|
||||
## [0.6.1](https://github.com/videojs/mpd-parser/compare/v0.6.0...v0.6.1) (2018-05-17)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* babel es module ([#25](https://github.com/videojs/mpd-parser/issues/25)) ([9a84461](https://github.com/videojs/mpd-parser/commit/9a84461))
|
||||
|
||||
<a name="0.6.0"></a>
|
||||
# [0.6.0](https://github.com/videojs/mpd-parser/compare/v0.5.0...v0.6.0) (2018-03-30)
|
||||
|
||||
### Features
|
||||
|
||||
* support in-manifest DRM data ([#23](https://github.com/videojs/mpd-parser/issues/23)) ([7ce9aca](https://github.com/videojs/mpd-parser/commit/7ce9aca))
|
||||
|
||||
<a name="0.5.0"></a>
|
||||
# [0.5.0](https://github.com/videojs/mpd-parser/compare/v0.4.0...v0.5.0) (2018-03-15)
|
||||
|
||||
### Features
|
||||
|
||||
* live support with SegmentTemplate[@duration](https://github.com/duration) and more ([#22](https://github.com/videojs/mpd-parser/issues/22)) ([f1cee87](https://github.com/videojs/mpd-parser/commit/f1cee87))
|
||||
|
||||
<a name="0.4.0"></a>
|
||||
# [0.4.0](https://github.com/videojs/mpd-parser/compare/v0.3.0...v0.4.0) (2018-02-26)
|
||||
|
||||
### Features
|
||||
|
||||
* Adding support for segments in Period and Representation. ([#19](https://github.com/videojs/mpd-parser/issues/19)) ([8e59b38](https://github.com/videojs/mpd-parser/commit/8e59b38))
|
||||
|
||||
<a name="0.3.0"></a>
|
||||
# [0.3.0](https://github.com/videojs/mpd-parser/compare/v0.2.1...v0.3.0) (2018-02-06)
|
||||
|
||||
### Features
|
||||
|
||||
* Parse <SegmentList> and <SegmentBase> ([#18](https://github.com/videojs/mpd-parser/issues/18)) ([71b8976](https://github.com/videojs/mpd-parser/commit/71b8976))
|
||||
* Support for inheriting BaseURL and alternate BaseURLs ([#17](https://github.com/videojs/mpd-parser/issues/17)) ([7dad5d5](https://github.com/videojs/mpd-parser/commit/7dad5d5))
|
||||
* add support for SegmentTemplate padding format string and SegmentTimeline ([#16](https://github.com/videojs/mpd-parser/issues/16)) ([87933f6](https://github.com/videojs/mpd-parser/commit/87933f6))
|
||||
|
||||
<a name="0.2.1"></a>
|
||||
## [0.2.1](https://github.com/videojs/mpd-parser/compare/v0.2.0...v0.2.1) (2017-12-15)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* access HTMLCollections with IE11 compatibility ([#15](https://github.com/videojs/mpd-parser/issues/15)) ([5612984](https://github.com/videojs/mpd-parser/commit/5612984))
|
||||
|
||||
<a name="0.2.0"></a>
|
||||
# [0.2.0](https://github.com/videojs/mpd-parser/compare/v0.1.1...v0.2.0) (2017-12-12)
|
||||
|
||||
### Features
|
||||
|
||||
* Support for vtt ([#13](https://github.com/videojs/mpd-parser/issues/13)) ([96fc406](https://github.com/videojs/mpd-parser/commit/96fc406))
|
||||
|
||||
### Tests
|
||||
|
||||
* add more tests for vtt ([#14](https://github.com/videojs/mpd-parser/issues/14)) ([4068790](https://github.com/videojs/mpd-parser/commit/4068790))
|
||||
|
||||
<a name="0.1.1"></a>
|
||||
## [0.1.1](https://github.com/videojs/mpd-parser/compare/v0.1.0...v0.1.1) (2017-12-07)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* avoid using Array.prototype.fill for IE support ([#11](https://github.com/videojs/mpd-parser/issues/11)) ([5c444de](https://github.com/videojs/mpd-parser/commit/5c444de))
|
||||
|
||||
<a name="0.1.0"></a>
|
||||
# 0.1.0 (2017-11-29)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* switch off in-manifest caption support ([#8](https://github.com/videojs/mpd-parser/issues/8)) ([15712c6](https://github.com/videojs/mpd-parser/commit/15712c6))
|
||||
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
## HEAD (Unreleased)
|
||||
_(none)_
|
||||
|
||||
--------------------
|
||||
|
||||
30
build/javascript/node_modules/mpd-parser/CONTRIBUTING.md
generated
vendored
30
build/javascript/node_modules/mpd-parser/CONTRIBUTING.md
generated
vendored
@@ -1,30 +0,0 @@
|
||||
# CONTRIBUTING
|
||||
|
||||
We welcome contributions from everyone!
|
||||
|
||||
## Getting Started
|
||||
|
||||
Make sure you have NodeJS 4.0 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
build/javascript/node_modules/mpd-parser/LICENSE
generated
vendored
13
build/javascript/node_modules/mpd-parser/LICENSE
generated
vendored
@@ -1,13 +0,0 @@
|
||||
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.
|
||||
164
build/javascript/node_modules/mpd-parser/README.md
generated
vendored
164
build/javascript/node_modules/mpd-parser/README.md
generated
vendored
@@ -1,164 +0,0 @@
|
||||
# mpd-parser
|
||||
|
||||
[](https://travis-ci.org/videojs/mpd-parser)
|
||||
[](https://greenkeeper.io/)
|
||||
[](http://slack.videojs.com)
|
||||
|
||||
[](https://nodei.co/npm/mpd-parser/)
|
||||
|
||||
mpd parser
|
||||
|
||||
## Table of Contents
|
||||
|
||||
<!-- 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)
|
||||
- [Parsed Output](#parsed-output)
|
||||
- [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 mpd-parser
|
||||
```
|
||||
|
||||
The npm installation is preferred, but Bower works, too.
|
||||
|
||||
```sh
|
||||
bower install --save mpd-parser
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
var manifest = [
|
||||
'<>',
|
||||
'<>',
|
||||
].join('\n');
|
||||
|
||||
var parsedManifest = mpdParser.parse(manifest, manifestUrl);
|
||||
```
|
||||
|
||||
### Parsed Output
|
||||
|
||||
The parser ouputs a plain javascript object with the following structure:
|
||||
|
||||
```js
|
||||
Manifest {
|
||||
allowCache: boolean,
|
||||
endList: boolean,
|
||||
mediaSequence: number,
|
||||
discontinuitySequence: number,
|
||||
playlistType: string,
|
||||
playlists: [
|
||||
{
|
||||
attributes: {},
|
||||
Manifest
|
||||
}
|
||||
],
|
||||
mediaGroups: {
|
||||
AUDIO: {
|
||||
'GROUP-ID': {
|
||||
default: boolean,
|
||||
autoselect: boolean,
|
||||
language: string,
|
||||
uri: string,
|
||||
instreamId: string,
|
||||
characteristics: string,
|
||||
forced: boolean
|
||||
}
|
||||
},
|
||||
VIDEO: {},
|
||||
'CLOSED-CAPTIONS': {},
|
||||
SUBTITLES: {}
|
||||
},
|
||||
dateTimeString: string,
|
||||
dateTimeObject: Date,
|
||||
targetDuration: number,
|
||||
totalDuration: number,
|
||||
discontinuityStarts: [number],
|
||||
segments: [
|
||||
{
|
||||
byterange: {
|
||||
length: number,
|
||||
offset: number
|
||||
},
|
||||
duration: number,
|
||||
attributes: {},
|
||||
discontinuity: number,
|
||||
uri: string,
|
||||
timeline: number,
|
||||
key: {
|
||||
method: string,
|
||||
uri: string,
|
||||
iv: string
|
||||
},
|
||||
map: {
|
||||
uri: string,
|
||||
byterange: {
|
||||
length: number,
|
||||
offset: number
|
||||
}
|
||||
},
|
||||
'cue-out': string,
|
||||
'cue-out-cont': string,
|
||||
'cue-in': string
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Including the Parser
|
||||
|
||||
To include mpd-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/mpd-parser.min.js"></script>
|
||||
<script>
|
||||
var mpdParser = window['mpd-parser'];
|
||||
var parsedManifest = mpdParser.parse(manifest, manifestUrl);
|
||||
</script>
|
||||
```
|
||||
|
||||
### Browserify
|
||||
|
||||
When using with Browserify, install mpd-parser via npm and `require` the parser as you would any other module.
|
||||
|
||||
```js
|
||||
var mpdParser = require('mpd-parser');
|
||||
|
||||
var parsedManifest = mpdParser.parse(manifest, manifestUrl);
|
||||
```
|
||||
|
||||
With ES6:
|
||||
```js
|
||||
import { parse } from 'mpd-parser';
|
||||
|
||||
const parsedManifest = parse(manifest, manifestUrl);
|
||||
```
|
||||
|
||||
### 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(['mpd-parser'], function(mpdParser) {
|
||||
var parsedManifest = mpdParser.parse(manifest, manifestUrl);
|
||||
});
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0. Copyright (c) Brightcove, Inc
|
||||
48
build/javascript/node_modules/mpd-parser/index.html
generated
vendored
48
build/javascript/node_modules/mpd-parser/index.html
generated
vendored
@@ -1,48 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>mpd-parser Demo</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Open dev tools to try it out</p>
|
||||
<ul>
|
||||
<li><a id="test/debug.html">Run unit tests in browser.</a></li>
|
||||
<li><a id="docs" href="docs/api/">Read generated docs.</a></li>
|
||||
</ul>
|
||||
|
||||
<form id=parse>
|
||||
<label>
|
||||
Video URL:
|
||||
<input id=url type=url value="http://dash.edgesuite.net/akamai/bbb_30fps/bbb_30fps.mpd">
|
||||
</label>
|
||||
<button type=submit>Parse</button>
|
||||
</form>
|
||||
|
||||
<script src="dist/mpd-parser.js"></script>
|
||||
<script>
|
||||
(function(window, mpdParser) {
|
||||
var parseForm = document.getElementById('parse');
|
||||
var url = document.getElementById('url');
|
||||
|
||||
parseForm.addEventListener('submit', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
fetch(url.value)
|
||||
.then(function(response) {
|
||||
return response.text();
|
||||
}).then(function(body) {
|
||||
console.log('Original ->');
|
||||
console.log(body);
|
||||
|
||||
var parsedMpd = mpdParser.parse(body, url.value);
|
||||
console.log('Parsed ->');
|
||||
console.log(parsedMpd);
|
||||
}).catch(error => console.error(error));
|
||||
|
||||
return false;
|
||||
});
|
||||
}(window, window.mpdParser));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
36
build/javascript/node_modules/mpd-parser/node_modules/@videojs/vhs-utils/CHANGELOG.md
generated
vendored
36
build/javascript/node_modules/mpd-parser/node_modules/@videojs/vhs-utils/CHANGELOG.md
generated
vendored
@@ -1,36 +0,0 @@
|
||||
<a name="1.3.0"></a>
|
||||
# [1.3.0](https://github.com/videojs/vhs-utils/compare/v1.2.1...v1.3.0) (2020-02-05)
|
||||
|
||||
### Features
|
||||
|
||||
* add forEachMediaGroup in media-groups module (#8) ([a1eacf4](https://github.com/videojs/vhs-utils/commit/a1eacf4)), closes [#8](https://github.com/videojs/vhs-utils/issues/8)
|
||||
|
||||
<a name="1.2.1"></a>
|
||||
## [1.2.1](https://github.com/videojs/vhs-utils/compare/v1.2.0...v1.2.1) (2020-01-15)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* include videojs in VHS JSON media type (#7) ([da072f0](https://github.com/videojs/vhs-utils/commit/da072f0)), closes [#7](https://github.com/videojs/vhs-utils/issues/7)
|
||||
|
||||
<a name="1.2.0"></a>
|
||||
# [1.2.0](https://github.com/videojs/vhs-utils/compare/v1.1.0...v1.2.0) (2019-12-06)
|
||||
|
||||
### Features
|
||||
|
||||
* add media-types module with simpleTypeFromSourceType function (#4) ([d3ebd3f](https://github.com/videojs/vhs-utils/commit/d3ebd3f)), closes [#4](https://github.com/videojs/vhs-utils/issues/4)
|
||||
* add VHS codec parsing and translation functions (#5) ([4fe0e22](https://github.com/videojs/vhs-utils/commit/4fe0e22)), closes [#5](https://github.com/videojs/vhs-utils/issues/5)
|
||||
|
||||
<a name="1.1.0"></a>
|
||||
# [1.1.0](https://github.com/videojs/stream/compare/v1.0.0...v1.1.0) (2019-08-30)
|
||||
|
||||
### Features
|
||||
|
||||
* node support and more stream tests ([315ab8d](https://github.com/videojs/stream/commit/315ab8d))
|
||||
|
||||
<a name="1.0.0"></a>
|
||||
# 1.0.0 (2019-08-21)
|
||||
|
||||
### Features
|
||||
|
||||
* clones from mpd-parser, m3u8-parser, mux.js, aes-decrypter, and vhs ([5e89042](https://github.com/videojs/stream/commit/5e89042))
|
||||
|
||||
30
build/javascript/node_modules/mpd-parser/node_modules/@videojs/vhs-utils/CONTRIBUTING.md
generated
vendored
30
build/javascript/node_modules/mpd-parser/node_modules/@videojs/vhs-utils/CONTRIBUTING.md
generated
vendored
@@ -1,30 +0,0 @@
|
||||
# CONTRIBUTING
|
||||
|
||||
We welcome contributions from everyone!
|
||||
|
||||
## Getting Started
|
||||
|
||||
Make sure you have Node.js 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
|
||||
19
build/javascript/node_modules/mpd-parser/node_modules/@videojs/vhs-utils/LICENSE
generated
vendored
19
build/javascript/node_modules/mpd-parser/node_modules/@videojs/vhs-utils/LICENSE
generated
vendored
@@ -1,19 +0,0 @@
|
||||
Copyright (c) brandonocasey <brandonocasey@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
29
build/javascript/node_modules/mpd-parser/node_modules/@videojs/vhs-utils/README.md
generated
vendored
29
build/javascript/node_modules/mpd-parser/node_modules/@videojs/vhs-utils/README.md
generated
vendored
@@ -1,29 +0,0 @@
|
||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
|
||||
|
||||
- [@videojs/vhs-utils](#videojsvhs-utils)
|
||||
- [Installation](#installation)
|
||||
- [Usage](#usage)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
# @videojs/vhs-utils
|
||||
|
||||
vhs-utils serves two purposes:
|
||||
|
||||
1. It extracts objects and functions shared throughout @videojs/http-streaming code to save on package size. See [the original @videojs/http-streaming PR](https://github.com/videojs/http-streaming/pull/637) for details.
|
||||
2. It exports generic functions from VHS that may be useful to plugin authors.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
npm install --save @videojs/vhs-utils
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
All utility functions are published under dist and can be required/imported like so:
|
||||
|
||||
`import resolveUrl from '@videojs/vhs-utils/dist/resolve-url';`
|
||||
`const resolveUrl = require('@videojs/vhs-utils/dist/resolve-url');`
|
||||
27
build/javascript/node_modules/mpd-parser/node_modules/@videojs/vhs-utils/index.html
generated
vendored
27
build/javascript/node_modules/mpd-parser/node_modules/@videojs/vhs-utils/index.html
generated
vendored
@@ -1,27 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>videojs-stream Demo</title>
|
||||
<link href="node_modules/video.js/dist/video-js.css" rel="stylesheet">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<video id="videojs-stream-player" class="video-js vjs-default-skin" controls>
|
||||
<source src="//vjs.zencdn.net/v/oceans.mp4" type='video/mp4'>
|
||||
<source src="//vjs.zencdn.net/v/oceans.webm" type='video/webm'>
|
||||
</video>
|
||||
<ul>
|
||||
<li><a href="/test/debug.html">Run unit tests in browser.</a></li>
|
||||
|
||||
</ul>
|
||||
<script src="node_modules/video.js/dist/video.js"></script>
|
||||
<script src="dist/videojs-stream.js"></script>
|
||||
<script>
|
||||
(function(window, videojs) {
|
||||
var examplePlayer = window.examplePlayer = videojs('videojs-stream-player');
|
||||
var stream = window.stream = examplePlayer.stream();
|
||||
}(window, window.videojs));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
120
build/javascript/node_modules/mpd-parser/node_modules/@videojs/vhs-utils/package.json
generated
vendored
120
build/javascript/node_modules/mpd-parser/node_modules/@videojs/vhs-utils/package.json
generated
vendored
@@ -1,120 +0,0 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
"@videojs/vhs-utils@1.3.0",
|
||||
"/home/runner/work/owncast/owncast/build/javascript"
|
||||
]
|
||||
],
|
||||
"_from": "@videojs/vhs-utils@1.3.0",
|
||||
"_id": "@videojs/vhs-utils@1.3.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-oiqXDtHQqDPun7JseWkirUHGrgdYdeF12goUut5z7vwAj4DmUufEPFJ4xK5hYGXGFDyDhk2rSFOR122Ze6qXyQ==",
|
||||
"_location": "/mpd-parser/@videojs/vhs-utils",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "@videojs/vhs-utils@1.3.0",
|
||||
"name": "@videojs/vhs-utils",
|
||||
"escapedName": "@videojs%2fvhs-utils",
|
||||
"scope": "@videojs",
|
||||
"rawSpec": "1.3.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "1.3.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/mpd-parser"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-1.3.0.tgz",
|
||||
"_spec": "1.3.0",
|
||||
"_where": "/home/runner/work/owncast/owncast/build/javascript",
|
||||
"author": {
|
||||
"name": "brandonocasey",
|
||||
"email": "brandonocasey@gmail.com"
|
||||
},
|
||||
"browserslist": [
|
||||
"defaults",
|
||||
"ie 11"
|
||||
],
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"global": "^4.3.2",
|
||||
"url-toolkit": "^2.1.6"
|
||||
},
|
||||
"description": "Objects and functions shared throughtout @videojs/http-streaming code",
|
||||
"devDependencies": {
|
||||
"@videojs/generator-helpers": "~1.2.0",
|
||||
"karma": "^4.0.0",
|
||||
"rollup": "^1.12.0",
|
||||
"sinon": "^7.2.2",
|
||||
"videojs-generate-karma-config": "~5.3.0",
|
||||
"videojs-generate-rollup-config": "~5.0.0",
|
||||
"videojs-generator-verify": "~1.2.0",
|
||||
"videojs-standard": "^8.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8",
|
||||
"npm": ">=5"
|
||||
},
|
||||
"files": [
|
||||
"CONTRIBUTING.md",
|
||||
"dist/",
|
||||
"docs/",
|
||||
"index.html",
|
||||
"scripts/",
|
||||
"src/",
|
||||
"test/"
|
||||
],
|
||||
"generator-videojs-plugin": {
|
||||
"version": "7.7.1"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
}
|
||||
},
|
||||
"keywords": [
|
||||
"videojs",
|
||||
"videojs-plugin"
|
||||
],
|
||||
"license": "MIT",
|
||||
"lint-staged": {
|
||||
"*.js": [
|
||||
"vjsstandard --fix",
|
||||
"git add"
|
||||
],
|
||||
"README.md": [
|
||||
"doctoc --notitle",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"name": "@videojs/vhs-utils",
|
||||
"scripts": {
|
||||
"build": "npm-run-all -s clean -p build:*",
|
||||
"build-prod": "cross-env-shell NO_TEST_BUNDLE=1 'npm run build'",
|
||||
"build-test": "cross-env-shell TEST_BUNDLE_ONLY=1 'npm run build'",
|
||||
"build:js": "rollup -c scripts/rollup.config.js",
|
||||
"clean": "shx rm -rf ./dist ./test/dist && shx mkdir -p ./dist ./test/dist",
|
||||
"lint": "vjsstandard",
|
||||
"posttest": "shx cat test/dist/coverage/text.txt",
|
||||
"prepublishOnly": "npm-run-all build-prod && vjsverify --verbose --skip-es-check",
|
||||
"preversion": "npm test",
|
||||
"server": "karma start scripts/karma.conf.js --singleRun=false --auto-watch",
|
||||
"start": "npm-run-all -p server watch",
|
||||
"test": "npm-run-all lint build-test && npm-run-all test:*",
|
||||
"test:browser": "karma start scripts/karma.conf.js",
|
||||
"test:node": "qunit test/dist/bundle.js",
|
||||
"update-changelog": "conventional-changelog -p videojs -i CHANGELOG.md -s",
|
||||
"version": "is-prerelease || npm run update-changelog && git add CHANGELOG.md",
|
||||
"watch": "npm-run-all -p watch:*",
|
||||
"watch:js": "npm run build:js -- -w"
|
||||
},
|
||||
"version": "1.3.0",
|
||||
"vjsstandard": {
|
||||
"ignore": [
|
||||
"dist",
|
||||
"docs",
|
||||
"test/dist"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
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!
|
||||
};
|
||||
@@ -1,42 +0,0 @@
|
||||
const generate = require('videojs-generate-rollup-config');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const BASE_DIR = path.join(__dirname, '..');
|
||||
const SRC_DIR = path.join(BASE_DIR, 'src');
|
||||
|
||||
const files = fs.readdirSync(SRC_DIR);
|
||||
|
||||
const shared = {
|
||||
externals(defaults) {
|
||||
defaults.module.push('url-toolkit');
|
||||
return defaults;
|
||||
}
|
||||
};
|
||||
const builds = [];
|
||||
|
||||
files.forEach(function(file, i) {
|
||||
const config = generate(Object.assign({}, shared, {
|
||||
input: path.relative(BASE_DIR, path.join(SRC_DIR, file)),
|
||||
distName: path.basename(file, path.extname(file))
|
||||
}));
|
||||
|
||||
// gaurd against test only builds
|
||||
if (config.builds.module) {
|
||||
const module = config.builds.module;
|
||||
|
||||
module.output = module.output.filter((o) => o.format === 'cjs');
|
||||
module.output[0].file = module.output[0].file.replace('.cjs.js', '.js');
|
||||
builds.push(module);
|
||||
}
|
||||
|
||||
// gaurd against production only builds
|
||||
// only add the last test bundle we generate as they are all the same
|
||||
if (i === (files.length - 1) && config.builds.test) {
|
||||
builds.push(config.builds.test);
|
||||
}
|
||||
});
|
||||
|
||||
// export the builds to rollup
|
||||
|
||||
export default builds;
|
||||
130
build/javascript/node_modules/mpd-parser/node_modules/@videojs/vhs-utils/src/codecs.js
generated
vendored
130
build/javascript/node_modules/mpd-parser/node_modules/@videojs/vhs-utils/src/codecs.js
generated
vendored
@@ -1,130 +0,0 @@
|
||||
/**
|
||||
* Replace the old apple-style `avc1.<dd>.<dd>` codec string with the standard
|
||||
* `avc1.<hhhhhh>`
|
||||
*
|
||||
* @param {string} codec
|
||||
* Codec string to translate
|
||||
* @return {string}
|
||||
* The translated codec string
|
||||
*/
|
||||
export const translateLegacyCodec = function(codec) {
|
||||
if (!codec) {
|
||||
return codec;
|
||||
}
|
||||
|
||||
return codec.replace(/avc1\.(\d+)\.(\d+)/i, function(orig, profile, avcLevel) {
|
||||
const profileHex = ('00' + Number(profile).toString(16)).slice(-2);
|
||||
const avcLevelHex = ('00' + Number(avcLevel).toString(16)).slice(-2);
|
||||
|
||||
return 'avc1.' + profileHex + '00' + avcLevelHex;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Replace the old apple-style `avc1.<dd>.<dd>` codec strings with the standard
|
||||
* `avc1.<hhhhhh>`
|
||||
*
|
||||
* @param {string[]} codecs
|
||||
* An array of codec strings to translate
|
||||
* @return {string[]}
|
||||
* The translated array of codec strings
|
||||
*/
|
||||
export const translateLegacyCodecs = function(codecs) {
|
||||
return codecs.map(translateLegacyCodec);
|
||||
};
|
||||
|
||||
/**
|
||||
* Replace codecs in the codec string with the old apple-style `avc1.<dd>.<dd>` to the
|
||||
* standard `avc1.<hhhhhh>`.
|
||||
*
|
||||
* @param {string} codecString
|
||||
* The codec string
|
||||
* @return {string}
|
||||
* The codec string with old apple-style codecs replaced
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
export const mapLegacyAvcCodecs = function(codecString) {
|
||||
return codecString.replace(/avc1\.(\d+)\.(\d+)/i, (match) => {
|
||||
return translateLegacyCodecs([match])[0];
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {Object} ParsedCodecInfo
|
||||
* @property {number} codecCount
|
||||
* Number of codecs parsed
|
||||
* @property {string} [videoCodec]
|
||||
* Parsed video codec (if found)
|
||||
* @property {string} [videoObjectTypeIndicator]
|
||||
* Video object type indicator (if found)
|
||||
* @property {string|null} audioProfile
|
||||
* Audio profile
|
||||
*/
|
||||
|
||||
/**
|
||||
* Parses a codec string to retrieve the number of codecs specified, the video codec and
|
||||
* object type indicator, and the audio profile.
|
||||
*
|
||||
* @param {string} [codecs]
|
||||
* The codec string to parse
|
||||
* @return {ParsedCodecInfo}
|
||||
* Parsed codec info
|
||||
*/
|
||||
export const parseCodecs = function(codecs = '') {
|
||||
const result = {
|
||||
codecCount: 0
|
||||
};
|
||||
|
||||
result.codecCount = codecs.split(',').length;
|
||||
result.codecCount = result.codecCount || 2;
|
||||
|
||||
// parse the video codec
|
||||
const parsed = (/(^|\s|,)+(avc[13])([^ ,]*)/i).exec(codecs);
|
||||
|
||||
if (parsed) {
|
||||
result.videoCodec = parsed[2];
|
||||
result.videoObjectTypeIndicator = parsed[3];
|
||||
}
|
||||
|
||||
// parse the last field of the audio codec
|
||||
result.audioProfile =
|
||||
(/(^|\s|,)+mp4a.[0-9A-Fa-f]+\.([0-9A-Fa-f]+)/i).exec(codecs);
|
||||
result.audioProfile = result.audioProfile && result.audioProfile[2];
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a ParsedCodecInfo object for the default alternate audio playlist if there is
|
||||
* a default alternate audio playlist for the provided audio group.
|
||||
*
|
||||
* @param {Object} master
|
||||
* The master playlist
|
||||
* @param {string} audioGroupId
|
||||
* ID of the audio group for which to find the default codec info
|
||||
* @return {ParsedCodecInfo}
|
||||
* Parsed codec info
|
||||
*/
|
||||
export const audioProfileFromDefault = (master, audioGroupId) => {
|
||||
if (!master.mediaGroups.AUDIO || !audioGroupId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const audioGroup = master.mediaGroups.AUDIO[audioGroupId];
|
||||
|
||||
if (!audioGroup) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (const name in audioGroup) {
|
||||
const audioType = audioGroup[name];
|
||||
|
||||
if (audioType.default && audioType.playlists) {
|
||||
// codec should be the same for all playlists within the audio type
|
||||
return parseCodecs(audioType.playlists[0].attributes.CODECS).audioProfile;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
@@ -1,13 +0,0 @@
|
||||
import window from 'global/window';
|
||||
|
||||
const atob = (s) => window.atob ? window.atob(s) : Buffer.from(s, 'base64').toString('binary');
|
||||
|
||||
export default function decodeB64ToUint8Array(b64Text) {
|
||||
const decodedString = atob(b64Text);
|
||||
const array = new Uint8Array(decodedString.length);
|
||||
|
||||
for (let i = 0; i < decodedString.length; i++) {
|
||||
array[i] = decodedString.charCodeAt(i);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/**
|
||||
* Loops through all supported media groups in master and calls the provided
|
||||
* callback for each group
|
||||
*
|
||||
* @param {Object} master
|
||||
* The parsed master manifest object
|
||||
* @param {string[]} groups
|
||||
* The media groups to call the callback for
|
||||
* @param {Function} callback
|
||||
* Callback to call for each media group
|
||||
*/
|
||||
export const forEachMediaGroup = (master, groups, callback) => {
|
||||
groups.forEach((mediaType) => {
|
||||
for (const groupKey in master.mediaGroups[mediaType]) {
|
||||
for (const labelKey in master.mediaGroups[mediaType][groupKey]) {
|
||||
const mediaProperties = master.mediaGroups[mediaType][groupKey][labelKey];
|
||||
|
||||
callback(mediaProperties, mediaType, groupKey, labelKey);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -1,36 +0,0 @@
|
||||
const MPEGURL_REGEX = /^(audio|video|application)\/(x-|vnd\.apple\.)?mpegurl/i;
|
||||
const DASH_REGEX = /^application\/dash\+xml/i;
|
||||
|
||||
/**
|
||||
* Returns a string that describes the type of source based on a video source object's
|
||||
* media type.
|
||||
*
|
||||
* @see {@link https://dev.w3.org/html5/pf-summary/video.html#dom-source-type|Source Type}
|
||||
*
|
||||
* @param {string} type
|
||||
* Video source object media type
|
||||
* @return {('hls'|'dash'|'vhs-json'|null)}
|
||||
* VHS source type string
|
||||
*/
|
||||
export const simpleTypeFromSourceType = (type) => {
|
||||
if (MPEGURL_REGEX.test(type)) {
|
||||
return 'hls';
|
||||
}
|
||||
|
||||
if (DASH_REGEX.test(type)) {
|
||||
return 'dash';
|
||||
}
|
||||
|
||||
// Denotes the special case of a manifest object passed to http-streaming instead of a
|
||||
// source URL.
|
||||
//
|
||||
// See https://en.wikipedia.org/wiki/Media_type for details on specifying media types.
|
||||
//
|
||||
// In this case, vnd stands for vendor, video.js for the organization, VHS for this
|
||||
// project, and the +json suffix identifies the structure of the media type.
|
||||
if (type === 'application/vnd.videojs.vhs+json') {
|
||||
return 'vhs-json';
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
@@ -1,18 +0,0 @@
|
||||
import URLToolkit from 'url-toolkit';
|
||||
import window from 'global/window';
|
||||
|
||||
const resolveUrl = (baseUrl, relativeUrl) => {
|
||||
// return early if we don't need to resolve
|
||||
if ((/^[a-z]+:/i).test(relativeUrl)) {
|
||||
return relativeUrl;
|
||||
}
|
||||
|
||||
// if the base URL is relative then combine with the current location
|
||||
if (!(/\/\//i).test(baseUrl)) {
|
||||
baseUrl = URLToolkit.buildAbsoluteURL(window.location && window.location.href || '', baseUrl);
|
||||
}
|
||||
|
||||
return URLToolkit.buildAbsoluteURL(baseUrl, relativeUrl);
|
||||
};
|
||||
|
||||
export default resolveUrl;
|
||||
108
build/javascript/node_modules/mpd-parser/node_modules/@videojs/vhs-utils/src/stream.js
generated
vendored
108
build/javascript/node_modules/mpd-parser/node_modules/@videojs/vhs-utils/src/stream.js
generated
vendored
@@ -1,108 +0,0 @@
|
||||
/**
|
||||
* @file stream.js
|
||||
*/
|
||||
/**
|
||||
* A lightweight readable stream implemention that handles event dispatching.
|
||||
*
|
||||
* @class Stream
|
||||
*/
|
||||
export default class Stream {
|
||||
constructor() {
|
||||
this.listeners = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a listener for a specified event type.
|
||||
*
|
||||
* @param {string} type the event name
|
||||
* @param {Function} listener the callback to be invoked when an event of
|
||||
* the specified type occurs
|
||||
*/
|
||||
on(type, listener) {
|
||||
if (!this.listeners[type]) {
|
||||
this.listeners[type] = [];
|
||||
}
|
||||
this.listeners[type].push(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a listener for a specified event type.
|
||||
*
|
||||
* @param {string} type the event name
|
||||
* @param {Function} listener a function previously registered for this
|
||||
* type of event through `on`
|
||||
* @return {boolean} if we could turn it off or not
|
||||
*/
|
||||
off(type, listener) {
|
||||
if (!this.listeners[type]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const index = this.listeners[type].indexOf(listener);
|
||||
|
||||
// TODO: which is better?
|
||||
// In Video.js we slice listener functions
|
||||
// on trigger so that it does not mess up the order
|
||||
// while we loop through.
|
||||
//
|
||||
// Here we slice on off so that the loop in trigger
|
||||
// can continue using it's old reference to loop without
|
||||
// messing up the order.
|
||||
this.listeners[type] = this.listeners[type].slice(0);
|
||||
this.listeners[type].splice(index, 1);
|
||||
return index > -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger an event of the specified type on this stream. Any additional
|
||||
* arguments to this function are passed as parameters to event listeners.
|
||||
*
|
||||
* @param {string} type the event name
|
||||
*/
|
||||
trigger(type) {
|
||||
const callbacks = this.listeners[type];
|
||||
|
||||
if (!callbacks) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Slicing the arguments on every invocation of this method
|
||||
// can add a significant amount of overhead. Avoid the
|
||||
// intermediate object creation for the common case of a
|
||||
// single callback argument
|
||||
if (arguments.length === 2) {
|
||||
const length = callbacks.length;
|
||||
|
||||
for (let i = 0; i < length; ++i) {
|
||||
callbacks[i].call(this, arguments[1]);
|
||||
}
|
||||
} else {
|
||||
const args = Array.prototype.slice.call(arguments, 1);
|
||||
const length = callbacks.length;
|
||||
|
||||
for (let i = 0; i < length; ++i) {
|
||||
callbacks[i].apply(this, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the stream and cleans up.
|
||||
*/
|
||||
dispose() {
|
||||
this.listeners = {};
|
||||
}
|
||||
/**
|
||||
* Forwards all `data` events on this stream to the destination stream. The
|
||||
* destination stream should provide a method `push` to receive the data
|
||||
* events as they arrive.
|
||||
*
|
||||
* @param {Stream} destination the stream that will receive all `data` events
|
||||
* @see http://nodejs.org/api/stream.html#stream_readable_pipe_destination_options
|
||||
*/
|
||||
pipe(destination) {
|
||||
this.on('data', function(data) {
|
||||
destination.push(data);
|
||||
});
|
||||
}
|
||||
}
|
||||
242
build/javascript/node_modules/mpd-parser/node_modules/@videojs/vhs-utils/test/codecs.test.js
generated
vendored
242
build/javascript/node_modules/mpd-parser/node_modules/@videojs/vhs-utils/test/codecs.test.js
generated
vendored
@@ -1,242 +0,0 @@
|
||||
import QUnit from 'qunit';
|
||||
import {
|
||||
mapLegacyAvcCodecs,
|
||||
translateLegacyCodecs,
|
||||
parseCodecs,
|
||||
audioProfileFromDefault
|
||||
} from '../src/codecs';
|
||||
|
||||
QUnit.module('Legacy Codecs');
|
||||
|
||||
QUnit.test('maps legacy AVC codecs', function(assert) {
|
||||
assert.equal(
|
||||
mapLegacyAvcCodecs('avc1.deadbeef'),
|
||||
'avc1.deadbeef',
|
||||
'does nothing for non legacy pattern'
|
||||
);
|
||||
assert.equal(
|
||||
mapLegacyAvcCodecs('avc1.dead.beef, mp4a.something'),
|
||||
'avc1.dead.beef, mp4a.something',
|
||||
'does nothing for non legacy pattern'
|
||||
);
|
||||
assert.equal(
|
||||
mapLegacyAvcCodecs('avc1.dead.beef,mp4a.something'),
|
||||
'avc1.dead.beef,mp4a.something',
|
||||
'does nothing for non legacy pattern'
|
||||
);
|
||||
assert.equal(
|
||||
mapLegacyAvcCodecs('mp4a.something,avc1.dead.beef'),
|
||||
'mp4a.something,avc1.dead.beef',
|
||||
'does nothing for non legacy pattern'
|
||||
);
|
||||
assert.equal(
|
||||
mapLegacyAvcCodecs('mp4a.something, avc1.dead.beef'),
|
||||
'mp4a.something, avc1.dead.beef',
|
||||
'does nothing for non legacy pattern'
|
||||
);
|
||||
assert.equal(
|
||||
mapLegacyAvcCodecs('avc1.42001e'),
|
||||
'avc1.42001e',
|
||||
'does nothing for non legacy pattern'
|
||||
);
|
||||
assert.equal(
|
||||
mapLegacyAvcCodecs('avc1.4d0020,mp4a.40.2'),
|
||||
'avc1.4d0020,mp4a.40.2',
|
||||
'does nothing for non legacy pattern'
|
||||
);
|
||||
assert.equal(
|
||||
mapLegacyAvcCodecs('mp4a.40.2,avc1.4d0020'),
|
||||
'mp4a.40.2,avc1.4d0020',
|
||||
'does nothing for non legacy pattern'
|
||||
);
|
||||
assert.equal(
|
||||
mapLegacyAvcCodecs('mp4a.40.40'),
|
||||
'mp4a.40.40',
|
||||
'does nothing for non video codecs'
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
mapLegacyAvcCodecs('avc1.66.30'),
|
||||
'avc1.42001e',
|
||||
'translates legacy video codec alone'
|
||||
);
|
||||
assert.equal(
|
||||
mapLegacyAvcCodecs('avc1.66.30, mp4a.40.2'),
|
||||
'avc1.42001e, mp4a.40.2',
|
||||
'translates legacy video codec when paired with audio'
|
||||
);
|
||||
assert.equal(
|
||||
mapLegacyAvcCodecs('mp4a.40.2, avc1.66.30'),
|
||||
'mp4a.40.2, avc1.42001e',
|
||||
'translates video codec when specified second'
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('translates legacy codecs', function(assert) {
|
||||
assert.deepEqual(
|
||||
translateLegacyCodecs(['avc1.66.30', 'avc1.66.30']),
|
||||
['avc1.42001e', 'avc1.42001e'],
|
||||
'translates legacy avc1.66.30 codec'
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
translateLegacyCodecs(['avc1.42C01E', 'avc1.42C01E']),
|
||||
['avc1.42C01E', 'avc1.42C01E'],
|
||||
'does not translate modern codecs'
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
translateLegacyCodecs(['avc1.42C01E', 'avc1.66.30']),
|
||||
['avc1.42C01E', 'avc1.42001e'],
|
||||
'only translates legacy codecs when mixed'
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
translateLegacyCodecs(['avc1.4d0020', 'avc1.100.41', 'avc1.77.41',
|
||||
'avc1.77.32', 'avc1.77.31', 'avc1.77.30',
|
||||
'avc1.66.30', 'avc1.66.21', 'avc1.42C01e']),
|
||||
['avc1.4d0020', 'avc1.640029', 'avc1.4d0029',
|
||||
'avc1.4d0020', 'avc1.4d001f', 'avc1.4d001e',
|
||||
'avc1.42001e', 'avc1.420015', 'avc1.42C01e'],
|
||||
'translates a whole bunch'
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.module('parseCodecs');
|
||||
|
||||
QUnit.test('parses video only codec string', function(assert) {
|
||||
assert.deepEqual(
|
||||
parseCodecs('avc1.42001e'),
|
||||
{
|
||||
codecCount: 1,
|
||||
videoCodec: 'avc1',
|
||||
videoObjectTypeIndicator: '.42001e',
|
||||
audioProfile: null
|
||||
},
|
||||
'parsed video only codec string'
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('parses audio only codec string', function(assert) {
|
||||
assert.deepEqual(
|
||||
parseCodecs('mp4a.40.2'),
|
||||
{
|
||||
codecCount: 1,
|
||||
audioProfile: '2'
|
||||
},
|
||||
'parsed audio only codec string'
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('parses video and audio codec string', function(assert) {
|
||||
assert.deepEqual(
|
||||
parseCodecs('avc1.42001e, mp4a.40.2'),
|
||||
{
|
||||
codecCount: 2,
|
||||
videoCodec: 'avc1',
|
||||
videoObjectTypeIndicator: '.42001e',
|
||||
audioProfile: '2'
|
||||
},
|
||||
'parsed video and audio codec string'
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.module('audioProfileFromDefault');
|
||||
|
||||
QUnit.test('returns falsey when no audio group ID', function(assert) {
|
||||
assert.notOk(
|
||||
audioProfileFromDefault(
|
||||
{ mediaGroups: { AUDIO: {} } },
|
||||
'',
|
||||
),
|
||||
'returns falsey when no audio group ID'
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('returns falsey when no matching audio group', function(assert) {
|
||||
assert.notOk(
|
||||
audioProfileFromDefault(
|
||||
{
|
||||
mediaGroups: {
|
||||
AUDIO: {
|
||||
au1: {
|
||||
en: {
|
||||
default: false,
|
||||
playlists: [{
|
||||
attributes: { CODECS: 'mp4a.40.2' }
|
||||
}]
|
||||
},
|
||||
es: {
|
||||
default: true,
|
||||
playlists: [{
|
||||
attributes: { CODECS: 'mp4a.40.5' }
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'au2'
|
||||
),
|
||||
'returned falsey when no matching audio group'
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('returns falsey when no default for audio group', function(assert) {
|
||||
assert.notOk(
|
||||
audioProfileFromDefault(
|
||||
{
|
||||
mediaGroups: {
|
||||
AUDIO: {
|
||||
au1: {
|
||||
en: {
|
||||
default: false,
|
||||
playlists: [{
|
||||
attributes: { CODECS: 'mp4a.40.2' }
|
||||
}]
|
||||
},
|
||||
es: {
|
||||
default: false,
|
||||
playlists: [{
|
||||
attributes: { CODECS: 'mp4a.40.5' }
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'au1'
|
||||
),
|
||||
'returned falsey when no default for audio group'
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('returns audio profile for default in audio group', function(assert) {
|
||||
assert.deepEqual(
|
||||
audioProfileFromDefault(
|
||||
{
|
||||
mediaGroups: {
|
||||
AUDIO: {
|
||||
au1: {
|
||||
en: {
|
||||
default: false,
|
||||
playlists: [{
|
||||
attributes: { CODECS: 'mp4a.40.2' }
|
||||
}]
|
||||
},
|
||||
es: {
|
||||
default: true,
|
||||
playlists: [{
|
||||
attributes: { CODECS: 'mp4a.40.5' }
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'au1'
|
||||
),
|
||||
'5',
|
||||
'returned parsed codec audio profile'
|
||||
);
|
||||
});
|
||||
@@ -1,13 +0,0 @@
|
||||
import QUnit from 'qunit';
|
||||
import decodeB64ToUint8Array from '../src/decode-b64-to-uint8-array.js';
|
||||
|
||||
QUnit.module('decodeB64ToUint8Array');
|
||||
|
||||
// slightly modified version of m3u8 test
|
||||
// 'parses Widevine #EXT-X-KEY attributes and attaches to manifest'
|
||||
QUnit.test('can decode', function(assert) {
|
||||
const b64 = 'AAAAPnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAB4iFnNoYWthX2NlYzJmNjRhYTc4OTBhMTFI49yVmwY';
|
||||
const result = decodeB64ToUint8Array(b64);
|
||||
|
||||
assert.deepEqual(result.byteLength, 62, 'decoded');
|
||||
});
|
||||
@@ -1,171 +0,0 @@
|
||||
import QUnit from 'qunit';
|
||||
import { forEachMediaGroup } from '../src/media-groups';
|
||||
|
||||
QUnit.module('forEachMediaGroup');
|
||||
|
||||
QUnit.test('runs callback for each audio media group', function(assert) {
|
||||
const master = {
|
||||
mediaGroups: {
|
||||
AUDIO: {
|
||||
au1: {
|
||||
en: { en: 'en' },
|
||||
es: { es: 'es' }
|
||||
},
|
||||
au2: {
|
||||
de: { de: 'de' },
|
||||
fr: { fr: 'fr' }
|
||||
}
|
||||
},
|
||||
OTHER: {
|
||||
other1: {
|
||||
other11: { other11: 'other11' },
|
||||
other12: { other12: 'other12' }
|
||||
},
|
||||
other2: {
|
||||
other21: { other21: 'other21' },
|
||||
other22: { other22: 'other22' }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
const iteratedMediaGroups = [];
|
||||
|
||||
forEachMediaGroup(
|
||||
master,
|
||||
['AUDIO'],
|
||||
(mediaGroup) => iteratedMediaGroups.push(mediaGroup)
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
iteratedMediaGroups,
|
||||
[
|
||||
{ en: 'en' },
|
||||
{ es: 'es' },
|
||||
{ de: 'de' },
|
||||
{ fr: 'fr' }
|
||||
],
|
||||
'iterated audio media groups'
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('runs callback for each subtitle media group', function(assert) {
|
||||
const master = {
|
||||
mediaGroups: {
|
||||
SUBTITLES: {
|
||||
sub1: {
|
||||
en: { en: 'en' },
|
||||
es: { es: 'es' }
|
||||
},
|
||||
sub2: {
|
||||
de: { de: 'de' },
|
||||
fr: { fr: 'fr' }
|
||||
}
|
||||
},
|
||||
OTHER: {
|
||||
other1: {
|
||||
other11: { other11: 'other11' },
|
||||
other12: { other12: 'other12' }
|
||||
},
|
||||
other2: {
|
||||
other21: { other21: 'other21' },
|
||||
other22: { other22: 'other22' }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
const iteratedMediaGroups = [];
|
||||
|
||||
forEachMediaGroup(
|
||||
master,
|
||||
['SUBTITLES'],
|
||||
(mediaGroup) => iteratedMediaGroups.push(mediaGroup)
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
iteratedMediaGroups,
|
||||
[
|
||||
{ en: 'en' },
|
||||
{ es: 'es' },
|
||||
{ de: 'de' },
|
||||
{ fr: 'fr' }
|
||||
],
|
||||
'iterated subtitles media groups'
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('runs callback for each audio and subtitles media group', function(assert) {
|
||||
const master = {
|
||||
mediaGroups: {
|
||||
AUDIO: {
|
||||
au1: {
|
||||
en: { en: 'en' },
|
||||
es: { es: 'es' }
|
||||
},
|
||||
au2: {
|
||||
de: { de: 'de' },
|
||||
fr: { fr: 'fr' }
|
||||
}
|
||||
},
|
||||
SUBTITLES: {
|
||||
sub1: {
|
||||
enS: { enS: 'enS' },
|
||||
esS: { esS: 'esS' }
|
||||
},
|
||||
sub2: {
|
||||
deS: { deS: 'deS' },
|
||||
frS: { frS: 'frS' }
|
||||
}
|
||||
},
|
||||
OTHER: {
|
||||
other1: {
|
||||
other11: { other11: 'other11' },
|
||||
other12: { other12: 'other12' }
|
||||
},
|
||||
other2: {
|
||||
other21: { other21: 'other21' },
|
||||
other22: { other22: 'other22' }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
const iteratedMediaGroups = [];
|
||||
|
||||
forEachMediaGroup(
|
||||
master,
|
||||
['AUDIO', 'SUBTITLES'],
|
||||
(mediaGroup) => iteratedMediaGroups.push(mediaGroup)
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
iteratedMediaGroups,
|
||||
[
|
||||
{ en: 'en' },
|
||||
{ es: 'es' },
|
||||
{ de: 'de' },
|
||||
{ fr: 'fr' },
|
||||
{ enS: 'enS' },
|
||||
{ esS: 'esS' },
|
||||
{ deS: 'deS' },
|
||||
{ frS: 'frS' }
|
||||
],
|
||||
'iterated audio and subtitles media groups'
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('does not run callback for non specified media groups', function(assert) {
|
||||
const master = {
|
||||
mediaGroups: {
|
||||
'VIDEO': { v1: { en: { en: 'en' } } },
|
||||
'CLOSED-CAPTIONS': { cc1: { en: { en: 'en' } } }
|
||||
}
|
||||
};
|
||||
const iteratedMediaGroups = [];
|
||||
|
||||
forEachMediaGroup(
|
||||
master,
|
||||
['AUDIO', 'SUBTITLES'],
|
||||
(mediaGroup) => iteratedMediaGroups.push(mediaGroup)
|
||||
);
|
||||
|
||||
assert.deepEqual(iteratedMediaGroups, [], 'did not iterate non specified media groups');
|
||||
});
|
||||
@@ -1,41 +0,0 @@
|
||||
import QUnit from 'qunit';
|
||||
import { simpleTypeFromSourceType } from '../src/media-types';
|
||||
|
||||
QUnit.module('simpleTypeFromSourceType');
|
||||
|
||||
QUnit.test('simpleTypeFromSourceType converts HLS mime types to hls', function(assert) {
|
||||
assert.equal(
|
||||
simpleTypeFromSourceType('aPplicatiOn/x-MPegUrl'),
|
||||
'hls',
|
||||
'supports application/x-mpegurl'
|
||||
);
|
||||
assert.equal(
|
||||
simpleTypeFromSourceType('aPplicatiOn/VnD.aPPle.MpEgUrL'),
|
||||
'hls',
|
||||
'supports application/vnd.apple.mpegurl'
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('simpleTypeFromSourceType converts DASH mime type to dash', function(assert) {
|
||||
assert.equal(
|
||||
simpleTypeFromSourceType('aPplication/dAsh+xMl'),
|
||||
'dash',
|
||||
'supports application/dash+xml'
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
'simpleTypeFromSourceType does not convert non HLS/DASH mime types',
|
||||
function(assert) {
|
||||
assert.notOk(simpleTypeFromSourceType('video/mp4'), 'does not support video/mp4');
|
||||
assert.notOk(simpleTypeFromSourceType('video/x-flv'), 'does not support video/x-flv');
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test('simpleTypeFromSourceType converts VHS media type to vhs-json', function(assert) {
|
||||
assert.equal(
|
||||
simpleTypeFromSourceType('application/vnd.videojs.vhs+json'),
|
||||
'vhs-json',
|
||||
'supports application/vnd.videojs.vhs+json'
|
||||
);
|
||||
});
|
||||
@@ -1,28 +0,0 @@
|
||||
import QUnit from 'qunit';
|
||||
import window from 'global/window';
|
||||
import resolveUrl from '../src/resolve-url';
|
||||
|
||||
// A modified subset of tests from https://github.com/tjenkinson/url-toolkit
|
||||
|
||||
QUnit.module('URL resolver');
|
||||
|
||||
QUnit.test('works with a selection of valid urls', function(assert) {
|
||||
let currentLocation = '';
|
||||
|
||||
if (window.location && window.location.protocol) {
|
||||
currentLocation = window.location.protocol + '//' + window.location.host;
|
||||
}
|
||||
|
||||
assert.equal(
|
||||
resolveUrl('http://a.com/b/cd/e.m3u8', 'https://example.com/z.ts'),
|
||||
'https://example.com/z.ts'
|
||||
);
|
||||
assert.equal(resolveUrl('http://a.com/b/cd/e.m3u8', 'z.ts'), 'http://a.com/b/cd/z.ts');
|
||||
assert.equal(resolveUrl('//a.com/b/cd/e.m3u8', 'z.ts'), '//a.com/b/cd/z.ts');
|
||||
assert.equal(
|
||||
resolveUrl('/a/b/cd/e.m3u8', 'https://example.com:8080/z.ts'),
|
||||
'https://example.com:8080/z.ts'
|
||||
);
|
||||
assert.equal(resolveUrl('/a/b/cd/e.m3u8', 'z.ts'), currentLocation + '/a/b/cd/z.ts');
|
||||
assert.equal(resolveUrl('/a/b/cd/e.m3u8', '../../../z.ts'), currentLocation + '/z.ts');
|
||||
});
|
||||
@@ -1,51 +0,0 @@
|
||||
import QUnit from 'qunit';
|
||||
import Stream from '../src/stream';
|
||||
|
||||
QUnit.module('stream', {
|
||||
|
||||
beforeEach() {
|
||||
this.stream = new Stream();
|
||||
},
|
||||
|
||||
afterEach() {
|
||||
this.stream.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
QUnit.test('trigger calls listeners', function(assert) {
|
||||
const args = [];
|
||||
|
||||
this.stream.on('test', function(data) {
|
||||
args.push(data);
|
||||
});
|
||||
|
||||
this.stream.trigger('test', 1);
|
||||
this.stream.trigger('test', 2);
|
||||
|
||||
assert.deepEqual(args, [1, 2]);
|
||||
});
|
||||
|
||||
QUnit.test('callbacks can remove themselves', function(assert) {
|
||||
const args1 = [];
|
||||
const args2 = [];
|
||||
const args3 = [];
|
||||
const arg2Fn = (event) => {
|
||||
args2.push(event);
|
||||
this.stream.off('test', arg2Fn);
|
||||
};
|
||||
|
||||
this.stream.on('test', (event) => {
|
||||
args1.push(event);
|
||||
});
|
||||
this.stream.on('test', arg2Fn);
|
||||
this.stream.on('test', (event) => {
|
||||
args3.push(event);
|
||||
});
|
||||
|
||||
this.stream.trigger('test', 1);
|
||||
this.stream.trigger('test', 2);
|
||||
|
||||
assert.deepEqual(args1, [1, 2], 'first callback ran all times');
|
||||
assert.deepEqual(args2, [1], 'second callback removed after first run');
|
||||
assert.deepEqual(args3, [1, 2], 'third callback ran all times');
|
||||
});
|
||||
133
build/javascript/node_modules/mpd-parser/package.json
generated
vendored
133
build/javascript/node_modules/mpd-parser/package.json
generated
vendored
@@ -1,133 +0,0 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
"mpd-parser@0.12.0",
|
||||
"/home/runner/work/owncast/owncast/build/javascript"
|
||||
]
|
||||
],
|
||||
"_from": "mpd-parser@0.12.0",
|
||||
"_id": "mpd-parser@0.12.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-Ov5Oz9bw5X/G8V/6PlO+rHuqKywYYjQ6USyv8fqFMs413HkrzlpDjgUKSBD7C+/J19ID5mWtxzrpMf4Yp++iZg==",
|
||||
"_location": "/mpd-parser",
|
||||
"_phantomChildren": {
|
||||
"@babel/runtime": "7.11.2",
|
||||
"global": "4.4.0",
|
||||
"url-toolkit": "2.2.0"
|
||||
},
|
||||
"_requested": {
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "mpd-parser@0.12.0",
|
||||
"name": "mpd-parser",
|
||||
"escapedName": "mpd-parser",
|
||||
"rawSpec": "0.12.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "0.12.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/@videojs/http-streaming"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.12.0.tgz",
|
||||
"_spec": "0.12.0",
|
||||
"_where": "/home/runner/work/owncast/owncast/build/javascript",
|
||||
"author": {
|
||||
"name": "Brightcove, Inc"
|
||||
},
|
||||
"browserslist": [
|
||||
"defaults",
|
||||
"ie 11"
|
||||
],
|
||||
"bugs": {
|
||||
"url": "https://github.com/videojs/mpd-parser/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"@videojs/vhs-utils": "^1.1.0",
|
||||
"global": "^4.3.2",
|
||||
"xmldom": "^0.1.27"
|
||||
},
|
||||
"description": "mpd parser",
|
||||
"devDependencies": {
|
||||
"@videojs/generator-helpers": "~1.2.0",
|
||||
"jsdom": "^15.1.1",
|
||||
"karma": "^4.0.0",
|
||||
"rollup": "^1.19.4",
|
||||
"rollup-plugin-string": "^2.0.2",
|
||||
"sinon": "^7.2.2",
|
||||
"videojs-generate-karma-config": "~5.3.1",
|
||||
"videojs-generate-rollup-config": "~5.0.1",
|
||||
"videojs-generator-verify": "~2.0.0",
|
||||
"videojs-standard": "^8.0.3"
|
||||
},
|
||||
"files": [
|
||||
"CONTRIBUTING.md",
|
||||
"dist/",
|
||||
"docs/",
|
||||
"index.html",
|
||||
"scripts/",
|
||||
"src/",
|
||||
"test/"
|
||||
],
|
||||
"generator-videojs-plugin": {
|
||||
"version": "7.7.3"
|
||||
},
|
||||
"homepage": "https://github.com/videojs/mpd-parser#readme",
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
}
|
||||
},
|
||||
"keywords": [
|
||||
"videojs",
|
||||
"videojs-plugin"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"lint-staged": {
|
||||
"*.js": [
|
||||
"vjsstandard --fix",
|
||||
"git add"
|
||||
],
|
||||
"README.md": [
|
||||
"doctoc --notitle",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"main": "dist/mpd-parser.cjs.js",
|
||||
"module": "dist/mpd-parser.es.js",
|
||||
"name": "mpd-parser",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+ssh://git@github.com/videojs/mpd-parser.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm-run-all -s clean -p build:*",
|
||||
"build-prod": "cross-env-shell NO_TEST_BUNDLE=1 'npm run build'",
|
||||
"build-test": "cross-env-shell TEST_BUNDLE_ONLY=1 'npm run build'",
|
||||
"build:js": "rollup -c scripts/rollup.config.js",
|
||||
"clean": "shx rm -rf ./dist ./test/dist && shx mkdir -p ./dist ./test/dist",
|
||||
"lint": "vjsstandard",
|
||||
"netlify": "node scripts/netlify.js",
|
||||
"posttest": "shx cat test/dist/coverage/text.txt",
|
||||
"prenetlify": "npm run build",
|
||||
"prepublishOnly": "npm-run-all build-prod && vjsverify --verbose",
|
||||
"preversion": "npm test",
|
||||
"server": "karma start scripts/karma.conf.js --singleRun=false --auto-watch",
|
||||
"start": "npm-run-all -p server watch",
|
||||
"test": "npm-run-all lint build-test && npm-run-all test:*",
|
||||
"test:browser": "karma start scripts/karma.conf.js",
|
||||
"test:node": "qunit test/dist/bundle-node.js",
|
||||
"update-changelog": "conventional-changelog -p videojs -i CHANGELOG.md -s",
|
||||
"version": "is-prerelease || npm run update-changelog && git add CHANGELOG.md",
|
||||
"watch": "npm-run-all -p watch:*",
|
||||
"watch:js": "npm run build:js -- -w"
|
||||
},
|
||||
"version": "0.12.0",
|
||||
"vjsstandard": {
|
||||
"ignore": [
|
||||
"dist",
|
||||
"docs",
|
||||
"test/dist"
|
||||
]
|
||||
}
|
||||
}
|
||||
13
build/javascript/node_modules/mpd-parser/scripts/karma.conf.js
generated
vendored
13
build/javascript/node_modules/mpd-parser/scripts/karma.conf.js
generated
vendored
@@ -1,13 +0,0 @@
|
||||
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!
|
||||
};
|
||||
|
||||
14
build/javascript/node_modules/mpd-parser/scripts/netlify.js
generated
vendored
14
build/javascript/node_modules/mpd-parser/scripts/netlify.js
generated
vendored
@@ -1,14 +0,0 @@
|
||||
const path = require('path');
|
||||
const sh = require('shelljs');
|
||||
|
||||
const files = ['dist', 'index.html'];
|
||||
const deployDir = 'deploy';
|
||||
|
||||
// cleanup previous deploy
|
||||
sh.rm('-rf', deployDir);
|
||||
// make sure the directory exists
|
||||
sh.mkdir('-p', deployDir);
|
||||
|
||||
// copy over dist, and html files
|
||||
files
|
||||
.forEach((file) => sh.cp('-r', file, path.join(deployDir, file)));
|
||||
56
build/javascript/node_modules/mpd-parser/scripts/rollup.config.js
generated
vendored
56
build/javascript/node_modules/mpd-parser/scripts/rollup.config.js
generated
vendored
@@ -1,56 +0,0 @@
|
||||
const generate = require('videojs-generate-rollup-config');
|
||||
const string = require('rollup-plugin-string');
|
||||
|
||||
// see https://github.com/videojs/videojs-generate-rollup-config
|
||||
// for options
|
||||
const options = {
|
||||
input: 'src/index.js',
|
||||
plugins(defaults) {
|
||||
defaults.test.unshift('string');
|
||||
|
||||
return defaults;
|
||||
},
|
||||
primedPlugins(defaults) {
|
||||
defaults.string = string({include: ['test/manifests/*.mpd']});
|
||||
|
||||
return defaults;
|
||||
},
|
||||
externals(defaults) {
|
||||
defaults.module.push('@videojs/vhs-utils');
|
||||
defaults.module.push('xmldom');
|
||||
defaults.module.push('atob');
|
||||
defaults.module.push('url-toolkit');
|
||||
return defaults;
|
||||
},
|
||||
globals(defaults) {
|
||||
defaults.browser.xmldom = 'window';
|
||||
defaults.browser.atob = 'window.atob';
|
||||
defaults.test.xmldom = 'window';
|
||||
defaults.test.atob = 'window.atob';
|
||||
defaults.test.jsdom = '{JSDOM: function() { return {window: window}; }}';
|
||||
return defaults;
|
||||
}
|
||||
};
|
||||
const config = generate(options);
|
||||
|
||||
if (config.builds.test) {
|
||||
config.builds.testNode = config.makeBuild('test', {
|
||||
input: 'test/**/*.test.js',
|
||||
output: [{
|
||||
name: `${config.settings.exportName}Tests`,
|
||||
file: 'test/dist/bundle-node.js',
|
||||
format: 'cjs'
|
||||
}]
|
||||
});
|
||||
|
||||
config.builds.testNode.output[0].globals = {};
|
||||
config.builds.testNode.external = [].concat(config.settings.externals.module).concat([
|
||||
'jsdom',
|
||||
'qunit'
|
||||
]);
|
||||
}
|
||||
|
||||
// Add additonal builds/customization here!
|
||||
|
||||
// export the builds to rollup
|
||||
export default Object.values(config.builds);
|
||||
9
build/javascript/node_modules/mpd-parser/src/errors.js
generated
vendored
9
build/javascript/node_modules/mpd-parser/src/errors.js
generated
vendored
@@ -1,9 +0,0 @@
|
||||
export default {
|
||||
INVALID_NUMBER_OF_PERIOD: 'INVALID_NUMBER_OF_PERIOD',
|
||||
DASH_EMPTY_MANIFEST: 'DASH_EMPTY_MANIFEST',
|
||||
DASH_INVALID_XML: 'DASH_INVALID_XML',
|
||||
NO_BASE_URL: 'NO_BASE_URL',
|
||||
MISSING_SEGMENT_INFORMATION: 'MISSING_SEGMENT_INFORMATION',
|
||||
SEGMENT_TIME_UNSPECIFIED: 'SEGMENT_TIME_UNSPECIFIED',
|
||||
UNSUPPORTED_UTC_TIMING_SCHEME: 'UNSUPPORTED_UTC_TIMING_SCHEME'
|
||||
};
|
||||
36
build/javascript/node_modules/mpd-parser/src/index.js
generated
vendored
36
build/javascript/node_modules/mpd-parser/src/index.js
generated
vendored
@@ -1,36 +0,0 @@
|
||||
import { version } from '../package.json';
|
||||
import { toM3u8 } from './toM3u8';
|
||||
import { toPlaylists } from './toPlaylists';
|
||||
import { inheritAttributes } from './inheritAttributes';
|
||||
import { stringToMpdXml } from './stringToMpdXml';
|
||||
import { parseUTCTimingScheme } from './parseUTCTimingScheme';
|
||||
|
||||
const VERSION = version;
|
||||
|
||||
const parse = (manifestString, options = {}) => {
|
||||
const parsedManifestInfo = inheritAttributes(stringToMpdXml(manifestString), options);
|
||||
const playlists = toPlaylists(parsedManifestInfo.representationInfo);
|
||||
|
||||
return toM3u8(playlists, parsedManifestInfo.locations, options.sidxMapping);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses the manifest for a UTCTiming node, returning the nodes attributes if found
|
||||
*
|
||||
* @param {string} manifestString
|
||||
* XML string of the MPD manifest
|
||||
* @return {Object|null}
|
||||
* Attributes of UTCTiming node specified in the manifest. Null if none found
|
||||
*/
|
||||
const parseUTCTiming = (manifestString) =>
|
||||
parseUTCTimingScheme(stringToMpdXml(manifestString));
|
||||
|
||||
export {
|
||||
VERSION,
|
||||
parse,
|
||||
parseUTCTiming,
|
||||
stringToMpdXml,
|
||||
inheritAttributes,
|
||||
toPlaylists,
|
||||
toM3u8
|
||||
};
|
||||
335
build/javascript/node_modules/mpd-parser/src/inheritAttributes.js
generated
vendored
335
build/javascript/node_modules/mpd-parser/src/inheritAttributes.js
generated
vendored
@@ -1,335 +0,0 @@
|
||||
import window from 'global/window';
|
||||
import { flatten } from './utils/list';
|
||||
import { merge } from './utils/object';
|
||||
import { findChildren, getContent } from './utils/xml';
|
||||
import { parseAttributes } from './parseAttributes';
|
||||
import errors from './errors';
|
||||
import resolveUrl from '@videojs/vhs-utils/dist/resolve-url';
|
||||
import decodeB64ToUint8Array from '@videojs/vhs-utils/dist/decode-b64-to-uint8-array';
|
||||
|
||||
const keySystemsMap = {
|
||||
'urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b': 'org.w3.clearkey',
|
||||
'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed': 'com.widevine.alpha',
|
||||
'urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95': 'com.microsoft.playready',
|
||||
'urn:uuid:f239e769-efa3-4850-9c16-a903c6932efb': 'com.adobe.primetime'
|
||||
};
|
||||
|
||||
/**
|
||||
* Builds a list of urls that is the product of the reference urls and BaseURL values
|
||||
*
|
||||
* @param {string[]} referenceUrls
|
||||
* List of reference urls to resolve to
|
||||
* @param {Node[]} baseUrlElements
|
||||
* List of BaseURL nodes from the mpd
|
||||
* @return {string[]}
|
||||
* List of resolved urls
|
||||
*/
|
||||
export const buildBaseUrls = (referenceUrls, baseUrlElements) => {
|
||||
if (!baseUrlElements.length) {
|
||||
return referenceUrls;
|
||||
}
|
||||
|
||||
return flatten(referenceUrls.map(function(reference) {
|
||||
return baseUrlElements.map(function(baseUrlElement) {
|
||||
return resolveUrl(reference, getContent(baseUrlElement));
|
||||
});
|
||||
}));
|
||||
};
|
||||
|
||||
/**
|
||||
* Contains all Segment information for its containing AdaptationSet
|
||||
*
|
||||
* @typedef {Object} SegmentInformation
|
||||
* @property {Object|undefined} template
|
||||
* Contains the attributes for the SegmentTemplate node
|
||||
* @property {Object[]|undefined} timeline
|
||||
* Contains a list of atrributes for each S node within the SegmentTimeline node
|
||||
* @property {Object|undefined} list
|
||||
* Contains the attributes for the SegmentList node
|
||||
* @property {Object|undefined} base
|
||||
* Contains the attributes for the SegmentBase node
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns all available Segment information contained within the AdaptationSet node
|
||||
*
|
||||
* @param {Node} adaptationSet
|
||||
* The AdaptationSet node to get Segment information from
|
||||
* @return {SegmentInformation}
|
||||
* The Segment information contained within the provided AdaptationSet
|
||||
*/
|
||||
export const getSegmentInformation = (adaptationSet) => {
|
||||
const segmentTemplate = findChildren(adaptationSet, 'SegmentTemplate')[0];
|
||||
const segmentList = findChildren(adaptationSet, 'SegmentList')[0];
|
||||
const segmentUrls = segmentList && findChildren(segmentList, 'SegmentURL')
|
||||
.map(s => merge({ tag: 'SegmentURL' }, parseAttributes(s)));
|
||||
const segmentBase = findChildren(adaptationSet, 'SegmentBase')[0];
|
||||
const segmentTimelineParentNode = segmentList || segmentTemplate;
|
||||
const segmentTimeline = segmentTimelineParentNode &&
|
||||
findChildren(segmentTimelineParentNode, 'SegmentTimeline')[0];
|
||||
const segmentInitializationParentNode = segmentList || segmentBase || segmentTemplate;
|
||||
const segmentInitialization = segmentInitializationParentNode &&
|
||||
findChildren(segmentInitializationParentNode, 'Initialization')[0];
|
||||
|
||||
// SegmentTemplate is handled slightly differently, since it can have both
|
||||
// @initialization and an <Initialization> node. @initialization can be templated,
|
||||
// while the node can have a url and range specified. If the <SegmentTemplate> has
|
||||
// both @initialization and an <Initialization> subelement we opt to override with
|
||||
// the node, as this interaction is not defined in the spec.
|
||||
const template = segmentTemplate && parseAttributes(segmentTemplate);
|
||||
|
||||
if (template && segmentInitialization) {
|
||||
template.initialization =
|
||||
(segmentInitialization && parseAttributes(segmentInitialization));
|
||||
} else if (template && template.initialization) {
|
||||
// If it is @initialization we convert it to an object since this is the format that
|
||||
// later functions will rely on for the initialization segment. This is only valid
|
||||
// for <SegmentTemplate>
|
||||
template.initialization = { sourceURL: template.initialization };
|
||||
}
|
||||
|
||||
const segmentInfo = {
|
||||
template,
|
||||
timeline: segmentTimeline &&
|
||||
findChildren(segmentTimeline, 'S').map(s => parseAttributes(s)),
|
||||
list: segmentList && merge(
|
||||
parseAttributes(segmentList),
|
||||
{
|
||||
segmentUrls,
|
||||
initialization: parseAttributes(segmentInitialization)
|
||||
}
|
||||
),
|
||||
base: segmentBase && merge(parseAttributes(segmentBase), {
|
||||
initialization: parseAttributes(segmentInitialization)
|
||||
})
|
||||
};
|
||||
|
||||
Object.keys(segmentInfo).forEach(key => {
|
||||
if (!segmentInfo[key]) {
|
||||
delete segmentInfo[key];
|
||||
}
|
||||
});
|
||||
|
||||
return segmentInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* Contains Segment information and attributes needed to construct a Playlist object
|
||||
* from a Representation
|
||||
*
|
||||
* @typedef {Object} RepresentationInformation
|
||||
* @property {SegmentInformation} segmentInfo
|
||||
* Segment information for this Representation
|
||||
* @property {Object} attributes
|
||||
* Inherited attributes for this Representation
|
||||
*/
|
||||
|
||||
/**
|
||||
* Maps a Representation node to an object containing Segment information and attributes
|
||||
*
|
||||
* @name inheritBaseUrlsCallback
|
||||
* @function
|
||||
* @param {Node} representation
|
||||
* Representation node from the mpd
|
||||
* @return {RepresentationInformation}
|
||||
* Representation information needed to construct a Playlist object
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns a callback for Array.prototype.map for mapping Representation nodes to
|
||||
* Segment information and attributes using inherited BaseURL nodes.
|
||||
*
|
||||
* @param {Object} adaptationSetAttributes
|
||||
* Contains attributes inherited by the AdaptationSet
|
||||
* @param {string[]} adaptationSetBaseUrls
|
||||
* Contains list of resolved base urls inherited by the AdaptationSet
|
||||
* @param {SegmentInformation} adaptationSetSegmentInfo
|
||||
* Contains Segment information for the AdaptationSet
|
||||
* @return {inheritBaseUrlsCallback}
|
||||
* Callback map function
|
||||
*/
|
||||
export const inheritBaseUrls =
|
||||
(adaptationSetAttributes, adaptationSetBaseUrls, adaptationSetSegmentInfo) =>
|
||||
(representation) => {
|
||||
const repBaseUrlElements = findChildren(representation, 'BaseURL');
|
||||
const repBaseUrls = buildBaseUrls(adaptationSetBaseUrls, repBaseUrlElements);
|
||||
const attributes = merge(adaptationSetAttributes, parseAttributes(representation));
|
||||
const representationSegmentInfo = getSegmentInformation(representation);
|
||||
|
||||
return repBaseUrls.map(baseUrl => {
|
||||
return {
|
||||
segmentInfo: merge(adaptationSetSegmentInfo, representationSegmentInfo),
|
||||
attributes: merge(attributes, { baseUrl })
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Tranforms a series of content protection nodes to
|
||||
* an object containing pssh data by key system
|
||||
*
|
||||
* @param {Node[]} contentProtectionNodes
|
||||
* Content protection nodes
|
||||
* @return {Object}
|
||||
* Object containing pssh data by key system
|
||||
*/
|
||||
const generateKeySystemInformation = (contentProtectionNodes) => {
|
||||
return contentProtectionNodes.reduce((acc, node) => {
|
||||
const attributes = parseAttributes(node);
|
||||
const keySystem = keySystemsMap[attributes.schemeIdUri];
|
||||
|
||||
if (keySystem) {
|
||||
acc[keySystem] = { attributes };
|
||||
|
||||
const psshNode = findChildren(node, 'cenc:pssh')[0];
|
||||
|
||||
if (psshNode) {
|
||||
const pssh = getContent(psshNode);
|
||||
const psshBuffer = pssh && decodeB64ToUint8Array(pssh);
|
||||
|
||||
acc[keySystem].pssh = psshBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
};
|
||||
|
||||
/**
|
||||
* Maps an AdaptationSet node to a list of Representation information objects
|
||||
*
|
||||
* @name toRepresentationsCallback
|
||||
* @function
|
||||
* @param {Node} adaptationSet
|
||||
* AdaptationSet node from the mpd
|
||||
* @return {RepresentationInformation[]}
|
||||
* List of objects containing Representaion information
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns a callback for Array.prototype.map for mapping AdaptationSet nodes to a list of
|
||||
* Representation information objects
|
||||
*
|
||||
* @param {Object} periodAttributes
|
||||
* Contains attributes inherited by the Period
|
||||
* @param {string[]} periodBaseUrls
|
||||
* Contains list of resolved base urls inherited by the Period
|
||||
* @param {string[]} periodSegmentInfo
|
||||
* Contains Segment Information at the period level
|
||||
* @return {toRepresentationsCallback}
|
||||
* Callback map function
|
||||
*/
|
||||
export const toRepresentations =
|
||||
(periodAttributes, periodBaseUrls, periodSegmentInfo) => (adaptationSet) => {
|
||||
const adaptationSetAttributes = parseAttributes(adaptationSet);
|
||||
const adaptationSetBaseUrls = buildBaseUrls(
|
||||
periodBaseUrls,
|
||||
findChildren(adaptationSet, 'BaseURL')
|
||||
);
|
||||
const role = findChildren(adaptationSet, 'Role')[0];
|
||||
const roleAttributes = { role: parseAttributes(role) };
|
||||
|
||||
let attrs = merge(
|
||||
periodAttributes,
|
||||
adaptationSetAttributes,
|
||||
roleAttributes
|
||||
);
|
||||
|
||||
const contentProtection = generateKeySystemInformation(findChildren(adaptationSet, 'ContentProtection'));
|
||||
|
||||
if (Object.keys(contentProtection).length) {
|
||||
attrs = merge(attrs, { contentProtection });
|
||||
}
|
||||
|
||||
const segmentInfo = getSegmentInformation(adaptationSet);
|
||||
const representations = findChildren(adaptationSet, 'Representation');
|
||||
const adaptationSetSegmentInfo = merge(periodSegmentInfo, segmentInfo);
|
||||
|
||||
return flatten(representations.map(inheritBaseUrls(attrs, adaptationSetBaseUrls, adaptationSetSegmentInfo)));
|
||||
};
|
||||
|
||||
/**
|
||||
* Maps an Period node to a list of Representation inforamtion objects for all
|
||||
* AdaptationSet nodes contained within the Period
|
||||
*
|
||||
* @name toAdaptationSetsCallback
|
||||
* @function
|
||||
* @param {Node} period
|
||||
* Period node from the mpd
|
||||
* @param {number} periodIndex
|
||||
* Index of the Period within the mpd
|
||||
* @return {RepresentationInformation[]}
|
||||
* List of objects containing Representaion information
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns a callback for Array.prototype.map for mapping Period nodes to a list of
|
||||
* Representation information objects
|
||||
*
|
||||
* @param {Object} mpdAttributes
|
||||
* Contains attributes inherited by the mpd
|
||||
* @param {string[]} mpdBaseUrls
|
||||
* Contains list of resolved base urls inherited by the mpd
|
||||
* @return {toAdaptationSetsCallback}
|
||||
* Callback map function
|
||||
*/
|
||||
export const toAdaptationSets = (mpdAttributes, mpdBaseUrls) => (period, index) => {
|
||||
const periodBaseUrls = buildBaseUrls(mpdBaseUrls, findChildren(period, 'BaseURL'));
|
||||
const periodAtt = parseAttributes(period);
|
||||
const parsedPeriodId = parseInt(periodAtt.id, 10);
|
||||
// fallback to mapping index if Period@id is not a number
|
||||
const periodIndex = window.isNaN(parsedPeriodId) ? index : parsedPeriodId;
|
||||
const periodAttributes = merge(mpdAttributes, { periodIndex });
|
||||
const adaptationSets = findChildren(period, 'AdaptationSet');
|
||||
const periodSegmentInfo = getSegmentInformation(period);
|
||||
|
||||
return flatten(adaptationSets.map(toRepresentations(periodAttributes, periodBaseUrls, periodSegmentInfo)));
|
||||
};
|
||||
|
||||
/**
|
||||
* Traverses the mpd xml tree to generate a list of Representation information objects
|
||||
* that have inherited attributes from parent nodes
|
||||
*
|
||||
* @param {Node} mpd
|
||||
* The root node of the mpd
|
||||
* @param {Object} options
|
||||
* Available options for inheritAttributes
|
||||
* @param {string} options.manifestUri
|
||||
* The uri source of the mpd
|
||||
* @param {number} options.NOW
|
||||
* Current time per DASH IOP. Default is current time in ms since epoch
|
||||
* @param {number} options.clientOffset
|
||||
* Client time difference from NOW (in milliseconds)
|
||||
* @return {RepresentationInformation[]}
|
||||
* List of objects containing Representation information
|
||||
*/
|
||||
export const inheritAttributes = (mpd, options = {}) => {
|
||||
const {
|
||||
manifestUri = '',
|
||||
NOW = Date.now(),
|
||||
clientOffset = 0
|
||||
} = options;
|
||||
const periods = findChildren(mpd, 'Period');
|
||||
|
||||
if (!periods.length) {
|
||||
throw new Error(errors.INVALID_NUMBER_OF_PERIOD);
|
||||
}
|
||||
|
||||
const locations = findChildren(mpd, 'Location');
|
||||
|
||||
const mpdAttributes = parseAttributes(mpd);
|
||||
const mpdBaseUrls = buildBaseUrls([ manifestUri ], findChildren(mpd, 'BaseURL'));
|
||||
|
||||
mpdAttributes.sourceDuration = mpdAttributes.mediaPresentationDuration || 0;
|
||||
mpdAttributes.NOW = NOW;
|
||||
mpdAttributes.clientOffset = clientOffset;
|
||||
|
||||
if (locations.length) {
|
||||
mpdAttributes.locations = locations.map(getContent);
|
||||
}
|
||||
|
||||
return {
|
||||
locations: mpdAttributes.locations,
|
||||
representationInfo: flatten(periods.map(toAdaptationSets(mpdAttributes, mpdBaseUrls)))
|
||||
};
|
||||
};
|
||||
254
build/javascript/node_modules/mpd-parser/src/parseAttributes.js
generated
vendored
254
build/javascript/node_modules/mpd-parser/src/parseAttributes.js
generated
vendored
@@ -1,254 +0,0 @@
|
||||
import { from } from './utils/list';
|
||||
import { parseDuration, parseDate } from './utils/time';
|
||||
|
||||
// TODO: maybe order these in some way that makes it easy to find specific attributes
|
||||
export const parsers = {
|
||||
/**
|
||||
* Specifies the duration of the entire Media Presentation. Format is a duration string
|
||||
* as specified in ISO 8601
|
||||
*
|
||||
* @param {string} value
|
||||
* value of attribute as a string
|
||||
* @return {number}
|
||||
* The duration in seconds
|
||||
*/
|
||||
mediaPresentationDuration(value) {
|
||||
return parseDuration(value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Specifies the Segment availability start time for all Segments referred to in this
|
||||
* MPD. For a dynamic manifest, it specifies the anchor for the earliest availability
|
||||
* time. Format is a date string as specified in ISO 8601
|
||||
*
|
||||
* @param {string} value
|
||||
* value of attribute as a string
|
||||
* @return {number}
|
||||
* The date as seconds from unix epoch
|
||||
*/
|
||||
availabilityStartTime(value) {
|
||||
return parseDate(value) / 1000;
|
||||
},
|
||||
|
||||
/**
|
||||
* Specifies the smallest period between potential changes to the MPD. Format is a
|
||||
* duration string as specified in ISO 8601
|
||||
*
|
||||
* @param {string} value
|
||||
* value of attribute as a string
|
||||
* @return {number}
|
||||
* The duration in seconds
|
||||
*/
|
||||
minimumUpdatePeriod(value) {
|
||||
return parseDuration(value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Specifies the suggested presentation delay. Format is a
|
||||
* duration string as specified in ISO 8601
|
||||
*
|
||||
* @param {string} value
|
||||
* value of attribute as a string
|
||||
* @return {number}
|
||||
* The duration in seconds
|
||||
*/
|
||||
suggestedPresentationDelay(value) {
|
||||
return parseDuration(value);
|
||||
},
|
||||
|
||||
/**
|
||||
* specifices the type of mpd. Can be either "static" or "dynamic"
|
||||
*
|
||||
* @param {string} value
|
||||
* value of attribute as a string
|
||||
*
|
||||
* @return {string}
|
||||
* The type as a string
|
||||
*/
|
||||
type(value) {
|
||||
return value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Specifies the duration of the smallest time shifting buffer for any Representation
|
||||
* in the MPD. Format is a duration string as specified in ISO 8601
|
||||
*
|
||||
* @param {string} value
|
||||
* value of attribute as a string
|
||||
* @return {number}
|
||||
* The duration in seconds
|
||||
*/
|
||||
timeShiftBufferDepth(value) {
|
||||
return parseDuration(value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Specifies the PeriodStart time of the Period relative to the availabilityStarttime.
|
||||
* Format is a duration string as specified in ISO 8601
|
||||
*
|
||||
* @param {string} value
|
||||
* value of attribute as a string
|
||||
* @return {number}
|
||||
* The duration in seconds
|
||||
*/
|
||||
start(value) {
|
||||
return parseDuration(value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Specifies the width of the visual presentation
|
||||
*
|
||||
* @param {string} value
|
||||
* value of attribute as a string
|
||||
* @return {number}
|
||||
* The parsed width
|
||||
*/
|
||||
width(value) {
|
||||
return parseInt(value, 10);
|
||||
},
|
||||
|
||||
/**
|
||||
* Specifies the height of the visual presentation
|
||||
*
|
||||
* @param {string} value
|
||||
* value of attribute as a string
|
||||
* @return {number}
|
||||
* The parsed height
|
||||
*/
|
||||
height(value) {
|
||||
return parseInt(value, 10);
|
||||
},
|
||||
|
||||
/**
|
||||
* Specifies the bitrate of the representation
|
||||
*
|
||||
* @param {string} value
|
||||
* value of attribute as a string
|
||||
* @return {number}
|
||||
* The parsed bandwidth
|
||||
*/
|
||||
bandwidth(value) {
|
||||
return parseInt(value, 10);
|
||||
},
|
||||
|
||||
/**
|
||||
* Specifies the number of the first Media Segment in this Representation in the Period
|
||||
*
|
||||
* @param {string} value
|
||||
* value of attribute as a string
|
||||
* @return {number}
|
||||
* The parsed number
|
||||
*/
|
||||
startNumber(value) {
|
||||
return parseInt(value, 10);
|
||||
},
|
||||
|
||||
/**
|
||||
* Specifies the timescale in units per seconds
|
||||
*
|
||||
* @param {string} value
|
||||
* value of attribute as a string
|
||||
* @return {number}
|
||||
* The aprsed timescale
|
||||
*/
|
||||
timescale(value) {
|
||||
return parseInt(value, 10);
|
||||
},
|
||||
|
||||
/**
|
||||
* Specifies the constant approximate Segment duration
|
||||
* NOTE: The <Period> element also contains an @duration attribute. This duration
|
||||
* specifies the duration of the Period. This attribute is currently not
|
||||
* supported by the rest of the parser, however we still check for it to prevent
|
||||
* errors.
|
||||
*
|
||||
* @param {string} value
|
||||
* value of attribute as a string
|
||||
* @return {number}
|
||||
* The parsed duration
|
||||
*/
|
||||
duration(value) {
|
||||
const parsedValue = parseInt(value, 10);
|
||||
|
||||
if (isNaN(parsedValue)) {
|
||||
return parseDuration(value);
|
||||
}
|
||||
|
||||
return parsedValue;
|
||||
},
|
||||
|
||||
/**
|
||||
* Specifies the Segment duration, in units of the value of the @timescale.
|
||||
*
|
||||
* @param {string} value
|
||||
* value of attribute as a string
|
||||
* @return {number}
|
||||
* The parsed duration
|
||||
*/
|
||||
d(value) {
|
||||
return parseInt(value, 10);
|
||||
},
|
||||
|
||||
/**
|
||||
* Specifies the MPD start time, in @timescale units, the first Segment in the series
|
||||
* starts relative to the beginning of the Period
|
||||
*
|
||||
* @param {string} value
|
||||
* value of attribute as a string
|
||||
* @return {number}
|
||||
* The parsed time
|
||||
*/
|
||||
t(value) {
|
||||
return parseInt(value, 10);
|
||||
},
|
||||
|
||||
/**
|
||||
* Specifies the repeat count of the number of following contiguous Segments with the
|
||||
* same duration expressed by the value of @d
|
||||
*
|
||||
* @param {string} value
|
||||
* value of attribute as a string
|
||||
* @return {number}
|
||||
* The parsed number
|
||||
*/
|
||||
r(value) {
|
||||
return parseInt(value, 10);
|
||||
},
|
||||
|
||||
/**
|
||||
* Default parser for all other attributes. Acts as a no-op and just returns the value
|
||||
* as a string
|
||||
*
|
||||
* @param {string} value
|
||||
* value of attribute as a string
|
||||
* @return {string}
|
||||
* Unparsed value
|
||||
*/
|
||||
DEFAULT(value) {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets all the attributes and values of the provided node, parses attributes with known
|
||||
* types, and returns an object with attribute names mapped to values.
|
||||
*
|
||||
* @param {Node} el
|
||||
* The node to parse attributes from
|
||||
* @return {Object}
|
||||
* Object with all attributes of el parsed
|
||||
*/
|
||||
export const parseAttributes = (el) => {
|
||||
if (!(el && el.attributes)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return from(el.attributes)
|
||||
.reduce((a, e) => {
|
||||
const parseFn = parsers[e.name] || parsers.DEFAULT;
|
||||
|
||||
a[e.name] = parseFn(e.value);
|
||||
|
||||
return a;
|
||||
}, {});
|
||||
};
|
||||
46
build/javascript/node_modules/mpd-parser/src/parseUTCTimingScheme.js
generated
vendored
46
build/javascript/node_modules/mpd-parser/src/parseUTCTimingScheme.js
generated
vendored
@@ -1,46 +0,0 @@
|
||||
import { findChildren } from './utils/xml';
|
||||
import { parseAttributes } from './parseAttributes';
|
||||
import errors from './errors';
|
||||
|
||||
/**
|
||||
* Parses the manifest for a UTCTiming node, returning the nodes attributes if found
|
||||
*
|
||||
* @param {string} mpd
|
||||
* XML string of the MPD manifest
|
||||
* @return {Object|null}
|
||||
* Attributes of UTCTiming node specified in the manifest. Null if none found
|
||||
*/
|
||||
export const parseUTCTimingScheme = (mpd) => {
|
||||
const UTCTimingNode = findChildren(mpd, 'UTCTiming')[0];
|
||||
|
||||
if (!UTCTimingNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const attributes = parseAttributes(UTCTimingNode);
|
||||
|
||||
switch (attributes.schemeIdUri) {
|
||||
case 'urn:mpeg:dash:utc:http-head:2014':
|
||||
case 'urn:mpeg:dash:utc:http-head:2012':
|
||||
attributes.method = 'HEAD';
|
||||
break;
|
||||
case 'urn:mpeg:dash:utc:http-xsdate:2014':
|
||||
case 'urn:mpeg:dash:utc:http-iso:2014':
|
||||
case 'urn:mpeg:dash:utc:http-xsdate:2012':
|
||||
case 'urn:mpeg:dash:utc:http-iso:2012':
|
||||
attributes.method = 'GET';
|
||||
break;
|
||||
case 'urn:mpeg:dash:utc:direct:2014':
|
||||
case 'urn:mpeg:dash:utc:direct:2012':
|
||||
attributes.method = 'DIRECT';
|
||||
attributes.value = Date.parse(attributes.value);
|
||||
break;
|
||||
case 'urn:mpeg:dash:utc:http-ntp:2014':
|
||||
case 'urn:mpeg:dash:utc:ntp:2014':
|
||||
case 'urn:mpeg:dash:utc:sntp:2014':
|
||||
default:
|
||||
throw new Error(errors.UNSUPPORTED_UTC_TIMING_SCHEME);
|
||||
}
|
||||
|
||||
return attributes;
|
||||
};
|
||||
132
build/javascript/node_modules/mpd-parser/src/segment/durationTimeParser.js
generated
vendored
132
build/javascript/node_modules/mpd-parser/src/segment/durationTimeParser.js
generated
vendored
@@ -1,132 +0,0 @@
|
||||
import { range } from '../utils/list';
|
||||
|
||||
/**
|
||||
* Functions for calculating the range of available segments in static and dynamic
|
||||
* manifests.
|
||||
*/
|
||||
export const segmentRange = {
|
||||
/**
|
||||
* Returns the entire range of available segments for a static MPD
|
||||
*
|
||||
* @param {Object} attributes
|
||||
* Inheritied MPD attributes
|
||||
* @return {{ start: number, end: number }}
|
||||
* The start and end numbers for available segments
|
||||
*/
|
||||
static(attributes) {
|
||||
const {
|
||||
duration,
|
||||
timescale = 1,
|
||||
sourceDuration
|
||||
} = attributes;
|
||||
|
||||
return {
|
||||
start: 0,
|
||||
end: Math.ceil(sourceDuration / (duration / timescale))
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the current live window range of available segments for a dynamic MPD
|
||||
*
|
||||
* @param {Object} attributes
|
||||
* Inheritied MPD attributes
|
||||
* @return {{ start: number, end: number }}
|
||||
* The start and end numbers for available segments
|
||||
*/
|
||||
dynamic(attributes) {
|
||||
const {
|
||||
NOW,
|
||||
clientOffset,
|
||||
availabilityStartTime,
|
||||
timescale = 1,
|
||||
duration,
|
||||
start = 0,
|
||||
minimumUpdatePeriod = 0,
|
||||
timeShiftBufferDepth = Infinity
|
||||
} = attributes;
|
||||
const now = (NOW + clientOffset) / 1000;
|
||||
const periodStartWC = availabilityStartTime + start;
|
||||
const periodEndWC = now + minimumUpdatePeriod;
|
||||
const periodDuration = periodEndWC - periodStartWC;
|
||||
const segmentCount = Math.ceil(periodDuration * timescale / duration);
|
||||
const availableStart =
|
||||
Math.floor((now - periodStartWC - timeShiftBufferDepth) * timescale / duration);
|
||||
const availableEnd = Math.floor((now - periodStartWC) * timescale / duration);
|
||||
|
||||
return {
|
||||
start: Math.max(0, availableStart),
|
||||
end: Math.min(segmentCount, availableEnd)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Maps a range of numbers to objects with information needed to build the corresponding
|
||||
* segment list
|
||||
*
|
||||
* @name toSegmentsCallback
|
||||
* @function
|
||||
* @param {number} number
|
||||
* Number of the segment
|
||||
* @param {number} index
|
||||
* Index of the number in the range list
|
||||
* @return {{ number: Number, duration: Number, timeline: Number, time: Number }}
|
||||
* Object with segment timing and duration info
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns a callback for Array.prototype.map for mapping a range of numbers to
|
||||
* information needed to build the segment list.
|
||||
*
|
||||
* @param {Object} attributes
|
||||
* Inherited MPD attributes
|
||||
* @return {toSegmentsCallback}
|
||||
* Callback map function
|
||||
*/
|
||||
export const toSegments = (attributes) => (number, index) => {
|
||||
const {
|
||||
duration,
|
||||
timescale = 1,
|
||||
periodIndex,
|
||||
startNumber = 1
|
||||
} = attributes;
|
||||
|
||||
return {
|
||||
number: startNumber + number,
|
||||
duration: duration / timescale,
|
||||
timeline: periodIndex,
|
||||
time: index * duration
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a list of objects containing segment timing and duration info used for
|
||||
* building the list of segments. This uses the @duration attribute specified
|
||||
* in the MPD manifest to derive the range of segments.
|
||||
*
|
||||
* @param {Object} attributes
|
||||
* Inherited MPD attributes
|
||||
* @return {{number: number, duration: number, time: number, timeline: number}[]}
|
||||
* List of Objects with segment timing and duration info
|
||||
*/
|
||||
export const parseByDuration = (attributes) => {
|
||||
const {
|
||||
type = 'static',
|
||||
duration,
|
||||
timescale = 1,
|
||||
sourceDuration
|
||||
} = attributes;
|
||||
|
||||
const { start, end } = segmentRange[type](attributes);
|
||||
const segments = range(start, end).map(toSegments(attributes));
|
||||
|
||||
if (type === 'static') {
|
||||
const index = segments.length - 1;
|
||||
|
||||
// final segment may be less than full segment duration
|
||||
segments[index].duration = sourceDuration - (duration / timescale * index);
|
||||
}
|
||||
|
||||
return segments;
|
||||
};
|
||||
123
build/javascript/node_modules/mpd-parser/src/segment/segmentBase.js
generated
vendored
123
build/javascript/node_modules/mpd-parser/src/segment/segmentBase.js
generated
vendored
@@ -1,123 +0,0 @@
|
||||
import errors from '../errors';
|
||||
import urlTypeConverter from './urlType';
|
||||
import { parseByDuration } from './durationTimeParser';
|
||||
|
||||
/**
|
||||
* Translates SegmentBase into a set of segments.
|
||||
* (DASH SPEC Section 5.3.9.3.2) contains a set of <SegmentURL> nodes. Each
|
||||
* node should be translated into segment.
|
||||
*
|
||||
* @param {Object} attributes
|
||||
* Object containing all inherited attributes from parent elements with attribute
|
||||
* names as keys
|
||||
* @return {Object.<Array>} list of segments
|
||||
*/
|
||||
export const segmentsFromBase = (attributes) => {
|
||||
const {
|
||||
baseUrl,
|
||||
initialization = {},
|
||||
sourceDuration,
|
||||
indexRange = '',
|
||||
duration
|
||||
} = attributes;
|
||||
|
||||
// base url is required for SegmentBase to work, per spec (Section 5.3.9.2.1)
|
||||
if (!baseUrl) {
|
||||
throw new Error(errors.NO_BASE_URL);
|
||||
}
|
||||
|
||||
const initSegment = urlTypeConverter({
|
||||
baseUrl,
|
||||
source: initialization.sourceURL,
|
||||
range: initialization.range
|
||||
});
|
||||
|
||||
const segment = urlTypeConverter({ baseUrl, source: baseUrl, indexRange });
|
||||
|
||||
segment.map = initSegment;
|
||||
|
||||
// If there is a duration, use it, otherwise use the given duration of the source
|
||||
// (since SegmentBase is only for one total segment)
|
||||
if (duration) {
|
||||
const segmentTimeInfo = parseByDuration(attributes);
|
||||
|
||||
if (segmentTimeInfo.length) {
|
||||
segment.duration = segmentTimeInfo[0].duration;
|
||||
segment.timeline = segmentTimeInfo[0].timeline;
|
||||
}
|
||||
} else if (sourceDuration) {
|
||||
segment.duration = sourceDuration;
|
||||
segment.timeline = 0;
|
||||
}
|
||||
|
||||
// This is used for mediaSequence
|
||||
segment.number = 0;
|
||||
|
||||
return [segment];
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a playlist, a sidx box, and a baseUrl, update the segment list of the playlist
|
||||
* according to the sidx information given.
|
||||
*
|
||||
* playlist.sidx has metadadata about the sidx where-as the sidx param
|
||||
* is the parsed sidx box itself.
|
||||
*
|
||||
* @param {Object} playlist the playlist to update the sidx information for
|
||||
* @param {Object} sidx the parsed sidx box
|
||||
* @return {Object} the playlist object with the updated sidx information
|
||||
*/
|
||||
export const addSegmentsToPlaylist = (playlist, sidx, baseUrl) => {
|
||||
// Retain init segment information
|
||||
const initSegment = playlist.sidx.map ? playlist.sidx.map : null;
|
||||
// Retain source duration from initial master manifest parsing
|
||||
const sourceDuration = playlist.sidx.duration;
|
||||
// Retain source timeline
|
||||
const timeline = playlist.timeline || 0;
|
||||
const sidxByteRange = playlist.sidx.byterange;
|
||||
const sidxEnd = sidxByteRange.offset + sidxByteRange.length;
|
||||
// Retain timescale of the parsed sidx
|
||||
const timescale = sidx.timescale;
|
||||
// referenceType 1 refers to other sidx boxes
|
||||
const mediaReferences = sidx.references.filter(r => r.referenceType !== 1);
|
||||
const segments = [];
|
||||
|
||||
// firstOffset is the offset from the end of the sidx box
|
||||
let startIndex = sidxEnd + sidx.firstOffset;
|
||||
|
||||
for (let i = 0; i < mediaReferences.length; i++) {
|
||||
const reference = sidx.references[i];
|
||||
// size of the referenced (sub)segment
|
||||
const size = reference.referencedSize;
|
||||
// duration of the referenced (sub)segment, in the timescale
|
||||
// this will be converted to seconds when generating segments
|
||||
const duration = reference.subsegmentDuration;
|
||||
// should be an inclusive range
|
||||
const endIndex = startIndex + size - 1;
|
||||
const indexRange = `${startIndex}-${endIndex}`;
|
||||
|
||||
const attributes = {
|
||||
baseUrl,
|
||||
timescale,
|
||||
timeline,
|
||||
// this is used in parseByDuration
|
||||
periodIndex: timeline,
|
||||
duration,
|
||||
sourceDuration,
|
||||
indexRange
|
||||
};
|
||||
|
||||
const segment = segmentsFromBase(attributes)[0];
|
||||
|
||||
if (initSegment) {
|
||||
segment.map = initSegment;
|
||||
}
|
||||
|
||||
segments.push(segment);
|
||||
startIndex += size;
|
||||
}
|
||||
|
||||
playlist.segments = segments;
|
||||
|
||||
return playlist;
|
||||
};
|
||||
90
build/javascript/node_modules/mpd-parser/src/segment/segmentList.js
generated
vendored
90
build/javascript/node_modules/mpd-parser/src/segment/segmentList.js
generated
vendored
@@ -1,90 +0,0 @@
|
||||
import { parseByTimeline } from './timelineTimeParser';
|
||||
import { parseByDuration } from './durationTimeParser';
|
||||
import urlTypeConverter from './urlType';
|
||||
import errors from '../errors';
|
||||
|
||||
/**
|
||||
* Converts a <SegmentUrl> (of type URLType from the DASH spec 5.3.9.2 Table 14)
|
||||
* to an object that matches the output of a segment in videojs/mpd-parser
|
||||
*
|
||||
* @param {Object} attributes
|
||||
* Object containing all inherited attributes from parent elements with attribute
|
||||
* names as keys
|
||||
* @param {Object} segmentUrl
|
||||
* <SegmentURL> node to translate into a segment object
|
||||
* @return {Object} translated segment object
|
||||
*/
|
||||
const SegmentURLToSegmentObject = (attributes, segmentUrl) => {
|
||||
const { baseUrl, initialization = {} } = attributes;
|
||||
|
||||
const initSegment = urlTypeConverter({
|
||||
baseUrl,
|
||||
source: initialization.sourceURL,
|
||||
range: initialization.range
|
||||
});
|
||||
|
||||
const segment = urlTypeConverter({
|
||||
baseUrl,
|
||||
source: segmentUrl.media,
|
||||
range: segmentUrl.mediaRange
|
||||
});
|
||||
|
||||
segment.map = initSegment;
|
||||
|
||||
return segment;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a list of segments using information provided by the SegmentList element
|
||||
* SegmentList (DASH SPEC Section 5.3.9.3.2) contains a set of <SegmentURL> nodes. Each
|
||||
* node should be translated into segment.
|
||||
*
|
||||
* @param {Object} attributes
|
||||
* Object containing all inherited attributes from parent elements with attribute
|
||||
* names as keys
|
||||
* @param {Object[]|undefined} segmentTimeline
|
||||
* List of objects representing the attributes of each S element contained within
|
||||
* the SegmentTimeline element
|
||||
* @return {Object.<Array>} list of segments
|
||||
*/
|
||||
export const segmentsFromList = (attributes, segmentTimeline) => {
|
||||
const {
|
||||
duration,
|
||||
segmentUrls = []
|
||||
} = attributes;
|
||||
|
||||
// Per spec (5.3.9.2.1) no way to determine segment duration OR
|
||||
// if both SegmentTimeline and @duration are defined, it is outside of spec.
|
||||
if ((!duration && !segmentTimeline) ||
|
||||
(duration && segmentTimeline)) {
|
||||
throw new Error(errors.SEGMENT_TIME_UNSPECIFIED);
|
||||
}
|
||||
|
||||
const segmentUrlMap = segmentUrls.map(segmentUrlObject =>
|
||||
SegmentURLToSegmentObject(attributes, segmentUrlObject));
|
||||
let segmentTimeInfo;
|
||||
|
||||
if (duration) {
|
||||
segmentTimeInfo = parseByDuration(attributes);
|
||||
}
|
||||
|
||||
if (segmentTimeline) {
|
||||
segmentTimeInfo = parseByTimeline(attributes, segmentTimeline);
|
||||
}
|
||||
|
||||
const segments = segmentTimeInfo.map((segmentTime, index) => {
|
||||
if (segmentUrlMap[index]) {
|
||||
const segment = segmentUrlMap[index];
|
||||
|
||||
segment.timeline = segmentTime.timeline;
|
||||
segment.duration = segmentTime.duration;
|
||||
segment.number = segmentTime.number;
|
||||
return segment;
|
||||
}
|
||||
// Since we're mapping we should get rid of any blank segments (in case
|
||||
// the given SegmentTimeline is handling for more elements than we have
|
||||
// SegmentURLs for).
|
||||
}).filter(segment => segment);
|
||||
|
||||
return segments;
|
||||
};
|
||||
170
build/javascript/node_modules/mpd-parser/src/segment/segmentTemplate.js
generated
vendored
170
build/javascript/node_modules/mpd-parser/src/segment/segmentTemplate.js
generated
vendored
@@ -1,170 +0,0 @@
|
||||
import resolveUrl from '@videojs/vhs-utils/dist/resolve-url';
|
||||
import urlTypeToSegment from './urlType';
|
||||
import { parseByTimeline } from './timelineTimeParser';
|
||||
import { parseByDuration } from './durationTimeParser';
|
||||
|
||||
const identifierPattern = /\$([A-z]*)(?:(%0)([0-9]+)d)?\$/g;
|
||||
|
||||
/**
|
||||
* Replaces template identifiers with corresponding values. To be used as the callback
|
||||
* for String.prototype.replace
|
||||
*
|
||||
* @name replaceCallback
|
||||
* @function
|
||||
* @param {string} match
|
||||
* Entire match of identifier
|
||||
* @param {string} identifier
|
||||
* Name of matched identifier
|
||||
* @param {string} format
|
||||
* Format tag string. Its presence indicates that padding is expected
|
||||
* @param {string} width
|
||||
* Desired length of the replaced value. Values less than this width shall be left
|
||||
* zero padded
|
||||
* @return {string}
|
||||
* Replacement for the matched identifier
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns a function to be used as a callback for String.prototype.replace to replace
|
||||
* template identifiers
|
||||
*
|
||||
* @param {Obect} values
|
||||
* Object containing values that shall be used to replace known identifiers
|
||||
* @param {number} values.RepresentationID
|
||||
* Value of the Representation@id attribute
|
||||
* @param {number} values.Number
|
||||
* Number of the corresponding segment
|
||||
* @param {number} values.Bandwidth
|
||||
* Value of the Representation@bandwidth attribute.
|
||||
* @param {number} values.Time
|
||||
* Timestamp value of the corresponding segment
|
||||
* @return {replaceCallback}
|
||||
* Callback to be used with String.prototype.replace to replace identifiers
|
||||
*/
|
||||
export const identifierReplacement = (values) => (match, identifier, format, width) => {
|
||||
if (match === '$$') {
|
||||
// escape sequence
|
||||
return '$';
|
||||
}
|
||||
|
||||
if (typeof values[identifier] === 'undefined') {
|
||||
return match;
|
||||
}
|
||||
|
||||
const value = '' + values[identifier];
|
||||
|
||||
if (identifier === 'RepresentationID') {
|
||||
// Format tag shall not be present with RepresentationID
|
||||
return value;
|
||||
}
|
||||
|
||||
if (!format) {
|
||||
width = 1;
|
||||
} else {
|
||||
width = parseInt(width, 10);
|
||||
}
|
||||
|
||||
if (value.length >= width) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return `${(new Array(width - value.length + 1)).join('0')}${value}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs a segment url from a template string
|
||||
*
|
||||
* @param {string} url
|
||||
* Template string to construct url from
|
||||
* @param {Obect} values
|
||||
* Object containing values that shall be used to replace known identifiers
|
||||
* @param {number} values.RepresentationID
|
||||
* Value of the Representation@id attribute
|
||||
* @param {number} values.Number
|
||||
* Number of the corresponding segment
|
||||
* @param {number} values.Bandwidth
|
||||
* Value of the Representation@bandwidth attribute.
|
||||
* @param {number} values.Time
|
||||
* Timestamp value of the corresponding segment
|
||||
* @return {string}
|
||||
* Segment url with identifiers replaced
|
||||
*/
|
||||
export const constructTemplateUrl = (url, values) =>
|
||||
url.replace(identifierPattern, identifierReplacement(values));
|
||||
|
||||
/**
|
||||
* Generates a list of objects containing timing and duration information about each
|
||||
* segment needed to generate segment uris and the complete segment object
|
||||
*
|
||||
* @param {Object} attributes
|
||||
* Object containing all inherited attributes from parent elements with attribute
|
||||
* names as keys
|
||||
* @param {Object[]|undefined} segmentTimeline
|
||||
* List of objects representing the attributes of each S element contained within
|
||||
* the SegmentTimeline element
|
||||
* @return {{number: number, duration: number, time: number, timeline: number}[]}
|
||||
* List of Objects with segment timing and duration info
|
||||
*/
|
||||
export const parseTemplateInfo = (attributes, segmentTimeline) => {
|
||||
if (!attributes.duration && !segmentTimeline) {
|
||||
// if neither @duration or SegmentTimeline are present, then there shall be exactly
|
||||
// one media segment
|
||||
return [{
|
||||
number: attributes.startNumber || 1,
|
||||
duration: attributes.sourceDuration,
|
||||
time: 0,
|
||||
timeline: attributes.periodIndex
|
||||
}];
|
||||
}
|
||||
|
||||
if (attributes.duration) {
|
||||
return parseByDuration(attributes);
|
||||
}
|
||||
|
||||
return parseByTimeline(attributes, segmentTimeline);
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a list of segments using information provided by the SegmentTemplate element
|
||||
*
|
||||
* @param {Object} attributes
|
||||
* Object containing all inherited attributes from parent elements with attribute
|
||||
* names as keys
|
||||
* @param {Object[]|undefined} segmentTimeline
|
||||
* List of objects representing the attributes of each S element contained within
|
||||
* the SegmentTimeline element
|
||||
* @return {Object[]}
|
||||
* List of segment objects
|
||||
*/
|
||||
export const segmentsFromTemplate = (attributes, segmentTimeline) => {
|
||||
const templateValues = {
|
||||
RepresentationID: attributes.id,
|
||||
Bandwidth: attributes.bandwidth || 0
|
||||
};
|
||||
|
||||
const { initialization = { sourceURL: '', range: '' } } = attributes;
|
||||
|
||||
const mapSegment = urlTypeToSegment({
|
||||
baseUrl: attributes.baseUrl,
|
||||
source: constructTemplateUrl(initialization.sourceURL, templateValues),
|
||||
range: initialization.range
|
||||
});
|
||||
|
||||
const segments = parseTemplateInfo(attributes, segmentTimeline);
|
||||
|
||||
return segments.map(segment => {
|
||||
templateValues.Number = segment.number;
|
||||
templateValues.Time = segment.time;
|
||||
|
||||
const uri = constructTemplateUrl(attributes.media || '', templateValues);
|
||||
|
||||
return {
|
||||
uri,
|
||||
timeline: segment.timeline,
|
||||
duration: segment.duration,
|
||||
resolvedUri: resolveUrl(attributes.baseUrl || '', uri),
|
||||
map: mapSegment,
|
||||
number: segment.number
|
||||
};
|
||||
});
|
||||
};
|
||||
129
build/javascript/node_modules/mpd-parser/src/segment/timelineTimeParser.js
generated
vendored
129
build/javascript/node_modules/mpd-parser/src/segment/timelineTimeParser.js
generated
vendored
@@ -1,129 +0,0 @@
|
||||
/**
|
||||
* Calculates the R (repetition) value for a live stream (for the final segment
|
||||
* in a manifest where the r value is negative 1)
|
||||
*
|
||||
* @param {Object} attributes
|
||||
* Object containing all inherited attributes from parent elements with attribute
|
||||
* names as keys
|
||||
* @param {number} time
|
||||
* current time (typically the total time up until the final segment)
|
||||
* @param {number} duration
|
||||
* duration property for the given <S />
|
||||
*
|
||||
* @return {number}
|
||||
* R value to reach the end of the given period
|
||||
*/
|
||||
const getLiveRValue = (attributes, time, duration) => {
|
||||
const {
|
||||
NOW,
|
||||
clientOffset,
|
||||
availabilityStartTime,
|
||||
timescale = 1,
|
||||
start = 0,
|
||||
minimumUpdatePeriod = 0
|
||||
} = attributes;
|
||||
const now = (NOW + clientOffset) / 1000;
|
||||
const periodStartWC = availabilityStartTime + start;
|
||||
const periodEndWC = now + minimumUpdatePeriod;
|
||||
const periodDuration = periodEndWC - periodStartWC;
|
||||
|
||||
return Math.ceil(((periodDuration * timescale) - time) / duration);
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses information provided by SegmentTemplate.SegmentTimeline to determine segment
|
||||
* timing and duration
|
||||
*
|
||||
* @param {Object} attributes
|
||||
* Object containing all inherited attributes from parent elements with attribute
|
||||
* names as keys
|
||||
* @param {Object[]} segmentTimeline
|
||||
* List of objects representing the attributes of each S element contained within
|
||||
*
|
||||
* @return {{number: number, duration: number, time: number, timeline: number}[]}
|
||||
* List of Objects with segment timing and duration info
|
||||
*/
|
||||
export const parseByTimeline = (attributes, segmentTimeline) => {
|
||||
const {
|
||||
type = 'static',
|
||||
minimumUpdatePeriod = 0,
|
||||
media = '',
|
||||
sourceDuration,
|
||||
timescale = 1,
|
||||
startNumber = 1,
|
||||
periodIndex: timeline
|
||||
} = attributes;
|
||||
const segments = [];
|
||||
let time = -1;
|
||||
|
||||
for (let sIndex = 0; sIndex < segmentTimeline.length; sIndex++) {
|
||||
const S = segmentTimeline[sIndex];
|
||||
const duration = S.d;
|
||||
const repeat = S.r || 0;
|
||||
const segmentTime = S.t || 0;
|
||||
|
||||
if (time < 0) {
|
||||
// first segment
|
||||
time = segmentTime;
|
||||
}
|
||||
|
||||
if (segmentTime && segmentTime > time) {
|
||||
// discontinuity
|
||||
|
||||
// TODO: How to handle this type of discontinuity
|
||||
// timeline++ here would treat it like HLS discontuity and content would
|
||||
// get appended without gap
|
||||
// E.G.
|
||||
// <S t="0" d="1" />
|
||||
// <S d="1" />
|
||||
// <S d="1" />
|
||||
// <S t="5" d="1" />
|
||||
// would have $Time$ values of [0, 1, 2, 5]
|
||||
// should this be appened at time positions [0, 1, 2, 3],(#EXT-X-DISCONTINUITY)
|
||||
// or [0, 1, 2, gap, gap, 5]? (#EXT-X-GAP)
|
||||
// does the value of sourceDuration consider this when calculating arbitrary
|
||||
// negative @r repeat value?
|
||||
// E.G. Same elements as above with this added at the end
|
||||
// <S d="1" r="-1" />
|
||||
// with a sourceDuration of 10
|
||||
// Would the 2 gaps be included in the time duration calculations resulting in
|
||||
// 8 segments with $Time$ values of [0, 1, 2, 5, 6, 7, 8, 9] or 10 segments
|
||||
// with $Time$ values of [0, 1, 2, 5, 6, 7, 8, 9, 10, 11] ?
|
||||
|
||||
time = segmentTime;
|
||||
}
|
||||
|
||||
let count;
|
||||
|
||||
if (repeat < 0) {
|
||||
const nextS = sIndex + 1;
|
||||
|
||||
if (nextS === segmentTimeline.length) {
|
||||
// last segment
|
||||
if (type === 'dynamic' &&
|
||||
minimumUpdatePeriod > 0 &&
|
||||
media.indexOf('$Number$') > 0) {
|
||||
count = getLiveRValue(attributes, time, duration);
|
||||
} else {
|
||||
// TODO: This may be incorrect depending on conclusion of TODO above
|
||||
count = ((sourceDuration * timescale) - time) / duration;
|
||||
}
|
||||
} else {
|
||||
count = (segmentTimeline[nextS].t - time) / duration;
|
||||
}
|
||||
} else {
|
||||
count = repeat + 1;
|
||||
}
|
||||
|
||||
const end = startNumber + segments.length + count;
|
||||
let number = startNumber + segments.length;
|
||||
|
||||
while (number < end) {
|
||||
segments.push({ number, duration: duration / timescale, time, timeline });
|
||||
time += duration;
|
||||
number++;
|
||||
}
|
||||
}
|
||||
|
||||
return segments;
|
||||
};
|
||||
59
build/javascript/node_modules/mpd-parser/src/segment/urlType.js
generated
vendored
59
build/javascript/node_modules/mpd-parser/src/segment/urlType.js
generated
vendored
@@ -1,59 +0,0 @@
|
||||
import resolveUrl from '@videojs/vhs-utils/dist/resolve-url';
|
||||
|
||||
/**
|
||||
* @typedef {Object} SingleUri
|
||||
* @property {string} uri - relative location of segment
|
||||
* @property {string} resolvedUri - resolved location of segment
|
||||
* @property {Object} byterange - Object containing information on how to make byte range
|
||||
* requests following byte-range-spec per RFC2616.
|
||||
* @property {String} byterange.length - length of range request
|
||||
* @property {String} byterange.offset - byte offset of range request
|
||||
*
|
||||
* @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.1
|
||||
*/
|
||||
|
||||
/**
|
||||
* Converts a URLType node (5.3.9.2.3 Table 13) to a segment object
|
||||
* that conforms to how m3u8-parser is structured
|
||||
*
|
||||
* @see https://github.com/videojs/m3u8-parser
|
||||
*
|
||||
* @param {string} baseUrl - baseUrl provided by <BaseUrl> nodes
|
||||
* @param {string} source - source url for segment
|
||||
* @param {string} range - optional range used for range calls,
|
||||
* follows RFC 2616, Clause 14.35.1
|
||||
* @return {SingleUri} full segment information transformed into a format similar
|
||||
* to m3u8-parser
|
||||
*/
|
||||
export const urlTypeToSegment = ({ baseUrl = '', source = '', range = '', indexRange = '' }) => {
|
||||
const segment = {
|
||||
uri: source,
|
||||
resolvedUri: resolveUrl(baseUrl || '', source)
|
||||
};
|
||||
|
||||
if (range || indexRange) {
|
||||
const rangeStr = range ? range : indexRange;
|
||||
const ranges = rangeStr.split('-');
|
||||
const startRange = parseInt(ranges[0], 10);
|
||||
const endRange = parseInt(ranges[1], 10);
|
||||
|
||||
// byterange should be inclusive according to
|
||||
// RFC 2616, Clause 14.35.1
|
||||
segment.byterange = {
|
||||
length: endRange - startRange + 1,
|
||||
offset: startRange
|
||||
};
|
||||
}
|
||||
|
||||
return segment;
|
||||
};
|
||||
|
||||
export const byteRangeToString = (byterange) => {
|
||||
// `endRange` is one less than `offset + length` because the HTTP range
|
||||
// header uses inclusive ranges
|
||||
const endRange = byterange.offset + byterange.length - 1;
|
||||
|
||||
return `${byterange.offset}-${endRange}`;
|
||||
};
|
||||
|
||||
export default urlTypeToSegment;
|
||||
20
build/javascript/node_modules/mpd-parser/src/stringToMpdXml.js
generated
vendored
20
build/javascript/node_modules/mpd-parser/src/stringToMpdXml.js
generated
vendored
@@ -1,20 +0,0 @@
|
||||
import {DOMParser} from 'xmldom';
|
||||
import errors from './errors';
|
||||
|
||||
export const stringToMpdXml = (manifestString) => {
|
||||
if (manifestString === '') {
|
||||
throw new Error(errors.DASH_EMPTY_MANIFEST);
|
||||
}
|
||||
|
||||
const parser = new DOMParser();
|
||||
const xml = parser.parseFromString(manifestString, 'application/xml');
|
||||
const mpd = xml && xml.documentElement.tagName === 'MPD' ?
|
||||
xml.documentElement : null;
|
||||
|
||||
if (!mpd || mpd &&
|
||||
mpd.getElementsByTagName('parsererror').length > 0) {
|
||||
throw new Error(errors.DASH_INVALID_XML);
|
||||
}
|
||||
|
||||
return mpd;
|
||||
};
|
||||
295
build/javascript/node_modules/mpd-parser/src/toM3u8.js
generated
vendored
295
build/javascript/node_modules/mpd-parser/src/toM3u8.js
generated
vendored
@@ -1,295 +0,0 @@
|
||||
import { values } from './utils/object';
|
||||
import { findIndexes } from './utils/list';
|
||||
import { addSegmentsToPlaylist } from './segment/segmentBase';
|
||||
import { byteRangeToString } from './segment/urlType';
|
||||
|
||||
const mergeDiscontiguousPlaylists = playlists => {
|
||||
const mergedPlaylists = values(playlists.reduce((acc, playlist) => {
|
||||
// assuming playlist IDs are the same across periods
|
||||
// TODO: handle multiperiod where representation sets are not the same
|
||||
// across periods
|
||||
const name = playlist.attributes.id + (playlist.attributes.lang || '');
|
||||
|
||||
// Periods after first
|
||||
if (acc[name]) {
|
||||
// first segment of subsequent periods signal a discontinuity
|
||||
if (playlist.segments[0]) {
|
||||
playlist.segments[0].discontinuity = true;
|
||||
}
|
||||
acc[name].segments.push(...playlist.segments);
|
||||
|
||||
// bubble up contentProtection, this assumes all DRM content
|
||||
// has the same contentProtection
|
||||
if (playlist.attributes.contentProtection) {
|
||||
acc[name].attributes.contentProtection =
|
||||
playlist.attributes.contentProtection;
|
||||
}
|
||||
} else {
|
||||
// first Period
|
||||
acc[name] = playlist;
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {}));
|
||||
|
||||
return mergedPlaylists.map(playlist => {
|
||||
playlist.discontinuityStarts =
|
||||
findIndexes(playlist.segments, 'discontinuity');
|
||||
|
||||
return playlist;
|
||||
});
|
||||
};
|
||||
|
||||
const addSegmentInfoFromSidx = (playlists, sidxMapping = {}) => {
|
||||
if (!Object.keys(sidxMapping).length) {
|
||||
return playlists;
|
||||
}
|
||||
|
||||
for (const i in playlists) {
|
||||
const playlist = playlists[i];
|
||||
|
||||
if (!playlist.sidx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const sidxKey = playlist.sidx.uri + '-' +
|
||||
byteRangeToString(playlist.sidx.byterange);
|
||||
const sidxMatch = sidxMapping[sidxKey] && sidxMapping[sidxKey].sidx;
|
||||
|
||||
if (playlist.sidx && sidxMatch) {
|
||||
addSegmentsToPlaylist(playlist, sidxMatch, playlist.sidx.resolvedUri);
|
||||
}
|
||||
}
|
||||
|
||||
return playlists;
|
||||
};
|
||||
|
||||
export const formatAudioPlaylist = ({ attributes, segments, sidx }) => {
|
||||
const playlist = {
|
||||
attributes: {
|
||||
NAME: attributes.id,
|
||||
BANDWIDTH: attributes.bandwidth,
|
||||
CODECS: attributes.codecs,
|
||||
['PROGRAM-ID']: 1
|
||||
},
|
||||
uri: '',
|
||||
endList: (attributes.type || 'static') === 'static',
|
||||
timeline: attributes.periodIndex,
|
||||
resolvedUri: '',
|
||||
targetDuration: attributes.duration,
|
||||
segments,
|
||||
mediaSequence: segments.length ? segments[0].number : 1
|
||||
};
|
||||
|
||||
if (attributes.contentProtection) {
|
||||
playlist.contentProtection = attributes.contentProtection;
|
||||
}
|
||||
|
||||
if (sidx) {
|
||||
playlist.sidx = sidx;
|
||||
}
|
||||
|
||||
return playlist;
|
||||
};
|
||||
|
||||
export const formatVttPlaylist = ({ attributes, segments }) => {
|
||||
if (typeof segments === 'undefined') {
|
||||
// vtt tracks may use single file in BaseURL
|
||||
segments = [{
|
||||
uri: attributes.baseUrl,
|
||||
timeline: attributes.periodIndex,
|
||||
resolvedUri: attributes.baseUrl || '',
|
||||
duration: attributes.sourceDuration,
|
||||
number: 0
|
||||
}];
|
||||
// targetDuration should be the same duration as the only segment
|
||||
attributes.duration = attributes.sourceDuration;
|
||||
}
|
||||
return {
|
||||
attributes: {
|
||||
NAME: attributes.id,
|
||||
BANDWIDTH: attributes.bandwidth,
|
||||
['PROGRAM-ID']: 1
|
||||
},
|
||||
uri: '',
|
||||
endList: (attributes.type || 'static') === 'static',
|
||||
timeline: attributes.periodIndex,
|
||||
resolvedUri: attributes.baseUrl || '',
|
||||
targetDuration: attributes.duration,
|
||||
segments,
|
||||
mediaSequence: segments.length ? segments[0].number : 1
|
||||
};
|
||||
};
|
||||
|
||||
export const organizeAudioPlaylists = (playlists, sidxMapping = {}) => {
|
||||
let mainPlaylist;
|
||||
|
||||
const formattedPlaylists = playlists.reduce((a, playlist) => {
|
||||
const role = playlist.attributes.role &&
|
||||
playlist.attributes.role.value || '';
|
||||
const language = playlist.attributes.lang || '';
|
||||
|
||||
let label = 'main';
|
||||
|
||||
if (language) {
|
||||
const roleLabel = role ? ` (${role})` : '';
|
||||
|
||||
label = `${playlist.attributes.lang}${roleLabel}`;
|
||||
}
|
||||
|
||||
// skip if we already have the highest quality audio for a language
|
||||
if (a[label] &&
|
||||
a[label].playlists[0].attributes.BANDWIDTH >
|
||||
playlist.attributes.bandwidth) {
|
||||
return a;
|
||||
}
|
||||
|
||||
a[label] = {
|
||||
language,
|
||||
autoselect: true,
|
||||
default: role === 'main',
|
||||
playlists: addSegmentInfoFromSidx(
|
||||
[formatAudioPlaylist(playlist)],
|
||||
sidxMapping
|
||||
),
|
||||
uri: ''
|
||||
};
|
||||
|
||||
if (typeof mainPlaylist === 'undefined' && role === 'main') {
|
||||
mainPlaylist = playlist;
|
||||
mainPlaylist.default = true;
|
||||
}
|
||||
|
||||
return a;
|
||||
}, {});
|
||||
|
||||
// if no playlists have role "main", mark the first as main
|
||||
if (!mainPlaylist) {
|
||||
const firstLabel = Object.keys(formattedPlaylists)[0];
|
||||
|
||||
formattedPlaylists[firstLabel].default = true;
|
||||
}
|
||||
|
||||
return formattedPlaylists;
|
||||
};
|
||||
|
||||
export const organizeVttPlaylists = (playlists, sidxMapping = {}) => {
|
||||
return playlists.reduce((a, playlist) => {
|
||||
const label = playlist.attributes.lang || 'text';
|
||||
|
||||
// skip if we already have subtitles
|
||||
if (a[label]) {
|
||||
return a;
|
||||
}
|
||||
|
||||
a[label] = {
|
||||
language: label,
|
||||
default: false,
|
||||
autoselect: false,
|
||||
playlists: addSegmentInfoFromSidx(
|
||||
[formatVttPlaylist(playlist)],
|
||||
sidxMapping
|
||||
),
|
||||
uri: ''
|
||||
};
|
||||
|
||||
return a;
|
||||
}, {});
|
||||
};
|
||||
|
||||
export const formatVideoPlaylist = ({ attributes, segments, sidx }) => {
|
||||
const playlist = {
|
||||
attributes: {
|
||||
NAME: attributes.id,
|
||||
AUDIO: 'audio',
|
||||
SUBTITLES: 'subs',
|
||||
RESOLUTION: {
|
||||
width: attributes.width,
|
||||
height: attributes.height
|
||||
},
|
||||
CODECS: attributes.codecs,
|
||||
BANDWIDTH: attributes.bandwidth,
|
||||
['PROGRAM-ID']: 1
|
||||
},
|
||||
uri: '',
|
||||
endList: (attributes.type || 'static') === 'static',
|
||||
timeline: attributes.periodIndex,
|
||||
resolvedUri: '',
|
||||
targetDuration: attributes.duration,
|
||||
segments,
|
||||
mediaSequence: segments.length ? segments[0].number : 1
|
||||
};
|
||||
|
||||
if (attributes.contentProtection) {
|
||||
playlist.contentProtection = attributes.contentProtection;
|
||||
}
|
||||
|
||||
if (sidx) {
|
||||
playlist.sidx = sidx;
|
||||
}
|
||||
|
||||
return playlist;
|
||||
};
|
||||
|
||||
export const toM3u8 = (dashPlaylists, locations, sidxMapping = {}) => {
|
||||
if (!dashPlaylists.length) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// grab all master attributes
|
||||
const {
|
||||
sourceDuration: duration,
|
||||
type = 'static',
|
||||
suggestedPresentationDelay,
|
||||
minimumUpdatePeriod
|
||||
} = dashPlaylists[0].attributes;
|
||||
|
||||
const videoOnly = ({ attributes }) =>
|
||||
attributes.mimeType === 'video/mp4' || attributes.contentType === 'video';
|
||||
const audioOnly = ({ attributes }) =>
|
||||
attributes.mimeType === 'audio/mp4' || attributes.contentType === 'audio';
|
||||
const vttOnly = ({ attributes }) =>
|
||||
attributes.mimeType === 'text/vtt' || attributes.contentType === 'text';
|
||||
|
||||
const videoPlaylists = mergeDiscontiguousPlaylists(dashPlaylists.filter(videoOnly)).map(formatVideoPlaylist);
|
||||
const audioPlaylists = mergeDiscontiguousPlaylists(dashPlaylists.filter(audioOnly));
|
||||
const vttPlaylists = dashPlaylists.filter(vttOnly);
|
||||
|
||||
const master = {
|
||||
allowCache: true,
|
||||
discontinuityStarts: [],
|
||||
segments: [],
|
||||
endList: true,
|
||||
mediaGroups: {
|
||||
AUDIO: {},
|
||||
VIDEO: {},
|
||||
['CLOSED-CAPTIONS']: {},
|
||||
SUBTITLES: {}
|
||||
},
|
||||
uri: '',
|
||||
duration,
|
||||
playlists: addSegmentInfoFromSidx(videoPlaylists, sidxMapping)
|
||||
};
|
||||
|
||||
if (minimumUpdatePeriod >= 0) {
|
||||
master.minimumUpdatePeriod = minimumUpdatePeriod * 1000;
|
||||
}
|
||||
|
||||
if (locations) {
|
||||
master.locations = locations;
|
||||
}
|
||||
|
||||
if (type === 'dynamic') {
|
||||
master.suggestedPresentationDelay = suggestedPresentationDelay;
|
||||
}
|
||||
|
||||
if (audioPlaylists.length) {
|
||||
master.mediaGroups.AUDIO.audio = organizeAudioPlaylists(audioPlaylists, sidxMapping);
|
||||
}
|
||||
|
||||
if (vttPlaylists.length) {
|
||||
master.mediaGroups.SUBTITLES.subs = organizeVttPlaylists(vttPlaylists, sidxMapping);
|
||||
}
|
||||
|
||||
return master;
|
||||
};
|
||||
60
build/javascript/node_modules/mpd-parser/src/toPlaylists.js
generated
vendored
60
build/javascript/node_modules/mpd-parser/src/toPlaylists.js
generated
vendored
@@ -1,60 +0,0 @@
|
||||
import { merge } from './utils/object';
|
||||
import { segmentsFromTemplate } from './segment/segmentTemplate';
|
||||
import { segmentsFromList } from './segment/segmentList';
|
||||
import { segmentsFromBase } from './segment/segmentBase';
|
||||
|
||||
export const generateSegments = ({ attributes, segmentInfo }) => {
|
||||
let segmentAttributes;
|
||||
let segmentsFn;
|
||||
|
||||
if (segmentInfo.template) {
|
||||
segmentsFn = segmentsFromTemplate;
|
||||
segmentAttributes = merge(attributes, segmentInfo.template);
|
||||
} else if (segmentInfo.base) {
|
||||
segmentsFn = segmentsFromBase;
|
||||
segmentAttributes = merge(attributes, segmentInfo.base);
|
||||
} else if (segmentInfo.list) {
|
||||
segmentsFn = segmentsFromList;
|
||||
segmentAttributes = merge(attributes, segmentInfo.list);
|
||||
}
|
||||
|
||||
const segmentsInfo = {
|
||||
attributes
|
||||
};
|
||||
|
||||
if (!segmentsFn) {
|
||||
return segmentsInfo;
|
||||
}
|
||||
|
||||
const segments = segmentsFn(segmentAttributes, segmentInfo.timeline);
|
||||
|
||||
// The @duration attribute will be used to determin the playlist's targetDuration which
|
||||
// must be in seconds. Since we've generated the segment list, we no longer need
|
||||
// @duration to be in @timescale units, so we can convert it here.
|
||||
if (segmentAttributes.duration) {
|
||||
const { duration, timescale = 1 } = segmentAttributes;
|
||||
|
||||
segmentAttributes.duration = duration / timescale;
|
||||
} else if (segments.length) {
|
||||
// if there is no @duration attribute, use the largest segment duration as
|
||||
// as target duration
|
||||
segmentAttributes.duration = segments.reduce((max, segment) => {
|
||||
return Math.max(max, Math.ceil(segment.duration));
|
||||
}, 0);
|
||||
} else {
|
||||
segmentAttributes.duration = 0;
|
||||
}
|
||||
|
||||
segmentsInfo.attributes = segmentAttributes;
|
||||
segmentsInfo.segments = segments;
|
||||
|
||||
// This is a sidx box without actual segment information
|
||||
if (segmentInfo.base && segmentAttributes.indexRange) {
|
||||
segmentsInfo.sidx = segments[0];
|
||||
segmentsInfo.segments = [];
|
||||
}
|
||||
|
||||
return segmentsInfo;
|
||||
};
|
||||
|
||||
export const toPlaylists = (representations) => representations.map(generateSegments);
|
||||
33
build/javascript/node_modules/mpd-parser/src/utils/list.js
generated
vendored
33
build/javascript/node_modules/mpd-parser/src/utils/list.js
generated
vendored
@@ -1,33 +0,0 @@
|
||||
export const range = (start, end) => {
|
||||
const result = [];
|
||||
|
||||
for (let i = start; i < end; i++) {
|
||||
result.push(i);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
export const flatten = lists => lists.reduce((x, y) => x.concat(y), []);
|
||||
|
||||
export const from = list => {
|
||||
if (!list.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const result = [];
|
||||
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
result.push(list[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
export const findIndexes = (l, key) => l.reduce((a, e, i) => {
|
||||
if (e[key]) {
|
||||
a.push(i);
|
||||
}
|
||||
|
||||
return a;
|
||||
}, []);
|
||||
23
build/javascript/node_modules/mpd-parser/src/utils/object.js
generated
vendored
23
build/javascript/node_modules/mpd-parser/src/utils/object.js
generated
vendored
@@ -1,23 +0,0 @@
|
||||
const isObject = (obj) => {
|
||||
return !!obj && typeof obj === 'object';
|
||||
};
|
||||
|
||||
export const merge = (...objects) => {
|
||||
|
||||
return objects.reduce((result, source) => {
|
||||
|
||||
Object.keys(source).forEach(key => {
|
||||
|
||||
if (Array.isArray(result[key]) && Array.isArray(source[key])) {
|
||||
result[key] = result[key].concat(source[key]);
|
||||
} else if (isObject(result[key]) && isObject(source[key])) {
|
||||
result[key] = merge(result[key], source[key]);
|
||||
} else {
|
||||
result[key] = source[key];
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}, {});
|
||||
};
|
||||
|
||||
export const values = o => Object.keys(o).map(k => o[k]);
|
||||
39
build/javascript/node_modules/mpd-parser/src/utils/time.js
generated
vendored
39
build/javascript/node_modules/mpd-parser/src/utils/time.js
generated
vendored
@@ -1,39 +0,0 @@
|
||||
export const parseDuration = (str) => {
|
||||
const SECONDS_IN_YEAR = 365 * 24 * 60 * 60;
|
||||
const SECONDS_IN_MONTH = 30 * 24 * 60 * 60;
|
||||
const SECONDS_IN_DAY = 24 * 60 * 60;
|
||||
const SECONDS_IN_HOUR = 60 * 60;
|
||||
const SECONDS_IN_MIN = 60;
|
||||
|
||||
// P10Y10M10DT10H10M10.1S
|
||||
const durationRegex =
|
||||
/P(?:(\d*)Y)?(?:(\d*)M)?(?:(\d*)D)?(?:T(?:(\d*)H)?(?:(\d*)M)?(?:([\d.]*)S)?)?/;
|
||||
const match = durationRegex.exec(str);
|
||||
|
||||
if (!match) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const [year, month, day, hour, minute, second] = match.slice(1);
|
||||
|
||||
return (parseFloat(year || 0) * SECONDS_IN_YEAR +
|
||||
parseFloat(month || 0) * SECONDS_IN_MONTH +
|
||||
parseFloat(day || 0) * SECONDS_IN_DAY +
|
||||
parseFloat(hour || 0) * SECONDS_IN_HOUR +
|
||||
parseFloat(minute || 0) * SECONDS_IN_MIN +
|
||||
parseFloat(second || 0));
|
||||
};
|
||||
|
||||
export const parseDate = (str) => {
|
||||
// Date format without timezone according to ISO 8601
|
||||
// YYY-MM-DDThh:mm:ss.ssssss
|
||||
const dateRegex = /^\d+-\d+-\d+T\d+:\d+:\d+(\.\d+)?$/;
|
||||
|
||||
// If the date string does not specifiy a timezone, we must specifiy UTC. This is
|
||||
// expressed by ending with 'Z'
|
||||
if (dateRegex.test(str)) {
|
||||
str += 'Z';
|
||||
}
|
||||
|
||||
return Date.parse(str);
|
||||
};
|
||||
6
build/javascript/node_modules/mpd-parser/src/utils/xml.js
generated
vendored
6
build/javascript/node_modules/mpd-parser/src/utils/xml.js
generated
vendored
@@ -1,6 +0,0 @@
|
||||
import { from } from './list';
|
||||
|
||||
export const findChildren = (element, name) =>
|
||||
from(element.childNodes).filter(({tagName}) => tagName === name);
|
||||
|
||||
export const getContent = element => element.textContent.trim();
|
||||
78
build/javascript/node_modules/mpd-parser/test/index.test.js
generated
vendored
78
build/javascript/node_modules/mpd-parser/test/index.test.js
generated
vendored
@@ -1,78 +0,0 @@
|
||||
import { parse, VERSION } from '../src';
|
||||
import QUnit from 'qunit';
|
||||
|
||||
// manifests
|
||||
import maatVttSegmentTemplate from './manifests/maat_vtt_segmentTemplate.mpd';
|
||||
import segmentBaseTemplate from './manifests/segmentBase.mpd';
|
||||
import segmentListTemplate from './manifests/segmentList.mpd';
|
||||
import locationTemplate from './manifests/location.mpd';
|
||||
import locationsTemplate from './manifests/locations.mpd';
|
||||
import multiperiod from './manifests/multiperiod.mpd';
|
||||
import multiperiodDynamic from './manifests/multiperiod-dynamic.mpd';
|
||||
import {
|
||||
parsedManifest as maatVttSegmentTemplateManifest
|
||||
} from './manifests/maat_vtt_segmentTemplate.js';
|
||||
import {
|
||||
parsedManifest as segmentBaseManifest
|
||||
} from './manifests/segmentBase.js';
|
||||
import {
|
||||
parsedManifest as segmentListManifest
|
||||
} from './manifests/segmentList.js';
|
||||
import {
|
||||
parsedManifest as multiperiodManifest
|
||||
} from './manifests/multiperiod.js';
|
||||
import {
|
||||
parsedManifest as multiperiodDynamicManifest
|
||||
} from './manifests/multiperiod-dynamic.js';
|
||||
import {
|
||||
parsedManifest as locationManifest
|
||||
} from './manifests/location.js';
|
||||
import {
|
||||
parsedManifest as locationsManifest
|
||||
} from './manifests/locations.js';
|
||||
|
||||
QUnit.module('mpd-parser');
|
||||
|
||||
QUnit.test('has VERSION', function(assert) {
|
||||
assert.ok(VERSION);
|
||||
});
|
||||
|
||||
QUnit.test('has parse', function(assert) {
|
||||
assert.ok(parse);
|
||||
});
|
||||
|
||||
[{
|
||||
name: 'maat_vtt_segmentTemplate',
|
||||
input: maatVttSegmentTemplate,
|
||||
expected: maatVttSegmentTemplateManifest
|
||||
}, {
|
||||
name: 'segmentBase',
|
||||
input: segmentBaseTemplate,
|
||||
expected: segmentBaseManifest
|
||||
}, {
|
||||
name: 'segmentList',
|
||||
input: segmentListTemplate,
|
||||
expected: segmentListManifest
|
||||
}, {
|
||||
name: 'multiperiod',
|
||||
input: multiperiod,
|
||||
expected: multiperiodManifest
|
||||
}, {
|
||||
name: 'multiperiod_dynamic',
|
||||
input: multiperiodDynamic,
|
||||
expected: multiperiodDynamicManifest
|
||||
}, {
|
||||
name: 'location',
|
||||
input: locationTemplate,
|
||||
expected: locationManifest
|
||||
}, {
|
||||
name: 'locations',
|
||||
input: locationsTemplate,
|
||||
expected: locationsManifest
|
||||
}].forEach(({ name, input, expected }) => {
|
||||
QUnit.test(`${name} test manifest`, function(assert) {
|
||||
const actual = parse(input);
|
||||
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
1499
build/javascript/node_modules/mpd-parser/test/inheritAttributes.test.js
generated
vendored
1499
build/javascript/node_modules/mpd-parser/test/inheritAttributes.test.js
generated
vendored
File diff suppressed because it is too large
Load Diff
52
build/javascript/node_modules/mpd-parser/test/manifests/location.js
generated
vendored
52
build/javascript/node_modules/mpd-parser/test/manifests/location.js
generated
vendored
@@ -1,52 +0,0 @@
|
||||
export const parsedManifest = {
|
||||
locations: [
|
||||
'https://www.example.com/updates'
|
||||
],
|
||||
allowCache: true,
|
||||
discontinuityStarts: [],
|
||||
duration: 6,
|
||||
endList: true,
|
||||
mediaGroups: {
|
||||
'AUDIO': {},
|
||||
'CLOSED-CAPTIONS': {},
|
||||
'SUBTITLES': {},
|
||||
'VIDEO': {}
|
||||
},
|
||||
playlists: [
|
||||
{
|
||||
attributes: {
|
||||
'AUDIO': 'audio',
|
||||
'BANDWIDTH': 449000,
|
||||
'CODECS': 'avc1.420015',
|
||||
'NAME': '482',
|
||||
'PROGRAM-ID': 1,
|
||||
'RESOLUTION': {
|
||||
height: 270,
|
||||
width: 482
|
||||
},
|
||||
'SUBTITLES': 'subs'
|
||||
},
|
||||
endList: true,
|
||||
resolvedUri: '',
|
||||
targetDuration: 6,
|
||||
mediaSequence: 0,
|
||||
segments: [
|
||||
{
|
||||
duration: 6,
|
||||
timeline: 0,
|
||||
number: 0,
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'https://www.example.com/1080p.ts'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/1080p.ts',
|
||||
uri: 'https://www.example.com/1080p.ts'
|
||||
}
|
||||
],
|
||||
timeline: 0,
|
||||
uri: ''
|
||||
}
|
||||
],
|
||||
segments: [],
|
||||
uri: ''
|
||||
};
|
||||
17
build/javascript/node_modules/mpd-parser/test/manifests/location.mpd
generated
vendored
17
build/javascript/node_modules/mpd-parser/test/manifests/location.mpd
generated
vendored
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" profiles="urn:mpeg:dash:profile:isoff-live:2011" type="static" mediaPresentationDuration="PT6S" minBufferTime="PT2.000S">
|
||||
<BaseURL>https://www.example.com/base</BaseURL>
|
||||
<Location>https://www.example.com/updates</Location>
|
||||
<Period>
|
||||
<AdaptationSet mimeType="video/mp4" scanType="progressive" segmentAlignment="true" startWithSAP="1">
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<Representation bandwidth="449000" codecs="avc1.420015" frameRate="2997/125" height="270" id="482" width="482" >
|
||||
<SegmentBase></SegmentBase>
|
||||
</Representation>
|
||||
<BaseURL>1080p.ts</BaseURL>
|
||||
<SegmentBase>
|
||||
<RepresentationIndex sourceURL="1080p.sidx"/>
|
||||
</SegmentBase>
|
||||
</AdaptationSet>
|
||||
</Period>
|
||||
</MPD>
|
||||
53
build/javascript/node_modules/mpd-parser/test/manifests/locations.js
generated
vendored
53
build/javascript/node_modules/mpd-parser/test/manifests/locations.js
generated
vendored
@@ -1,53 +0,0 @@
|
||||
export const parsedManifest = {
|
||||
locations: [
|
||||
'https://www.example.com/updates',
|
||||
'https://www.example.com/updates2'
|
||||
],
|
||||
allowCache: true,
|
||||
discontinuityStarts: [],
|
||||
duration: 6,
|
||||
endList: true,
|
||||
mediaGroups: {
|
||||
'AUDIO': {},
|
||||
'CLOSED-CAPTIONS': {},
|
||||
'SUBTITLES': {},
|
||||
'VIDEO': {}
|
||||
},
|
||||
playlists: [
|
||||
{
|
||||
attributes: {
|
||||
'AUDIO': 'audio',
|
||||
'BANDWIDTH': 449000,
|
||||
'CODECS': 'avc1.420015',
|
||||
'NAME': '482',
|
||||
'PROGRAM-ID': 1,
|
||||
'RESOLUTION': {
|
||||
height: 270,
|
||||
width: 482
|
||||
},
|
||||
'SUBTITLES': 'subs'
|
||||
},
|
||||
endList: true,
|
||||
resolvedUri: '',
|
||||
targetDuration: 6,
|
||||
mediaSequence: 0,
|
||||
segments: [
|
||||
{
|
||||
duration: 6,
|
||||
timeline: 0,
|
||||
number: 0,
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'https://www.example.com/1080p.ts'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/1080p.ts',
|
||||
uri: 'https://www.example.com/1080p.ts'
|
||||
}
|
||||
],
|
||||
timeline: 0,
|
||||
uri: ''
|
||||
}
|
||||
],
|
||||
segments: [],
|
||||
uri: ''
|
||||
};
|
||||
18
build/javascript/node_modules/mpd-parser/test/manifests/locations.mpd
generated
vendored
18
build/javascript/node_modules/mpd-parser/test/manifests/locations.mpd
generated
vendored
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" profiles="urn:mpeg:dash:profile:isoff-live:2011" type="static" mediaPresentationDuration="PT6S" minBufferTime="PT2.000S">
|
||||
<BaseURL>https://www.example.com/base</BaseURL>
|
||||
<Location>https://www.example.com/updates</Location>
|
||||
<Location>https://www.example.com/updates2</Location>
|
||||
<Period>
|
||||
<AdaptationSet mimeType="video/mp4" scanType="progressive" segmentAlignment="true" startWithSAP="1">
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<Representation bandwidth="449000" codecs="avc1.420015" frameRate="2997/125" height="270" id="482" width="482" >
|
||||
<SegmentBase></SegmentBase>
|
||||
</Representation>
|
||||
<BaseURL>1080p.ts</BaseURL>
|
||||
<SegmentBase>
|
||||
<RepresentationIndex sourceURL="1080p.sidx"/>
|
||||
</SegmentBase>
|
||||
</AdaptationSet>
|
||||
</Period>
|
||||
</MPD>
|
||||
347
build/javascript/node_modules/mpd-parser/test/manifests/maat_vtt_segmentTemplate.js
generated
vendored
347
build/javascript/node_modules/mpd-parser/test/manifests/maat_vtt_segmentTemplate.js
generated
vendored
@@ -1,347 +0,0 @@
|
||||
export const parsedManifest = {
|
||||
allowCache: true,
|
||||
discontinuityStarts: [],
|
||||
duration: 6,
|
||||
endList: true,
|
||||
mediaGroups: {
|
||||
AUDIO: {
|
||||
audio: {
|
||||
['en (main)']: {
|
||||
autoselect: true,
|
||||
default: true,
|
||||
language: 'en',
|
||||
playlists: [{
|
||||
attributes: {
|
||||
BANDWIDTH: 125000,
|
||||
CODECS: 'mp4a.40.2',
|
||||
NAME: '125000',
|
||||
['PROGRAM-ID']: 1
|
||||
},
|
||||
contentProtection: {
|
||||
'com.widevine.alpha': {
|
||||
attributes: {
|
||||
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
|
||||
},
|
||||
pssh: new Uint8Array([181, 235, 45])
|
||||
}
|
||||
},
|
||||
endList: true,
|
||||
mediaSequence: 0,
|
||||
targetDuration: 1.984,
|
||||
resolvedUri: '',
|
||||
segments: [{
|
||||
duration: 1.984,
|
||||
map: {
|
||||
resolvedUri: 'https://www.example.com/125000/init.m4f',
|
||||
uri: '125000/init.m4f'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/125000/0.m4f',
|
||||
timeline: 0,
|
||||
uri: '125000/0.m4f',
|
||||
number: 0
|
||||
}, {
|
||||
duration: 1.984,
|
||||
map: {
|
||||
resolvedUri: 'https://www.example.com/125000/init.m4f',
|
||||
uri: '125000/init.m4f'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/125000/1.m4f',
|
||||
timeline: 0,
|
||||
uri: '125000/1.m4f',
|
||||
number: 1
|
||||
}, {
|
||||
duration: 1.984,
|
||||
map: {
|
||||
resolvedUri: 'https://www.example.com/125000/init.m4f',
|
||||
uri: '125000/init.m4f'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/125000/2.m4f',
|
||||
timeline: 0,
|
||||
uri: '125000/2.m4f',
|
||||
number: 2
|
||||
}, {
|
||||
duration: 0.04800000000000004,
|
||||
map: {
|
||||
resolvedUri: 'https://www.example.com/125000/init.m4f',
|
||||
uri: '125000/init.m4f'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/125000/3.m4f',
|
||||
timeline: 0,
|
||||
uri: '125000/3.m4f',
|
||||
number: 3
|
||||
}],
|
||||
timeline: 0,
|
||||
uri: ''
|
||||
}],
|
||||
uri: ''
|
||||
},
|
||||
['es']: {
|
||||
autoselect: true,
|
||||
default: false,
|
||||
language: 'es',
|
||||
playlists: [{
|
||||
attributes: {
|
||||
BANDWIDTH: 125000,
|
||||
CODECS: 'mp4a.40.2',
|
||||
NAME: '125000',
|
||||
['PROGRAM-ID']: 1
|
||||
},
|
||||
contentProtection: {
|
||||
'com.widevine.alpha': {
|
||||
attributes: {
|
||||
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
|
||||
},
|
||||
pssh: new Uint8Array([181, 235, 45])
|
||||
}
|
||||
},
|
||||
endList: true,
|
||||
targetDuration: 1.984,
|
||||
mediaSequence: 0,
|
||||
resolvedUri: '',
|
||||
segments: [{
|
||||
duration: 1.984,
|
||||
map: {
|
||||
resolvedUri: 'https://www.example.com/125000/es/init.m4f',
|
||||
uri: '125000/es/init.m4f'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/125000/es/0.m4f',
|
||||
timeline: 0,
|
||||
uri: '125000/es/0.m4f',
|
||||
number: 0
|
||||
}, {
|
||||
duration: 1.984,
|
||||
map: {
|
||||
resolvedUri: 'https://www.example.com/125000/es/init.m4f',
|
||||
uri: '125000/es/init.m4f'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/125000/es/1.m4f',
|
||||
timeline: 0,
|
||||
uri: '125000/es/1.m4f',
|
||||
number: 1
|
||||
}, {
|
||||
duration: 1.984,
|
||||
map: {
|
||||
resolvedUri: 'https://www.example.com/125000/es/init.m4f',
|
||||
uri: '125000/es/init.m4f'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/125000/es/2.m4f',
|
||||
timeline: 0,
|
||||
uri: '125000/es/2.m4f',
|
||||
number: 2
|
||||
}, {
|
||||
duration: 0.04800000000000004,
|
||||
map: {
|
||||
resolvedUri: 'https://www.example.com/125000/es/init.m4f',
|
||||
uri: '125000/es/init.m4f'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/125000/es/3.m4f',
|
||||
timeline: 0,
|
||||
uri: '125000/es/3.m4f',
|
||||
number: 3
|
||||
}],
|
||||
timeline: 0,
|
||||
uri: ''
|
||||
}],
|
||||
uri: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
['CLOSED-CAPTIONS']: {},
|
||||
SUBTITLES: {
|
||||
subs: {
|
||||
en: {
|
||||
autoselect: false,
|
||||
default: false,
|
||||
language: 'en',
|
||||
playlists: [{
|
||||
attributes: {
|
||||
BANDWIDTH: 256,
|
||||
NAME: 'en',
|
||||
['PROGRAM-ID']: 1
|
||||
},
|
||||
mediaSequence: 0,
|
||||
endList: true,
|
||||
targetDuration: 6,
|
||||
resolvedUri: 'https://example.com/en.vtt',
|
||||
segments: [{
|
||||
duration: 6,
|
||||
resolvedUri: 'https://example.com/en.vtt',
|
||||
timeline: 0,
|
||||
uri: 'https://example.com/en.vtt',
|
||||
number: 0
|
||||
}],
|
||||
timeline: 0,
|
||||
uri: ''
|
||||
}],
|
||||
uri: ''
|
||||
},
|
||||
es: {
|
||||
autoselect: false,
|
||||
default: false,
|
||||
language: 'es',
|
||||
playlists: [{
|
||||
attributes: {
|
||||
BANDWIDTH: 256,
|
||||
NAME: 'es',
|
||||
['PROGRAM-ID']: 1
|
||||
},
|
||||
endList: true,
|
||||
targetDuration: 6,
|
||||
mediaSequence: 0,
|
||||
resolvedUri: 'https://example.com/es.vtt',
|
||||
segments: [{
|
||||
duration: 6,
|
||||
resolvedUri: 'https://example.com/es.vtt',
|
||||
timeline: 0,
|
||||
uri: 'https://example.com/es.vtt',
|
||||
number: 0
|
||||
}],
|
||||
timeline: 0,
|
||||
uri: ''
|
||||
}],
|
||||
uri: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
VIDEO: {}
|
||||
},
|
||||
playlists: [{
|
||||
attributes: {
|
||||
AUDIO: 'audio',
|
||||
SUBTITLES: 'subs',
|
||||
BANDWIDTH: 449000,
|
||||
CODECS: 'avc1.420015',
|
||||
NAME: '482',
|
||||
['PROGRAM-ID']: 1,
|
||||
RESOLUTION: {
|
||||
height: 270,
|
||||
width: 482
|
||||
}
|
||||
},
|
||||
contentProtection: {
|
||||
'com.widevine.alpha': {
|
||||
attributes: {
|
||||
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
|
||||
},
|
||||
pssh: new Uint8Array([181, 235, 45])
|
||||
}
|
||||
},
|
||||
endList: true,
|
||||
targetDuration: 1.9185833333333333,
|
||||
mediaSequence: 0,
|
||||
resolvedUri: '',
|
||||
segments: [{
|
||||
duration: 1.9185833333333333,
|
||||
map: {
|
||||
resolvedUri: 'https://www.example.com/482/init.m4f',
|
||||
uri: '482/init.m4f'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/482/0.m4f',
|
||||
timeline: 0,
|
||||
uri: '482/0.m4f',
|
||||
number: 0
|
||||
}, {
|
||||
duration: 1.9185833333333333,
|
||||
map: {
|
||||
resolvedUri: 'https://www.example.com/482/init.m4f',
|
||||
uri: '482/init.m4f'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/482/1.m4f',
|
||||
timeline: 0,
|
||||
uri: '482/1.m4f',
|
||||
number: 1
|
||||
}, {
|
||||
duration: 1.9185833333333333,
|
||||
map: {
|
||||
resolvedUri: 'https://www.example.com/482/init.m4f',
|
||||
uri: '482/init.m4f'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/482/2.m4f',
|
||||
timeline: 0,
|
||||
uri: '482/2.m4f',
|
||||
number: 2
|
||||
}, {
|
||||
duration: 0.24425000000000008,
|
||||
map: {
|
||||
resolvedUri: 'https://www.example.com/482/init.m4f',
|
||||
uri: '482/init.m4f'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/482/3.m4f',
|
||||
timeline: 0,
|
||||
uri: '482/3.m4f',
|
||||
number: 3
|
||||
}],
|
||||
timeline: 0,
|
||||
uri: ''
|
||||
}, {
|
||||
attributes: {
|
||||
AUDIO: 'audio',
|
||||
SUBTITLES: 'subs',
|
||||
BANDWIDTH: 3971000,
|
||||
CODECS: 'avc1.64001e',
|
||||
NAME: '720',
|
||||
['PROGRAM-ID']: 1,
|
||||
RESOLUTION: {
|
||||
height: 404,
|
||||
width: 720
|
||||
}
|
||||
},
|
||||
contentProtection: {
|
||||
'com.widevine.alpha': {
|
||||
attributes: {
|
||||
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
|
||||
},
|
||||
pssh: new Uint8Array([181, 235, 45])
|
||||
}
|
||||
},
|
||||
endList: true,
|
||||
targetDuration: 1.9185833333333333,
|
||||
mediaSequence: 0,
|
||||
resolvedUri: '',
|
||||
segments: [{
|
||||
duration: 1.9185833333333333,
|
||||
map: {
|
||||
resolvedUri: 'https://www.example.com/720/init.m4f',
|
||||
uri: '720/init.m4f'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/720/0.m4f',
|
||||
timeline: 0,
|
||||
uri: '720/0.m4f',
|
||||
number: 0
|
||||
}, {
|
||||
duration: 1.9185833333333333,
|
||||
map: {
|
||||
resolvedUri: 'https://www.example.com/720/init.m4f',
|
||||
uri: '720/init.m4f'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/720/1.m4f',
|
||||
timeline: 0,
|
||||
uri: '720/1.m4f',
|
||||
number: 1
|
||||
}, {
|
||||
duration: 1.9185833333333333,
|
||||
map: {
|
||||
resolvedUri: 'https://www.example.com/720/init.m4f',
|
||||
uri: '720/init.m4f'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/720/2.m4f',
|
||||
timeline: 0,
|
||||
uri: '720/2.m4f',
|
||||
number: 2
|
||||
}, {
|
||||
duration: 0.24425000000000008,
|
||||
map: {
|
||||
resolvedUri: 'https://www.example.com/720/init.m4f',
|
||||
uri: '720/init.m4f'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/720/3.m4f',
|
||||
timeline: 0,
|
||||
uri: '720/3.m4f',
|
||||
number: 3
|
||||
}],
|
||||
timeline: 0,
|
||||
uri: ''
|
||||
}],
|
||||
segments: [],
|
||||
uri: ''
|
||||
};
|
||||
60
build/javascript/node_modules/mpd-parser/test/manifests/maat_vtt_segmentTemplate.mpd
generated
vendored
60
build/javascript/node_modules/mpd-parser/test/manifests/maat_vtt_segmentTemplate.mpd
generated
vendored
@@ -1,60 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-live:2011" type="static" mediaPresentationDuration="PT6S" minBufferTime="PT2.000S">
|
||||
<BaseURL>https://www.example.com/base</BaseURL>
|
||||
<Period>
|
||||
|
||||
<AdaptationSet mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1" lang="en">
|
||||
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="aaa"/>
|
||||
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||
<cenc:pssh>test</cenc:pssh>
|
||||
</ContentProtection>
|
||||
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate duration="95232" initialization="$RepresentationID$/init.m4f" media="$RepresentationID$/$Number$.m4f" startNumber="0" timescale="48000"></SegmentTemplate>
|
||||
<Representation audioSamplingRate="48000" bandwidth="63000" codecs="mp4a.40.2" id="63000">
|
||||
</Representation>
|
||||
<Representation audioSamplingRate="48000" bandwidth="125000" codecs="mp4a.40.2" id="125000">
|
||||
</Representation>
|
||||
</AdaptationSet>
|
||||
|
||||
<AdaptationSet mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1" lang="es">
|
||||
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="aaa"/>
|
||||
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||
<cenc:pssh>test</cenc:pssh>
|
||||
</ContentProtection>
|
||||
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011"></Role>
|
||||
<SegmentTemplate duration="95232" initialization="$RepresentationID$/es/init.m4f" media="$RepresentationID$/es/$Number$.m4f" startNumber="0" timescale="48000"></SegmentTemplate>
|
||||
<Representation audioSamplingRate="48000" bandwidth="63000" codecs="mp4a.40.2" id="63000">
|
||||
</Representation>
|
||||
<Representation audioSamplingRate="48000" bandwidth="125000" codecs="mp4a.40.2" id="125000">
|
||||
</Representation>
|
||||
</AdaptationSet>
|
||||
|
||||
<AdaptationSet mimeType="video/mp4" scanType="progressive" segmentAlignment="true" startWithSAP="1">
|
||||
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="aaa"/>
|
||||
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||
<cenc:pssh>test</cenc:pssh>
|
||||
</ContentProtection>
|
||||
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate duration="46046" initialization="$RepresentationID$/init.m4f" media="$RepresentationID$/$Number$.m4f" startNumber="0" timescale="24000"></SegmentTemplate>
|
||||
<Representation bandwidth="449000" codecs="avc1.420015" frameRate="2997/125" height="270" id="482" width="482">
|
||||
</Representation>
|
||||
<Representation bandwidth="3971000" codecs="avc1.64001e" frameRate="2997/125" height="404" id="720" width="720">
|
||||
</Representation>
|
||||
</AdaptationSet>
|
||||
|
||||
<AdaptationSet mimeType="text/vtt" lang="en">
|
||||
<Representation bandwidth="256" id="en">
|
||||
<BaseURL>https://example.com/en.vtt</BaseURL>
|
||||
</Representation>
|
||||
</AdaptationSet>
|
||||
<AdaptationSet mimeType="text/vtt" lang="es">
|
||||
<Representation bandwidth="256" id="es">
|
||||
<BaseURL>https://example.com/es.vtt</BaseURL>
|
||||
</Representation>
|
||||
</AdaptationSet>
|
||||
|
||||
</Period>
|
||||
</MPD>
|
||||
952
build/javascript/node_modules/mpd-parser/test/manifests/multiperiod-dynamic.js
generated
vendored
952
build/javascript/node_modules/mpd-parser/test/manifests/multiperiod-dynamic.js
generated
vendored
@@ -1,952 +0,0 @@
|
||||
export const parsedManifest = {
|
||||
allowCache: true,
|
||||
discontinuityStarts: [],
|
||||
segments: [],
|
||||
endList: true,
|
||||
mediaGroups: {
|
||||
'AUDIO': {
|
||||
audio: {
|
||||
'en (main)': {
|
||||
language: 'en',
|
||||
autoselect: true,
|
||||
default: true,
|
||||
playlists: [{
|
||||
attributes: {
|
||||
'NAME': 'default_audio128_2',
|
||||
'BANDWIDTH': 123000,
|
||||
'CODECS': 'mp4a.40.2',
|
||||
'PROGRAM-ID': 1
|
||||
},
|
||||
uri: '',
|
||||
endList: false,
|
||||
timeline: 0,
|
||||
resolvedUri: '',
|
||||
targetDuration: 2,
|
||||
segments: [{
|
||||
uri: 'https://example.com/default_audio128_2/segment0.m4f',
|
||||
timeline: 0,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment0.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init0.m4f'
|
||||
},
|
||||
number: 0
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment1.m4f',
|
||||
timeline: 0,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment1.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init0.m4f'
|
||||
},
|
||||
number: 1
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment2.m4f',
|
||||
timeline: 0,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment2.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init0.m4f'
|
||||
},
|
||||
number: 2
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment3.m4f',
|
||||
timeline: 1,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment3.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init1.m4f'
|
||||
},
|
||||
number: 3,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment4.m4f',
|
||||
timeline: 1,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment4.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init1.m4f'
|
||||
},
|
||||
number: 4
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment5.m4f',
|
||||
timeline: 1,
|
||||
duration: 0.8591383219954648,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment5.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init1.m4f'
|
||||
},
|
||||
number: 5
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment6.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment6.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init2.m4f'
|
||||
},
|
||||
number: 6,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment7.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment7.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init2.m4f'
|
||||
},
|
||||
number: 7
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment8.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment8.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init2.m4f'
|
||||
},
|
||||
number: 8
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment9.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment9.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init2.m4f'
|
||||
},
|
||||
number: 9
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment10.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment10.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init2.m4f'
|
||||
},
|
||||
number: 10
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment11.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment11.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init2.m4f'
|
||||
},
|
||||
number: 11
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment12.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment12.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init2.m4f'
|
||||
},
|
||||
number: 12
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment13.m4f',
|
||||
timeline: 2,
|
||||
duration: 0.023219954648526078,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment13.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init2.m4f'
|
||||
},
|
||||
number: 13
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment14.m4f',
|
||||
timeline: 3,
|
||||
duration: 1.1609977324263039,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment14.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init3.m4f'
|
||||
},
|
||||
number: 14,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment15.m4f',
|
||||
timeline: 3,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment15.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init3.m4f'
|
||||
},
|
||||
number: 15
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment16.m4f',
|
||||
timeline: 4,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment16.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment$Number$.m4f'
|
||||
},
|
||||
number: 16,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment17.m4f',
|
||||
timeline: 4,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment17.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment$Number$.m4f'
|
||||
},
|
||||
number: 17
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment18.m4f',
|
||||
timeline: 4,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment18.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment$Number$.m4f'
|
||||
},
|
||||
number: 18
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment19.m4f',
|
||||
timeline: 4,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment19.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment$Number$.m4f'
|
||||
},
|
||||
number: 19
|
||||
}],
|
||||
mediaSequence: 0,
|
||||
contentProtection: {
|
||||
'com.widevine.alpha': {
|
||||
attributes: {
|
||||
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
|
||||
},
|
||||
pssh: new Uint8Array([181, 235, 45])
|
||||
}
|
||||
}
|
||||
}],
|
||||
uri: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
'VIDEO': {},
|
||||
'CLOSED-CAPTIONS': {},
|
||||
'SUBTITLES': {}
|
||||
},
|
||||
uri: '',
|
||||
duration: 36.269,
|
||||
playlists: [{
|
||||
attributes: {
|
||||
'NAME': 'default_video2000_0_1280x720',
|
||||
'AUDIO': 'audio',
|
||||
'SUBTITLES': 'subs',
|
||||
'RESOLUTION': {
|
||||
width: 1280,
|
||||
height: 720
|
||||
},
|
||||
'CODECS': 'avc1.4d001f',
|
||||
'BANDWIDTH': 2008E3,
|
||||
'PROGRAM-ID': 1
|
||||
},
|
||||
uri: '',
|
||||
endList: false,
|
||||
timeline: 0,
|
||||
resolvedUri: '',
|
||||
targetDuration: 3,
|
||||
segments: [{
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment0.m4f',
|
||||
timeline: 0,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment0.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init0.m4f'
|
||||
},
|
||||
number: 0
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment1.m4f',
|
||||
timeline: 0,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment1.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init0.m4f'
|
||||
},
|
||||
number: 1
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment2.m4f',
|
||||
timeline: 0,
|
||||
duration: 1.9686333333333332,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment2.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init0.m4f'
|
||||
},
|
||||
number: 2
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment3.m4f',
|
||||
timeline: 1,
|
||||
duration: 1.9352666666666667,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment3.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init1.m4f'
|
||||
},
|
||||
number: 3,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment4.m4f',
|
||||
timeline: 1,
|
||||
duration: 1.9352666666666667,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment4.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init1.m4f'
|
||||
},
|
||||
number: 4
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment5.m4f',
|
||||
timeline: 1,
|
||||
duration: 0.9676333333333333,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment5.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init1.m4f'
|
||||
},
|
||||
number: 5
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment6.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment6.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init2.m4f'
|
||||
},
|
||||
number: 6,
|
||||
discontinuity: true
|
||||
},
|
||||
{
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment7.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment7.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init2.m4f'
|
||||
},
|
||||
number: 7
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment8.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment8.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init2.m4f'
|
||||
},
|
||||
number: 8
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment9.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment9.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init2.m4f'
|
||||
},
|
||||
number: 9
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment10.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment10.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init2.m4f'
|
||||
},
|
||||
number: 10
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment11.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment11.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init2.m4f'
|
||||
},
|
||||
number: 11
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment12.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9686333333333332,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment12.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init2.m4f'
|
||||
},
|
||||
number: 12
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment13.m4f',
|
||||
timeline: 3,
|
||||
duration: 0.9676333333333333,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment13.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init3.m4f'
|
||||
},
|
||||
number: 13,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment14.m4f',
|
||||
timeline: 3,
|
||||
duration: 1.9352666666666667,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment14.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init3.m4f'
|
||||
},
|
||||
number: 14
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment15.m4f',
|
||||
timeline: 3,
|
||||
duration: 0.26693333333333336,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment15.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init3.m4f'
|
||||
},
|
||||
number: 15
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment16.m4f',
|
||||
timeline: 4,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment16.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment$Number$.m4f'
|
||||
},
|
||||
number: 16,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment17.m4f',
|
||||
timeline: 4,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment17.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment$Number$.m4f'
|
||||
},
|
||||
number: 17
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment18.m4f',
|
||||
timeline: 4,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment18.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment$Number$.m4f'
|
||||
},
|
||||
number: 18
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment19.m4f',
|
||||
timeline: 4,
|
||||
duration: 1.9686333333333332,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment19.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment$Number$.m4f'
|
||||
},
|
||||
number: 19
|
||||
}],
|
||||
mediaSequence: 0,
|
||||
contentProtection: {
|
||||
'com.widevine.alpha': {
|
||||
attributes: {
|
||||
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
|
||||
},
|
||||
pssh: new Uint8Array([181, 235, 45])
|
||||
}
|
||||
}
|
||||
}, {
|
||||
attributes: {
|
||||
'NAME': 'default_video1200_1_960x540',
|
||||
'AUDIO': 'audio',
|
||||
'SUBTITLES': 'subs',
|
||||
'RESOLUTION': {
|
||||
width: 960,
|
||||
height: 540
|
||||
},
|
||||
'CODECS': 'avc1.4d001f',
|
||||
'BANDWIDTH': 1195E3,
|
||||
'PROGRAM-ID': 1
|
||||
},
|
||||
uri: '',
|
||||
endList: false,
|
||||
timeline: 0,
|
||||
resolvedUri: '',
|
||||
targetDuration: 3,
|
||||
segments: [{
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment0.m4f',
|
||||
timeline: 0,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment0.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init0.m4f'
|
||||
},
|
||||
number: 0
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment1.m4f',
|
||||
timeline: 0,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment1.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init0.m4f'
|
||||
},
|
||||
number: 1
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment2.m4f',
|
||||
timeline: 0,
|
||||
duration: 1.9686333333333332,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment2.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init0.m4f'
|
||||
},
|
||||
number: 2
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment3.m4f',
|
||||
timeline: 1,
|
||||
duration: 1.9352666666666667,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment3.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init1.m4f'
|
||||
},
|
||||
number: 3,
|
||||
discontinuity: true
|
||||
},
|
||||
{
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment4.m4f',
|
||||
timeline: 1,
|
||||
duration: 1.9352666666666667,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment4.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init1.m4f'
|
||||
},
|
||||
number: 4
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment5.m4f',
|
||||
timeline: 1,
|
||||
duration: 0.9676333333333333,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment5.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init1.m4f'
|
||||
},
|
||||
number: 5
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment6.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment6.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init2.m4f'
|
||||
},
|
||||
number: 6,
|
||||
discontinuity: true
|
||||
},
|
||||
{
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment7.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment7.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init2.m4f'
|
||||
},
|
||||
number: 7
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment8.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment8.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init2.m4f'
|
||||
},
|
||||
number: 8
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment9.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment9.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init2.m4f'
|
||||
},
|
||||
number: 9
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment10.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment10.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init2.m4f'
|
||||
},
|
||||
number: 10
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment11.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment11.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init2.m4f'
|
||||
},
|
||||
number: 11
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment12.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9686333333333332,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment12.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init2.m4f'
|
||||
},
|
||||
number: 12
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment13.m4f',
|
||||
timeline: 3,
|
||||
duration: 0.9676333333333333,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment13.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init3.m4f'
|
||||
},
|
||||
number: 13,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment14.m4f',
|
||||
timeline: 3,
|
||||
duration: 1.9352666666666667,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment14.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init3.m4f'
|
||||
},
|
||||
number: 14
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment15.m4f',
|
||||
timeline: 3,
|
||||
duration: 0.26693333333333336,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment15.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init3.m4f'
|
||||
},
|
||||
number: 15
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment16.m4f',
|
||||
timeline: 4,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment16.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment$Number$.m4f'
|
||||
},
|
||||
number: 16,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment17.m4f',
|
||||
timeline: 4,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment17.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment$Number$.m4f'
|
||||
},
|
||||
number: 17
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment18.m4f',
|
||||
timeline: 4,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment18.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment$Number$.m4f'
|
||||
},
|
||||
number: 18
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment19.m4f',
|
||||
timeline: 4,
|
||||
duration: 1.9686333333333332,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment19.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment$Number$.m4f'
|
||||
},
|
||||
number: 19
|
||||
}],
|
||||
mediaSequence: 0,
|
||||
contentProtection: {
|
||||
'com.widevine.alpha': {
|
||||
attributes: {
|
||||
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
|
||||
},
|
||||
pssh: new Uint8Array([181, 235, 45])
|
||||
}
|
||||
}
|
||||
}, {
|
||||
attributes: {
|
||||
'NAME': 'default_video900_1_640x360',
|
||||
'AUDIO': 'audio',
|
||||
'SUBTITLES': 'subs',
|
||||
'RESOLUTION': {
|
||||
width: 640,
|
||||
height: 360
|
||||
},
|
||||
'CODECS': 'avc1.4d001e',
|
||||
'BANDWIDTH': 884E3,
|
||||
'PROGRAM-ID': 1
|
||||
},
|
||||
uri: '',
|
||||
endList: false,
|
||||
timeline: 0,
|
||||
resolvedUri: '',
|
||||
targetDuration: 3,
|
||||
segments: [{
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment0.m4f',
|
||||
timeline: 0,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment0.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init0.m4f'
|
||||
},
|
||||
number: 0
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment1.m4f',
|
||||
timeline: 0,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment1.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init0.m4f'
|
||||
},
|
||||
number: 1
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment2.m4f',
|
||||
timeline: 0,
|
||||
duration: 1.9686333333333332,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment2.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init0.m4f'
|
||||
},
|
||||
number: 2
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment3.m4f',
|
||||
timeline: 1,
|
||||
duration: 1.9352666666666667,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment3.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init1.m4f'
|
||||
},
|
||||
number: 3,
|
||||
discontinuity: true
|
||||
},
|
||||
{
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment4.m4f',
|
||||
timeline: 1,
|
||||
duration: 1.9352666666666667,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment4.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init1.m4f'
|
||||
},
|
||||
number: 4
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment5.m4f',
|
||||
timeline: 1,
|
||||
duration: 0.9676333333333333,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment5.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init1.m4f'
|
||||
},
|
||||
number: 5
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment6.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment6.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init2.m4f'
|
||||
},
|
||||
number: 6,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment7.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment7.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init2.m4f'
|
||||
},
|
||||
number: 7
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment8.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment8.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init2.m4f'
|
||||
},
|
||||
number: 8
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment9.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment9.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init2.m4f'
|
||||
},
|
||||
number: 9
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment10.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment10.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init2.m4f'
|
||||
},
|
||||
number: 10
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment11.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment11.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init2.m4f'
|
||||
},
|
||||
number: 11
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment12.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9686333333333332,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment12.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init2.m4f'
|
||||
},
|
||||
number: 12
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment13.m4f',
|
||||
timeline: 3,
|
||||
duration: 0.9676333333333333,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment13.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init3.m4f'
|
||||
},
|
||||
number: 13,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment14.m4f',
|
||||
timeline: 3,
|
||||
duration: 1.9352666666666667,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment14.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init3.m4f'
|
||||
},
|
||||
number: 14
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment15.m4f',
|
||||
timeline: 3,
|
||||
duration: 0.26693333333333336,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment15.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init3.m4f'
|
||||
},
|
||||
number: 15
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment16.m4f',
|
||||
timeline: 4,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment16.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment$Number$.m4f'
|
||||
},
|
||||
number: 16,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment17.m4f',
|
||||
timeline: 4,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment17.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment$Number$.m4f'
|
||||
},
|
||||
number: 17
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment18.m4f',
|
||||
timeline: 4,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment18.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment$Number$.m4f'
|
||||
},
|
||||
number: 18
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment19.m4f',
|
||||
timeline: 4,
|
||||
duration: 1.9686333333333332,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment19.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment$Number$.m4f'
|
||||
},
|
||||
number: 19
|
||||
}],
|
||||
mediaSequence: 0,
|
||||
contentProtection: {
|
||||
'com.widevine.alpha': {
|
||||
attributes: {
|
||||
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
|
||||
},
|
||||
pssh: new Uint8Array([181, 235, 45])
|
||||
}
|
||||
}
|
||||
}],
|
||||
suggestedPresentationDelay: 18
|
||||
};
|
||||
143
build/javascript/node_modules/mpd-parser/test/manifests/multiperiod-dynamic.mpd
generated
vendored
143
build/javascript/node_modules/mpd-parser/test/manifests/multiperiod-dynamic.mpd
generated
vendored
@@ -1,143 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-live:2011" type="dynamic" mediaPresentationDuration="PT36.269S" minBufferTime="PT2.000S" suggestedPresentationDelay="PT18S">
|
||||
<Period id="0" duration="PT5.972633333S">
|
||||
<AdaptationSet mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1" lang="en">
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate initialization="https://example.com/$RepresentationID$/init0.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="0" timescale="44100">
|
||||
<SegmentTimeline>
|
||||
<S d="88064" r="2"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation audioSamplingRate="44100" bandwidth="123000" codecs="mp4a.40.2" id="default_audio128_2"></Representation>
|
||||
<Representation audioSamplingRate="44100" bandwidth="93000" codecs="mp4a.40.2" id="default_audio96_2"></Representation>
|
||||
</AdaptationSet>
|
||||
<AdaptationSet mimeType="video/mp4" scanType="progressive" segmentAlignment="true" startWithSAP="1">
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate initialization="https://example.com/$RepresentationID$/init0.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="0" timescale="30000">
|
||||
<SegmentTimeline>
|
||||
<S d="60060" r="1"></S>
|
||||
<S d="59059"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation bandwidth="2008000" codecs="avc1.4d001f" frameRate="2997/100" height="720" id="default_video2000_0_1280x720" width="1280"></Representation>
|
||||
<Representation bandwidth="1195000" codecs="avc1.4d001f" frameRate="2997/100" height="540" id="default_video1200_1_960x540" width="960"></Representation>
|
||||
<Representation bandwidth="884000" codecs="avc1.4d001e" frameRate="2997/100" height="360" id="default_video900_1_640x360" width="640"></Representation>
|
||||
</AdaptationSet>
|
||||
</Period>
|
||||
<Period id="1" duration="PT4.838166665S">
|
||||
<AdaptationSet mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1" lang="en">
|
||||
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="aaa"/>
|
||||
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||
<cenc:pssh>test</cenc:pssh>
|
||||
</ContentProtection>
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate initialization="https://example.com/$RepresentationID$/init1.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="3" timescale="44100">
|
||||
<SegmentTimeline>
|
||||
<S d="88064" r="1"></S>
|
||||
<S d="37888"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation audioSamplingRate="44100" bandwidth="123000" codecs="mp4a.40.2" id="default_audio128_2"></Representation>
|
||||
<Representation audioSamplingRate="44100" bandwidth="93000" codecs="mp4a.40.2" id="default_audio96_2"></Representation>
|
||||
</AdaptationSet>
|
||||
<AdaptationSet mimeType="video/mp4" scanType="progressive" segmentAlignment="true" startWithSAP="1">
|
||||
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="aaa"/>
|
||||
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||
<cenc:pssh>test</cenc:pssh>
|
||||
</ContentProtection>
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate initialization="https://example.com/$RepresentationID$/init1.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="3" timescale="30000">
|
||||
<SegmentTimeline>
|
||||
<S d="58058" r="1"></S>
|
||||
<S d="29029"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation bandwidth="2008000" codecs="avc1.4d001f" frameRate="2997/100" height="720" id="default_video2000_0_1280x720" width="1280"></Representation>
|
||||
<Representation bandwidth="1195000" codecs="avc1.4d001f" frameRate="2997/100" height="540" id="default_video1200_1_960x540" width="960"></Representation>
|
||||
<Representation bandwidth="884000" codecs="avc1.4d001e" frameRate="2997/100" height="360" id="default_video900_1_640x360" width="640"></Representation>
|
||||
</AdaptationSet>
|
||||
</Period>
|
||||
<Period id="2" duration="PT13.980633333S">
|
||||
<AdaptationSet mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1" lang="en">
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate initialization="https://example.com/$RepresentationID$/init2.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="6" timescale="44100">
|
||||
<SegmentTimeline>
|
||||
<S d="88064" r="6"></S>
|
||||
<S d="1024"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation audioSamplingRate="44100" bandwidth="123000" codecs="mp4a.40.2" id="default_audio128_2"></Representation>
|
||||
<Representation audioSamplingRate="44100" bandwidth="93000" codecs="mp4a.40.2" id="default_audio96_2"></Representation>
|
||||
</AdaptationSet>
|
||||
<AdaptationSet mimeType="video/mp4" scanType="progressive" segmentAlignment="true" startWithSAP="1">
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate initialization="https://example.com/$RepresentationID$/init2.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="6" timescale="30000">
|
||||
<SegmentTimeline>
|
||||
<S d="60060" r="5"></S>
|
||||
<S d="59059"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation bandwidth="2008000" codecs="avc1.4d001f" frameRate="2997/100" height="720" id="default_video2000_0_1280x720" width="1280"></Representation>
|
||||
<Representation bandwidth="1195000" codecs="avc1.4d001f" frameRate="2997/100" height="540" id="default_video1200_1_960x540" width="960"></Representation>
|
||||
<Representation bandwidth="884000" codecs="avc1.4d001e" frameRate="2997/100" height="360" id="default_video900_1_640x360" width="640"></Representation>
|
||||
</AdaptationSet>
|
||||
</Period>
|
||||
<Period id="3" duration="PT3.157913831S">
|
||||
<AdaptationSet mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1" lang="en">
|
||||
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="aaa"/>
|
||||
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||
<cenc:pssh>test</cenc:pssh>
|
||||
</ContentProtection>
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate presentationTimeOffset="214016" initialization="https://example.com/$RepresentationID$/init3.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="14" timescale="44100">
|
||||
<SegmentTimeline>
|
||||
<S d="51200"></S>
|
||||
<S d="88064"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation audioSamplingRate="44100" bandwidth="123000" codecs="mp4a.40.2" id="default_audio128_2"></Representation>
|
||||
<Representation audioSamplingRate="44100" bandwidth="93000" codecs="mp4a.40.2" id="default_audio96_2"></Representation>
|
||||
</AdaptationSet>
|
||||
<AdaptationSet mimeType="video/mp4" scanType="progressive" segmentAlignment="true" startWithSAP="1">
|
||||
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="aaa"/>
|
||||
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||
<cenc:pssh>test</cenc:pssh>
|
||||
</ContentProtection>
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate presentationTimeOffset="145145" initialization="https://example.com/$RepresentationID$/init3.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="13" timescale="30000">
|
||||
<SegmentTimeline>
|
||||
<S d="29029"></S>
|
||||
<S d="58058"></S>
|
||||
<S d="8008"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation bandwidth="2008000" codecs="avc1.4d001f" frameRate="2997/100" height="720" id="default_video2000_0_1280x720" width="1280"></Representation>
|
||||
<Representation bandwidth="1195000" codecs="avc1.4d001f" frameRate="2997/100" height="540" id="default_video1200_1_960x540" width="960"></Representation>
|
||||
<Representation bandwidth="884000" codecs="avc1.4d001e" frameRate="2997/100" height="360" id="default_video900_1_640x360" width="640"></Representation>
|
||||
</AdaptationSet>
|
||||
</Period>
|
||||
<Period id="4" duration="PT7.987664396S">
|
||||
<AdaptationSet mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1" lang="en">
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate initialization="https://example.com/$RepresentationID$/segment$Number$.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="16" timescale="44100">
|
||||
<SegmentTimeline>
|
||||
<S d="88064" r="3"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation audioSamplingRate="44100" bandwidth="123000" codecs="mp4a.40.2" id="default_audio128_2"></Representation>
|
||||
<Representation audioSamplingRate="44100" bandwidth="93000" codecs="mp4a.40.2" id="default_audio96_2"></Representation>
|
||||
</AdaptationSet>
|
||||
<AdaptationSet mimeType="video/mp4" scanType="progressive" segmentAlignment="true" startWithSAP="1">
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate initialization="https://example.com/$RepresentationID$/segment$Number$.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="16" timescale="30000">
|
||||
<SegmentTimeline>
|
||||
<S d="60060" r="2"></S>
|
||||
<S d="59059"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation bandwidth="2008000" codecs="avc1.4d001f" frameRate="2997/100" height="720" id="default_video2000_0_1280x720" width="1280"></Representation>
|
||||
<Representation bandwidth="1195000" codecs="avc1.4d001f" frameRate="2997/100" height="540" id="default_video1200_1_960x540" width="960"></Representation>
|
||||
<Representation bandwidth="884000" codecs="avc1.4d001e" frameRate="2997/100" height="360" id="default_video900_1_640x360" width="640"></Representation>
|
||||
</AdaptationSet>
|
||||
</Period>
|
||||
</MPD>
|
||||
951
build/javascript/node_modules/mpd-parser/test/manifests/multiperiod.js
generated
vendored
951
build/javascript/node_modules/mpd-parser/test/manifests/multiperiod.js
generated
vendored
@@ -1,951 +0,0 @@
|
||||
export const parsedManifest = {
|
||||
allowCache: true,
|
||||
discontinuityStarts: [],
|
||||
segments: [],
|
||||
endList: true,
|
||||
mediaGroups: {
|
||||
'AUDIO': {
|
||||
audio: {
|
||||
'en (main)': {
|
||||
language: 'en',
|
||||
autoselect: true,
|
||||
default: true,
|
||||
playlists: [{
|
||||
attributes: {
|
||||
'NAME': 'default_audio128_2',
|
||||
'BANDWIDTH': 123000,
|
||||
'CODECS': 'mp4a.40.2',
|
||||
'PROGRAM-ID': 1
|
||||
},
|
||||
uri: '',
|
||||
endList: true,
|
||||
timeline: 0,
|
||||
resolvedUri: '',
|
||||
targetDuration: 2,
|
||||
segments: [{
|
||||
uri: 'https://example.com/default_audio128_2/segment0.m4f',
|
||||
timeline: 0,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment0.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init0.m4f'
|
||||
},
|
||||
number: 0
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment1.m4f',
|
||||
timeline: 0,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment1.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init0.m4f'
|
||||
},
|
||||
number: 1
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment2.m4f',
|
||||
timeline: 0,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment2.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init0.m4f'
|
||||
},
|
||||
number: 2
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment3.m4f',
|
||||
timeline: 1,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment3.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init1.m4f'
|
||||
},
|
||||
number: 3,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment4.m4f',
|
||||
timeline: 1,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment4.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init1.m4f'
|
||||
},
|
||||
number: 4
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment5.m4f',
|
||||
timeline: 1,
|
||||
duration: 0.8591383219954648,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment5.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init1.m4f'
|
||||
},
|
||||
number: 5
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment6.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment6.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init2.m4f'
|
||||
},
|
||||
number: 6,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment7.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment7.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init2.m4f'
|
||||
},
|
||||
number: 7
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment8.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment8.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init2.m4f'
|
||||
},
|
||||
number: 8
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment9.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment9.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init2.m4f'
|
||||
},
|
||||
number: 9
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment10.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment10.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init2.m4f'
|
||||
},
|
||||
number: 10
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment11.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment11.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init2.m4f'
|
||||
},
|
||||
number: 11
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment12.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment12.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init2.m4f'
|
||||
},
|
||||
number: 12
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment13.m4f',
|
||||
timeline: 2,
|
||||
duration: 0.023219954648526078,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment13.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init2.m4f'
|
||||
},
|
||||
number: 13
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment14.m4f',
|
||||
timeline: 3,
|
||||
duration: 1.1609977324263039,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment14.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init3.m4f'
|
||||
},
|
||||
number: 14,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment15.m4f',
|
||||
timeline: 3,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment15.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/init3.m4f'
|
||||
},
|
||||
number: 15
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment16.m4f',
|
||||
timeline: 4,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment16.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment$Number$.m4f'
|
||||
},
|
||||
number: 16,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment17.m4f',
|
||||
timeline: 4,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment17.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment$Number$.m4f'
|
||||
},
|
||||
number: 17
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment18.m4f',
|
||||
timeline: 4,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment18.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment$Number$.m4f'
|
||||
},
|
||||
number: 18
|
||||
}, {
|
||||
uri: 'https://example.com/default_audio128_2/segment19.m4f',
|
||||
timeline: 4,
|
||||
duration: 1.9969160997732427,
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment19.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_audio128_2/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_audio128_2/segment$Number$.m4f'
|
||||
},
|
||||
number: 19
|
||||
}],
|
||||
mediaSequence: 0,
|
||||
contentProtection: {
|
||||
'com.widevine.alpha': {
|
||||
attributes: {
|
||||
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
|
||||
},
|
||||
pssh: new Uint8Array([181, 235, 45])
|
||||
}
|
||||
}
|
||||
}],
|
||||
uri: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
'VIDEO': {},
|
||||
'CLOSED-CAPTIONS': {},
|
||||
'SUBTITLES': {}
|
||||
},
|
||||
uri: '',
|
||||
duration: 36.269,
|
||||
playlists: [{
|
||||
attributes: {
|
||||
'NAME': 'default_video2000_0_1280x720',
|
||||
'AUDIO': 'audio',
|
||||
'SUBTITLES': 'subs',
|
||||
'RESOLUTION': {
|
||||
width: 1280,
|
||||
height: 720
|
||||
},
|
||||
'CODECS': 'avc1.4d001f',
|
||||
'BANDWIDTH': 2008E3,
|
||||
'PROGRAM-ID': 1
|
||||
},
|
||||
uri: '',
|
||||
endList: true,
|
||||
timeline: 0,
|
||||
resolvedUri: '',
|
||||
targetDuration: 3,
|
||||
segments: [{
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment0.m4f',
|
||||
timeline: 0,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment0.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init0.m4f'
|
||||
},
|
||||
number: 0
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment1.m4f',
|
||||
timeline: 0,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment1.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init0.m4f'
|
||||
},
|
||||
number: 1
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment2.m4f',
|
||||
timeline: 0,
|
||||
duration: 1.9686333333333332,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment2.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init0.m4f'
|
||||
},
|
||||
number: 2
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment3.m4f',
|
||||
timeline: 1,
|
||||
duration: 1.9352666666666667,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment3.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init1.m4f'
|
||||
},
|
||||
number: 3,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment4.m4f',
|
||||
timeline: 1,
|
||||
duration: 1.9352666666666667,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment4.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init1.m4f'
|
||||
},
|
||||
number: 4
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment5.m4f',
|
||||
timeline: 1,
|
||||
duration: 0.9676333333333333,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment5.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init1.m4f'
|
||||
},
|
||||
number: 5
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment6.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment6.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init2.m4f'
|
||||
},
|
||||
number: 6,
|
||||
discontinuity: true
|
||||
},
|
||||
{
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment7.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment7.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init2.m4f'
|
||||
},
|
||||
number: 7
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment8.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment8.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init2.m4f'
|
||||
},
|
||||
number: 8
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment9.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment9.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init2.m4f'
|
||||
},
|
||||
number: 9
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment10.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment10.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init2.m4f'
|
||||
},
|
||||
number: 10
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment11.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment11.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init2.m4f'
|
||||
},
|
||||
number: 11
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment12.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9686333333333332,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment12.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init2.m4f'
|
||||
},
|
||||
number: 12
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment13.m4f',
|
||||
timeline: 3,
|
||||
duration: 0.9676333333333333,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment13.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init3.m4f'
|
||||
},
|
||||
number: 13,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment14.m4f',
|
||||
timeline: 3,
|
||||
duration: 1.9352666666666667,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment14.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init3.m4f'
|
||||
},
|
||||
number: 14
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment15.m4f',
|
||||
timeline: 3,
|
||||
duration: 0.26693333333333336,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment15.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/init3.m4f'
|
||||
},
|
||||
number: 15
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment16.m4f',
|
||||
timeline: 4,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment16.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment$Number$.m4f'
|
||||
},
|
||||
number: 16,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment17.m4f',
|
||||
timeline: 4,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment17.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment$Number$.m4f'
|
||||
},
|
||||
number: 17
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment18.m4f',
|
||||
timeline: 4,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment18.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment$Number$.m4f'
|
||||
},
|
||||
number: 18
|
||||
}, {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment19.m4f',
|
||||
timeline: 4,
|
||||
duration: 1.9686333333333332,
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment19.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video2000_0_1280x720/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video2000_0_1280x720/segment$Number$.m4f'
|
||||
},
|
||||
number: 19
|
||||
}],
|
||||
mediaSequence: 0,
|
||||
contentProtection: {
|
||||
'com.widevine.alpha': {
|
||||
attributes: {
|
||||
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
|
||||
},
|
||||
pssh: new Uint8Array([181, 235, 45])
|
||||
}
|
||||
}
|
||||
}, {
|
||||
attributes: {
|
||||
'NAME': 'default_video1200_1_960x540',
|
||||
'AUDIO': 'audio',
|
||||
'SUBTITLES': 'subs',
|
||||
'RESOLUTION': {
|
||||
width: 960,
|
||||
height: 540
|
||||
},
|
||||
'CODECS': 'avc1.4d001f',
|
||||
'BANDWIDTH': 1195E3,
|
||||
'PROGRAM-ID': 1
|
||||
},
|
||||
uri: '',
|
||||
endList: true,
|
||||
timeline: 0,
|
||||
resolvedUri: '',
|
||||
targetDuration: 3,
|
||||
segments: [{
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment0.m4f',
|
||||
timeline: 0,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment0.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init0.m4f'
|
||||
},
|
||||
number: 0
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment1.m4f',
|
||||
timeline: 0,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment1.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init0.m4f'
|
||||
},
|
||||
number: 1
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment2.m4f',
|
||||
timeline: 0,
|
||||
duration: 1.9686333333333332,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment2.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init0.m4f'
|
||||
},
|
||||
number: 2
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment3.m4f',
|
||||
timeline: 1,
|
||||
duration: 1.9352666666666667,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment3.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init1.m4f'
|
||||
},
|
||||
number: 3,
|
||||
discontinuity: true
|
||||
},
|
||||
{
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment4.m4f',
|
||||
timeline: 1,
|
||||
duration: 1.9352666666666667,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment4.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init1.m4f'
|
||||
},
|
||||
number: 4
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment5.m4f',
|
||||
timeline: 1,
|
||||
duration: 0.9676333333333333,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment5.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init1.m4f'
|
||||
},
|
||||
number: 5
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment6.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment6.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init2.m4f'
|
||||
},
|
||||
number: 6,
|
||||
discontinuity: true
|
||||
},
|
||||
{
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment7.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment7.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init2.m4f'
|
||||
},
|
||||
number: 7
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment8.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment8.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init2.m4f'
|
||||
},
|
||||
number: 8
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment9.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment9.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init2.m4f'
|
||||
},
|
||||
number: 9
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment10.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment10.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init2.m4f'
|
||||
},
|
||||
number: 10
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment11.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment11.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init2.m4f'
|
||||
},
|
||||
number: 11
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment12.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9686333333333332,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment12.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init2.m4f'
|
||||
},
|
||||
number: 12
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment13.m4f',
|
||||
timeline: 3,
|
||||
duration: 0.9676333333333333,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment13.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init3.m4f'
|
||||
},
|
||||
number: 13,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment14.m4f',
|
||||
timeline: 3,
|
||||
duration: 1.9352666666666667,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment14.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init3.m4f'
|
||||
},
|
||||
number: 14
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment15.m4f',
|
||||
timeline: 3,
|
||||
duration: 0.26693333333333336,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment15.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/init3.m4f'
|
||||
},
|
||||
number: 15
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment16.m4f',
|
||||
timeline: 4,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment16.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment$Number$.m4f'
|
||||
},
|
||||
number: 16,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment17.m4f',
|
||||
timeline: 4,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment17.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment$Number$.m4f'
|
||||
},
|
||||
number: 17
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment18.m4f',
|
||||
timeline: 4,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment18.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment$Number$.m4f'
|
||||
},
|
||||
number: 18
|
||||
}, {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment19.m4f',
|
||||
timeline: 4,
|
||||
duration: 1.9686333333333332,
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment19.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video1200_1_960x540/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video1200_1_960x540/segment$Number$.m4f'
|
||||
},
|
||||
number: 19
|
||||
}],
|
||||
mediaSequence: 0,
|
||||
contentProtection: {
|
||||
'com.widevine.alpha': {
|
||||
attributes: {
|
||||
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
|
||||
},
|
||||
pssh: new Uint8Array([181, 235, 45])
|
||||
}
|
||||
}
|
||||
}, {
|
||||
attributes: {
|
||||
'NAME': 'default_video900_1_640x360',
|
||||
'AUDIO': 'audio',
|
||||
'SUBTITLES': 'subs',
|
||||
'RESOLUTION': {
|
||||
width: 640,
|
||||
height: 360
|
||||
},
|
||||
'CODECS': 'avc1.4d001e',
|
||||
'BANDWIDTH': 884E3,
|
||||
'PROGRAM-ID': 1
|
||||
},
|
||||
uri: '',
|
||||
endList: true,
|
||||
timeline: 0,
|
||||
resolvedUri: '',
|
||||
targetDuration: 3,
|
||||
segments: [{
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment0.m4f',
|
||||
timeline: 0,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment0.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init0.m4f'
|
||||
},
|
||||
number: 0
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment1.m4f',
|
||||
timeline: 0,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment1.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init0.m4f'
|
||||
},
|
||||
number: 1
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment2.m4f',
|
||||
timeline: 0,
|
||||
duration: 1.9686333333333332,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment2.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init0.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init0.m4f'
|
||||
},
|
||||
number: 2
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment3.m4f',
|
||||
timeline: 1,
|
||||
duration: 1.9352666666666667,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment3.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init1.m4f'
|
||||
},
|
||||
number: 3,
|
||||
discontinuity: true
|
||||
},
|
||||
{
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment4.m4f',
|
||||
timeline: 1,
|
||||
duration: 1.9352666666666667,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment4.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init1.m4f'
|
||||
},
|
||||
number: 4
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment5.m4f',
|
||||
timeline: 1,
|
||||
duration: 0.9676333333333333,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment5.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init1.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init1.m4f'
|
||||
},
|
||||
number: 5
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment6.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment6.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init2.m4f'
|
||||
},
|
||||
number: 6,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment7.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment7.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init2.m4f'
|
||||
},
|
||||
number: 7
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment8.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment8.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init2.m4f'
|
||||
},
|
||||
number: 8
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment9.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment9.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init2.m4f'
|
||||
},
|
||||
number: 9
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment10.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment10.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init2.m4f'
|
||||
},
|
||||
number: 10
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment11.m4f',
|
||||
timeline: 2,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment11.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init2.m4f'
|
||||
},
|
||||
number: 11
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment12.m4f',
|
||||
timeline: 2,
|
||||
duration: 1.9686333333333332,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment12.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init2.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init2.m4f'
|
||||
},
|
||||
number: 12
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment13.m4f',
|
||||
timeline: 3,
|
||||
duration: 0.9676333333333333,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment13.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init3.m4f'
|
||||
},
|
||||
number: 13,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment14.m4f',
|
||||
timeline: 3,
|
||||
duration: 1.9352666666666667,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment14.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init3.m4f'
|
||||
},
|
||||
number: 14
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment15.m4f',
|
||||
timeline: 3,
|
||||
duration: 0.26693333333333336,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment15.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/init3.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/init3.m4f'
|
||||
},
|
||||
number: 15
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment16.m4f',
|
||||
timeline: 4,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment16.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment$Number$.m4f'
|
||||
},
|
||||
number: 16,
|
||||
discontinuity: true
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment17.m4f',
|
||||
timeline: 4,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment17.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment$Number$.m4f'
|
||||
},
|
||||
number: 17
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment18.m4f',
|
||||
timeline: 4,
|
||||
duration: 2.002,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment18.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment$Number$.m4f'
|
||||
},
|
||||
number: 18
|
||||
}, {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment19.m4f',
|
||||
timeline: 4,
|
||||
duration: 1.9686333333333332,
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment19.m4f',
|
||||
map: {
|
||||
uri: 'https://example.com/default_video900_1_640x360/segment$Number$.m4f',
|
||||
resolvedUri: 'https://example.com/default_video900_1_640x360/segment$Number$.m4f'
|
||||
},
|
||||
number: 19
|
||||
}],
|
||||
mediaSequence: 0,
|
||||
contentProtection: {
|
||||
'com.widevine.alpha': {
|
||||
attributes: {
|
||||
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
|
||||
},
|
||||
pssh: new Uint8Array([181, 235, 45])
|
||||
}
|
||||
}
|
||||
}]
|
||||
};
|
||||
143
build/javascript/node_modules/mpd-parser/test/manifests/multiperiod.mpd
generated
vendored
143
build/javascript/node_modules/mpd-parser/test/manifests/multiperiod.mpd
generated
vendored
@@ -1,143 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-live:2011" type="static" mediaPresentationDuration="PT36.269S" minBufferTime="PT2.000S">
|
||||
<Period id="0" duration="PT5.972633333S">
|
||||
<AdaptationSet mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1" lang="en">
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate initialization="https://example.com/$RepresentationID$/init0.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="0" timescale="44100">
|
||||
<SegmentTimeline>
|
||||
<S d="88064" r="2"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation audioSamplingRate="44100" bandwidth="123000" codecs="mp4a.40.2" id="default_audio128_2"></Representation>
|
||||
<Representation audioSamplingRate="44100" bandwidth="93000" codecs="mp4a.40.2" id="default_audio96_2"></Representation>
|
||||
</AdaptationSet>
|
||||
<AdaptationSet mimeType="video/mp4" scanType="progressive" segmentAlignment="true" startWithSAP="1">
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate initialization="https://example.com/$RepresentationID$/init0.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="0" timescale="30000">
|
||||
<SegmentTimeline>
|
||||
<S d="60060" r="1"></S>
|
||||
<S d="59059"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation bandwidth="2008000" codecs="avc1.4d001f" frameRate="2997/100" height="720" id="default_video2000_0_1280x720" width="1280"></Representation>
|
||||
<Representation bandwidth="1195000" codecs="avc1.4d001f" frameRate="2997/100" height="540" id="default_video1200_1_960x540" width="960"></Representation>
|
||||
<Representation bandwidth="884000" codecs="avc1.4d001e" frameRate="2997/100" height="360" id="default_video900_1_640x360" width="640"></Representation>
|
||||
</AdaptationSet>
|
||||
</Period>
|
||||
<Period id="1" duration="PT4.838166665S">
|
||||
<AdaptationSet mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1" lang="en">
|
||||
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="aaa"/>
|
||||
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||
<cenc:pssh>test</cenc:pssh>
|
||||
</ContentProtection>
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate initialization="https://example.com/$RepresentationID$/init1.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="3" timescale="44100">
|
||||
<SegmentTimeline>
|
||||
<S d="88064" r="1"></S>
|
||||
<S d="37888"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation audioSamplingRate="44100" bandwidth="123000" codecs="mp4a.40.2" id="default_audio128_2"></Representation>
|
||||
<Representation audioSamplingRate="44100" bandwidth="93000" codecs="mp4a.40.2" id="default_audio96_2"></Representation>
|
||||
</AdaptationSet>
|
||||
<AdaptationSet mimeType="video/mp4" scanType="progressive" segmentAlignment="true" startWithSAP="1">
|
||||
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="aaa"/>
|
||||
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||
<cenc:pssh>test</cenc:pssh>
|
||||
</ContentProtection>
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate initialization="https://example.com/$RepresentationID$/init1.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="3" timescale="30000">
|
||||
<SegmentTimeline>
|
||||
<S d="58058" r="1"></S>
|
||||
<S d="29029"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation bandwidth="2008000" codecs="avc1.4d001f" frameRate="2997/100" height="720" id="default_video2000_0_1280x720" width="1280"></Representation>
|
||||
<Representation bandwidth="1195000" codecs="avc1.4d001f" frameRate="2997/100" height="540" id="default_video1200_1_960x540" width="960"></Representation>
|
||||
<Representation bandwidth="884000" codecs="avc1.4d001e" frameRate="2997/100" height="360" id="default_video900_1_640x360" width="640"></Representation>
|
||||
</AdaptationSet>
|
||||
</Period>
|
||||
<Period id="2" duration="PT13.980633333S">
|
||||
<AdaptationSet mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1" lang="en">
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate initialization="https://example.com/$RepresentationID$/init2.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="6" timescale="44100">
|
||||
<SegmentTimeline>
|
||||
<S d="88064" r="6"></S>
|
||||
<S d="1024"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation audioSamplingRate="44100" bandwidth="123000" codecs="mp4a.40.2" id="default_audio128_2"></Representation>
|
||||
<Representation audioSamplingRate="44100" bandwidth="93000" codecs="mp4a.40.2" id="default_audio96_2"></Representation>
|
||||
</AdaptationSet>
|
||||
<AdaptationSet mimeType="video/mp4" scanType="progressive" segmentAlignment="true" startWithSAP="1">
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate initialization="https://example.com/$RepresentationID$/init2.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="6" timescale="30000">
|
||||
<SegmentTimeline>
|
||||
<S d="60060" r="5"></S>
|
||||
<S d="59059"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation bandwidth="2008000" codecs="avc1.4d001f" frameRate="2997/100" height="720" id="default_video2000_0_1280x720" width="1280"></Representation>
|
||||
<Representation bandwidth="1195000" codecs="avc1.4d001f" frameRate="2997/100" height="540" id="default_video1200_1_960x540" width="960"></Representation>
|
||||
<Representation bandwidth="884000" codecs="avc1.4d001e" frameRate="2997/100" height="360" id="default_video900_1_640x360" width="640"></Representation>
|
||||
</AdaptationSet>
|
||||
</Period>
|
||||
<Period id="3" duration="PT3.157913831S">
|
||||
<AdaptationSet mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1" lang="en">
|
||||
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="aaa"/>
|
||||
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||
<cenc:pssh>test</cenc:pssh>
|
||||
</ContentProtection>
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate presentationTimeOffset="214016" initialization="https://example.com/$RepresentationID$/init3.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="14" timescale="44100">
|
||||
<SegmentTimeline>
|
||||
<S d="51200"></S>
|
||||
<S d="88064"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation audioSamplingRate="44100" bandwidth="123000" codecs="mp4a.40.2" id="default_audio128_2"></Representation>
|
||||
<Representation audioSamplingRate="44100" bandwidth="93000" codecs="mp4a.40.2" id="default_audio96_2"></Representation>
|
||||
</AdaptationSet>
|
||||
<AdaptationSet mimeType="video/mp4" scanType="progressive" segmentAlignment="true" startWithSAP="1">
|
||||
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="aaa"/>
|
||||
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||
<cenc:pssh>test</cenc:pssh>
|
||||
</ContentProtection>
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate presentationTimeOffset="145145" initialization="https://example.com/$RepresentationID$/init3.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="13" timescale="30000">
|
||||
<SegmentTimeline>
|
||||
<S d="29029"></S>
|
||||
<S d="58058"></S>
|
||||
<S d="8008"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation bandwidth="2008000" codecs="avc1.4d001f" frameRate="2997/100" height="720" id="default_video2000_0_1280x720" width="1280"></Representation>
|
||||
<Representation bandwidth="1195000" codecs="avc1.4d001f" frameRate="2997/100" height="540" id="default_video1200_1_960x540" width="960"></Representation>
|
||||
<Representation bandwidth="884000" codecs="avc1.4d001e" frameRate="2997/100" height="360" id="default_video900_1_640x360" width="640"></Representation>
|
||||
</AdaptationSet>
|
||||
</Period>
|
||||
<Period id="4" duration="PT7.987664396S">
|
||||
<AdaptationSet mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1" lang="en">
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate initialization="https://example.com/$RepresentationID$/segment$Number$.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="16" timescale="44100">
|
||||
<SegmentTimeline>
|
||||
<S d="88064" r="3"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation audioSamplingRate="44100" bandwidth="123000" codecs="mp4a.40.2" id="default_audio128_2"></Representation>
|
||||
<Representation audioSamplingRate="44100" bandwidth="93000" codecs="mp4a.40.2" id="default_audio96_2"></Representation>
|
||||
</AdaptationSet>
|
||||
<AdaptationSet mimeType="video/mp4" scanType="progressive" segmentAlignment="true" startWithSAP="1">
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<SegmentTemplate initialization="https://example.com/$RepresentationID$/segment$Number$.m4f" media="https://example.com/$RepresentationID$/segment$Number$.m4f" startNumber="16" timescale="30000">
|
||||
<SegmentTimeline>
|
||||
<S d="60060" r="2"></S>
|
||||
<S d="59059"></S>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<Representation bandwidth="2008000" codecs="avc1.4d001f" frameRate="2997/100" height="720" id="default_video2000_0_1280x720" width="1280"></Representation>
|
||||
<Representation bandwidth="1195000" codecs="avc1.4d001f" frameRate="2997/100" height="540" id="default_video1200_1_960x540" width="960"></Representation>
|
||||
<Representation bandwidth="884000" codecs="avc1.4d001e" frameRate="2997/100" height="360" id="default_video900_1_640x360" width="640"></Representation>
|
||||
</AdaptationSet>
|
||||
</Period>
|
||||
</MPD>
|
||||
49
build/javascript/node_modules/mpd-parser/test/manifests/segmentBase.js
generated
vendored
49
build/javascript/node_modules/mpd-parser/test/manifests/segmentBase.js
generated
vendored
@@ -1,49 +0,0 @@
|
||||
export const parsedManifest = {
|
||||
allowCache: true,
|
||||
discontinuityStarts: [],
|
||||
duration: 6,
|
||||
endList: true,
|
||||
mediaGroups: {
|
||||
'AUDIO': {},
|
||||
'CLOSED-CAPTIONS': {},
|
||||
'SUBTITLES': {},
|
||||
'VIDEO': {}
|
||||
},
|
||||
playlists: [
|
||||
{
|
||||
attributes: {
|
||||
'AUDIO': 'audio',
|
||||
'BANDWIDTH': 449000,
|
||||
'CODECS': 'avc1.420015',
|
||||
'NAME': '482',
|
||||
'PROGRAM-ID': 1,
|
||||
'RESOLUTION': {
|
||||
height: 270,
|
||||
width: 482
|
||||
},
|
||||
'SUBTITLES': 'subs'
|
||||
},
|
||||
endList: true,
|
||||
resolvedUri: '',
|
||||
targetDuration: 6,
|
||||
mediaSequence: 0,
|
||||
segments: [
|
||||
{
|
||||
duration: 6,
|
||||
timeline: 0,
|
||||
number: 0,
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'https://www.example.com/1080p.ts'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/1080p.ts',
|
||||
uri: 'https://www.example.com/1080p.ts'
|
||||
}
|
||||
],
|
||||
timeline: 0,
|
||||
uri: ''
|
||||
}
|
||||
],
|
||||
segments: [],
|
||||
uri: ''
|
||||
};
|
||||
16
build/javascript/node_modules/mpd-parser/test/manifests/segmentBase.mpd
generated
vendored
16
build/javascript/node_modules/mpd-parser/test/manifests/segmentBase.mpd
generated
vendored
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" profiles="urn:mpeg:dash:profile:isoff-live:2011" type="static" mediaPresentationDuration="PT6S" minBufferTime="PT2.000S">
|
||||
<BaseURL>https://www.example.com/base</BaseURL>
|
||||
<Period>
|
||||
<AdaptationSet mimeType="video/mp4" scanType="progressive" segmentAlignment="true" startWithSAP="1">
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<Representation bandwidth="449000" codecs="avc1.420015" frameRate="2997/125" height="270" id="482" width="482" >
|
||||
<SegmentBase></SegmentBase>
|
||||
</Representation>
|
||||
<BaseURL>1080p.ts</BaseURL>
|
||||
<SegmentBase>
|
||||
<RepresentationIndex sourceURL="1080p.sidx"/>
|
||||
</SegmentBase>
|
||||
</AdaptationSet>
|
||||
</Period>
|
||||
</MPD>
|
||||
236
build/javascript/node_modules/mpd-parser/test/manifests/segmentList.js
generated
vendored
236
build/javascript/node_modules/mpd-parser/test/manifests/segmentList.js
generated
vendored
@@ -1,236 +0,0 @@
|
||||
export const parsedManifest = {
|
||||
allowCache: true,
|
||||
discontinuityStarts: [],
|
||||
duration: 6,
|
||||
endList: true,
|
||||
mediaGroups: {
|
||||
'AUDIO': {},
|
||||
'CLOSED-CAPTIONS': {},
|
||||
'SUBTITLES': {},
|
||||
'VIDEO': {}
|
||||
},
|
||||
playlists: [
|
||||
{
|
||||
attributes: {
|
||||
'AUDIO': 'audio',
|
||||
'BANDWIDTH': 449000,
|
||||
'CODECS': 'avc1.420015',
|
||||
'NAME': '482',
|
||||
'PROGRAM-ID': 1,
|
||||
'RESOLUTION': {
|
||||
height: 270,
|
||||
width: 482
|
||||
},
|
||||
'SUBTITLES': 'subs'
|
||||
},
|
||||
endList: true,
|
||||
mediaSequence: 1,
|
||||
targetDuration: 1,
|
||||
resolvedUri: '',
|
||||
segments: [
|
||||
{
|
||||
duration: 1,
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'https://www.example.com/base'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/low/segment-1.ts',
|
||||
timeline: 0,
|
||||
uri: 'low/segment-1.ts',
|
||||
number: 1
|
||||
},
|
||||
{
|
||||
duration: 1,
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'https://www.example.com/base'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/low/segment-2.ts',
|
||||
timeline: 0,
|
||||
uri: 'low/segment-2.ts',
|
||||
number: 2
|
||||
},
|
||||
{
|
||||
duration: 1,
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'https://www.example.com/base'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/low/segment-3.ts',
|
||||
timeline: 0,
|
||||
uri: 'low/segment-3.ts',
|
||||
number: 3
|
||||
},
|
||||
{
|
||||
duration: 1,
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'https://www.example.com/base'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/low/segment-4.ts',
|
||||
timeline: 0,
|
||||
uri: 'low/segment-4.ts',
|
||||
number: 4
|
||||
},
|
||||
{
|
||||
duration: 1,
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'https://www.example.com/base'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/low/segment-5.ts',
|
||||
timeline: 0,
|
||||
uri: 'low/segment-5.ts',
|
||||
number: 5
|
||||
},
|
||||
{
|
||||
duration: 1,
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'https://www.example.com/base'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/low/segment-6.ts',
|
||||
timeline: 0,
|
||||
uri: 'low/segment-6.ts',
|
||||
number: 6
|
||||
}
|
||||
],
|
||||
timeline: 0,
|
||||
uri: ''
|
||||
},
|
||||
{
|
||||
attributes: {
|
||||
'AUDIO': 'audio',
|
||||
'BANDWIDTH': 3971000,
|
||||
'CODECS': 'avc1.420015',
|
||||
'NAME': '720',
|
||||
'PROGRAM-ID': 1,
|
||||
'RESOLUTION': {
|
||||
height: 404,
|
||||
width: 720
|
||||
},
|
||||
'SUBTITLES': 'subs'
|
||||
},
|
||||
endList: true,
|
||||
resolvedUri: '',
|
||||
mediaSequence: 1,
|
||||
targetDuration: 60,
|
||||
segments: [
|
||||
{
|
||||
duration: 60,
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'https://www.example.com/base'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/high/segment-1.ts',
|
||||
timeline: 0,
|
||||
uri: 'high/segment-1.ts',
|
||||
number: 1
|
||||
},
|
||||
{
|
||||
duration: 60,
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'https://www.example.com/base'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/high/segment-2.ts',
|
||||
timeline: 0,
|
||||
uri: 'high/segment-2.ts',
|
||||
number: 2
|
||||
},
|
||||
{
|
||||
duration: 60,
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'https://www.example.com/base'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/high/segment-3.ts',
|
||||
timeline: 0,
|
||||
uri: 'high/segment-3.ts',
|
||||
number: 3
|
||||
},
|
||||
{
|
||||
duration: 60,
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'https://www.example.com/base'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/high/segment-4.ts',
|
||||
timeline: 0,
|
||||
uri: 'high/segment-4.ts',
|
||||
number: 4
|
||||
},
|
||||
{
|
||||
duration: 60,
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'https://www.example.com/base'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/high/segment-5.ts',
|
||||
timeline: 0,
|
||||
uri: 'high/segment-5.ts',
|
||||
number: 5
|
||||
},
|
||||
{
|
||||
duration: 60,
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'https://www.example.com/base'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/high/segment-6.ts',
|
||||
timeline: 0,
|
||||
uri: 'high/segment-6.ts',
|
||||
number: 6
|
||||
},
|
||||
{
|
||||
duration: 60,
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'https://www.example.com/base'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/high/segment-7.ts',
|
||||
timeline: 0,
|
||||
uri: 'high/segment-7.ts',
|
||||
number: 7
|
||||
},
|
||||
{
|
||||
duration: 60,
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'https://www.example.com/base'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/high/segment-8.ts',
|
||||
timeline: 0,
|
||||
uri: 'high/segment-8.ts',
|
||||
number: 8
|
||||
},
|
||||
{
|
||||
duration: 60,
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'https://www.example.com/base'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/high/segment-9.ts',
|
||||
timeline: 0,
|
||||
uri: 'high/segment-9.ts',
|
||||
number: 9
|
||||
},
|
||||
{
|
||||
duration: 60,
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'https://www.example.com/base'
|
||||
},
|
||||
resolvedUri: 'https://www.example.com/high/segment-10.ts',
|
||||
timeline: 0,
|
||||
uri: 'high/segment-10.ts',
|
||||
number: 10
|
||||
}
|
||||
],
|
||||
timeline: 0,
|
||||
uri: ''
|
||||
}
|
||||
],
|
||||
segments: [],
|
||||
uri: ''
|
||||
};
|
||||
47
build/javascript/node_modules/mpd-parser/test/manifests/segmentList.mpd
generated
vendored
47
build/javascript/node_modules/mpd-parser/test/manifests/segmentList.mpd
generated
vendored
@@ -1,47 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" profiles="urn:mpeg:dash:profile:isoff-live:2011" type="static" mediaPresentationDuration="PT6S" minBufferTime="PT2.000S">
|
||||
<BaseURL>https://www.example.com/base</BaseURL>
|
||||
<Period>
|
||||
<AdaptationSet mimeType="video/mp4" scanType="progressive" segmentAlignment="true" startWithSAP="1">
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<Representation bandwidth="449000" codecs="avc1.420015" frameRate="2997/125" height="270" id="482" width="482" >
|
||||
</Representation>
|
||||
<SegmentList timescale="1000" duration="1000">
|
||||
<RepresentationIndex sourceURL="representation-index-low"/>
|
||||
<SegmentURL media="low/segment-1.ts"/>
|
||||
<SegmentURL media="low/segment-2.ts"/>
|
||||
<SegmentURL media="low/segment-3.ts"/>
|
||||
<SegmentURL media="low/segment-4.ts"/>
|
||||
<SegmentURL media="low/segment-5.ts"/>
|
||||
<SegmentURL media="low/segment-6.ts"/>
|
||||
<SegmentURL media="low/segment-7.ts"/>
|
||||
<SegmentURL media="low/segment-8.ts"/>
|
||||
<SegmentURL media="low/segment-9.ts"/>
|
||||
<SegmentURL media="low/segment-10.ts"/>
|
||||
</SegmentList>
|
||||
</AdaptationSet>
|
||||
|
||||
<AdaptationSet mimeType="video/mp4" scanType="progressive" segmentAlignment="true" startWithSAP="1">
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
|
||||
<Representation bandwidth="3971000" codecs="avc1.420015" frameRate="2997/125" height="404" id="720" width="720" >
|
||||
<SegmentList timescale="90000">
|
||||
<RepresentationIndex sourceURL="representation-index-high"/>
|
||||
<SegmentTimeline>
|
||||
<S t="0" r="9" d="5400000"/>
|
||||
</SegmentTimeline>
|
||||
<SegmentURL media="high/segment-1.ts"/>
|
||||
<SegmentURL media="high/segment-2.ts"/>
|
||||
<SegmentURL media="high/segment-3.ts"/>
|
||||
<SegmentURL media="high/segment-4.ts"/>
|
||||
<SegmentURL media="high/segment-5.ts"/>
|
||||
<SegmentURL media="high/segment-6.ts"/>
|
||||
<SegmentURL media="high/segment-7.ts"/>
|
||||
<SegmentURL media="high/segment-8.ts"/>
|
||||
<SegmentURL media="high/segment-9.ts"/>
|
||||
<SegmentURL media="high/segment-10.ts"/>
|
||||
</SegmentList>
|
||||
</Representation>
|
||||
</AdaptationSet>
|
||||
|
||||
</Period>
|
||||
</MPD>
|
||||
21
build/javascript/node_modules/mpd-parser/test/parseAttributes.test.js
generated
vendored
21
build/javascript/node_modules/mpd-parser/test/parseAttributes.test.js
generated
vendored
@@ -1,21 +0,0 @@
|
||||
import {JSDOM} from 'jsdom';
|
||||
import QUnit from 'qunit';
|
||||
import { parseAttributes } from '../src/parseAttributes';
|
||||
|
||||
const document = new JSDOM().window.document;
|
||||
|
||||
QUnit.module('parseAttributes');
|
||||
|
||||
QUnit.test('simple', function(assert) {
|
||||
const el = document.createElement('el');
|
||||
|
||||
el.setAttribute('foo', 1);
|
||||
|
||||
assert.deepEqual(parseAttributes(el), { foo: '1' });
|
||||
});
|
||||
|
||||
QUnit.test('empty', function(assert) {
|
||||
const el = document.createElement('el');
|
||||
|
||||
assert.deepEqual(parseAttributes(el), {});
|
||||
});
|
||||
201
build/javascript/node_modules/mpd-parser/test/segment/segmentBase.test.js
generated
vendored
201
build/javascript/node_modules/mpd-parser/test/segment/segmentBase.test.js
generated
vendored
@@ -1,201 +0,0 @@
|
||||
import QUnit from 'qunit';
|
||||
import {
|
||||
segmentsFromBase,
|
||||
addSegmentsToPlaylist
|
||||
} from '../../src/segment/segmentBase';
|
||||
import errors from '../../src/errors';
|
||||
|
||||
QUnit.module('segmentBase - segmentsFromBase');
|
||||
|
||||
QUnit.test('sets segment to baseUrl', function(assert) {
|
||||
const inputAttributes = {
|
||||
baseUrl: 'http://www.example.com/i.fmp4',
|
||||
initialization: { sourceURL: 'http://www.example.com/init.fmp4' }
|
||||
};
|
||||
|
||||
assert.deepEqual(segmentsFromBase(inputAttributes), [{
|
||||
map: {
|
||||
resolvedUri: 'http://www.example.com/init.fmp4',
|
||||
uri: 'http://www.example.com/init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://www.example.com/i.fmp4',
|
||||
uri: 'http://www.example.com/i.fmp4',
|
||||
number: 0
|
||||
}]);
|
||||
});
|
||||
|
||||
QUnit.test('sets duration based on sourceDuration', function(assert) {
|
||||
const inputAttributes = {
|
||||
baseUrl: 'http://www.example.com/i.fmp4',
|
||||
initialization: { sourceURL: 'http://www.example.com/init.fmp4' },
|
||||
sourceDuration: 10
|
||||
};
|
||||
|
||||
assert.deepEqual(segmentsFromBase(inputAttributes), [{
|
||||
duration: 10,
|
||||
timeline: 0,
|
||||
map: {
|
||||
resolvedUri: 'http://www.example.com/init.fmp4',
|
||||
uri: 'http://www.example.com/init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://www.example.com/i.fmp4',
|
||||
uri: 'http://www.example.com/i.fmp4',
|
||||
number: 0
|
||||
}]);
|
||||
});
|
||||
|
||||
// sourceDuration comes from mediaPresentationDuration. The DASH spec defines the type of
|
||||
// mediaPresentationDuration as xs:duration, which follows ISO 8601. It does not need to
|
||||
// be adjusted based on timescale.
|
||||
//
|
||||
// References:
|
||||
// https://www.w3.org/TR/xmlschema-2/#duration
|
||||
// https://en.wikipedia.org/wiki/ISO_8601
|
||||
QUnit.test('sets duration based on sourceDuration and not @timescale', function(assert) {
|
||||
const inputAttributes = {
|
||||
baseUrl: 'http://www.example.com/i.fmp4',
|
||||
initialization: { sourceURL: 'http://www.example.com/init.fmp4' },
|
||||
sourceDuration: 10,
|
||||
timescale: 2
|
||||
};
|
||||
|
||||
assert.deepEqual(segmentsFromBase(inputAttributes), [{
|
||||
duration: 10,
|
||||
timeline: 0,
|
||||
map: {
|
||||
resolvedUri: 'http://www.example.com/init.fmp4',
|
||||
uri: 'http://www.example.com/init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://www.example.com/i.fmp4',
|
||||
uri: 'http://www.example.com/i.fmp4',
|
||||
number: 0
|
||||
}]);
|
||||
});
|
||||
|
||||
QUnit.test('sets duration based on @duration', function(assert) {
|
||||
const inputAttributes = {
|
||||
duration: 10,
|
||||
sourceDuration: 20,
|
||||
baseUrl: 'http://www.example.com/i.fmp4',
|
||||
initialization: { sourceURL: 'http://www.example.com/init.fmp4' },
|
||||
periodIndex: 0
|
||||
};
|
||||
|
||||
assert.deepEqual(segmentsFromBase(inputAttributes), [{
|
||||
duration: 10,
|
||||
timeline: 0,
|
||||
map: {
|
||||
resolvedUri: 'http://www.example.com/init.fmp4',
|
||||
uri: 'http://www.example.com/init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://www.example.com/i.fmp4',
|
||||
uri: 'http://www.example.com/i.fmp4',
|
||||
number: 0
|
||||
}]);
|
||||
});
|
||||
|
||||
QUnit.test('sets duration based on @duration and @timescale', function(assert) {
|
||||
const inputAttributes = {
|
||||
duration: 10,
|
||||
sourceDuration: 20,
|
||||
timescale: 5,
|
||||
baseUrl: 'http://www.example.com/i.fmp4',
|
||||
initialization: { sourceURL: 'http://www.example.com/init.fmp4' },
|
||||
periodIndex: 0
|
||||
};
|
||||
|
||||
assert.deepEqual(segmentsFromBase(inputAttributes), [{
|
||||
duration: 2,
|
||||
timeline: 0,
|
||||
map: {
|
||||
resolvedUri: 'http://www.example.com/init.fmp4',
|
||||
uri: 'http://www.example.com/init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://www.example.com/i.fmp4',
|
||||
uri: 'http://www.example.com/i.fmp4',
|
||||
number: 0
|
||||
}]);
|
||||
});
|
||||
|
||||
QUnit.test('translates ranges in <Initialization> node', function(assert) {
|
||||
const inputAttributes = {
|
||||
duration: 10,
|
||||
sourceDuration: 20,
|
||||
timescale: 5,
|
||||
baseUrl: 'http://www.example.com/i.fmp4',
|
||||
initialization: {
|
||||
sourceURL: 'http://www.example.com/init.fmp4',
|
||||
range: '121-125'
|
||||
},
|
||||
periodIndex: 0
|
||||
};
|
||||
|
||||
assert.deepEqual(segmentsFromBase(inputAttributes), [{
|
||||
duration: 2,
|
||||
timeline: 0,
|
||||
map: {
|
||||
resolvedUri: 'http://www.example.com/init.fmp4',
|
||||
uri: 'http://www.example.com/init.fmp4',
|
||||
byterange: {
|
||||
length: 5,
|
||||
offset: 121
|
||||
}
|
||||
},
|
||||
resolvedUri: 'http://www.example.com/i.fmp4',
|
||||
uri: 'http://www.example.com/i.fmp4',
|
||||
number: 0
|
||||
}]);
|
||||
});
|
||||
|
||||
QUnit.test('errors if no baseUrl exists', function(assert) {
|
||||
assert.throws(() => segmentsFromBase({}), new Error(errors.NO_BASE_URL));
|
||||
});
|
||||
|
||||
QUnit.module('segmentBase - addSegmentsToPlaylist');
|
||||
|
||||
QUnit.test('generates playlist from sidx references', function(assert) {
|
||||
const baseUrl = 'http://www.example.com/i.fmp4';
|
||||
const playlist = {
|
||||
sidx: {
|
||||
map: {
|
||||
byterange: {
|
||||
offset: 0,
|
||||
length: 10
|
||||
}
|
||||
},
|
||||
duration: 10,
|
||||
byterange: {
|
||||
offset: 9,
|
||||
length: 11
|
||||
}
|
||||
},
|
||||
segments: []
|
||||
};
|
||||
const sidx = {
|
||||
timescale: 1,
|
||||
firstOffset: 0,
|
||||
references: [{
|
||||
referenceType: 0,
|
||||
referencedSize: 5,
|
||||
subsegmentDuration: 2
|
||||
}]
|
||||
};
|
||||
|
||||
assert.deepEqual(addSegmentsToPlaylist(playlist, sidx, baseUrl).segments, [{
|
||||
map: {
|
||||
byterange: {
|
||||
offset: 0,
|
||||
length: 10
|
||||
}
|
||||
},
|
||||
uri: 'http://www.example.com/i.fmp4',
|
||||
resolvedUri: 'http://www.example.com/i.fmp4',
|
||||
byterange: {
|
||||
offset: 20,
|
||||
length: 5
|
||||
},
|
||||
duration: 2,
|
||||
timeline: 0,
|
||||
number: 0
|
||||
}]);
|
||||
});
|
||||
553
build/javascript/node_modules/mpd-parser/test/segment/segmentList.test.js
generated
vendored
553
build/javascript/node_modules/mpd-parser/test/segment/segmentList.test.js
generated
vendored
@@ -1,553 +0,0 @@
|
||||
import QUnit from 'qunit';
|
||||
import {
|
||||
segmentsFromList
|
||||
} from '../../src/segment/segmentList';
|
||||
import errors from '../../src/errors';
|
||||
|
||||
QUnit.module('segmentList - segmentsFromList');
|
||||
|
||||
QUnit.test('uses segmentTimeline to set segments', function(assert) {
|
||||
const inputAttributes = {
|
||||
segmentUrls: [{
|
||||
media: '1.fmp4'
|
||||
}, {
|
||||
media: '2.fmp4'
|
||||
}, {
|
||||
media: '3.fmp4'
|
||||
}, {
|
||||
media: '4.fmp4'
|
||||
}, {
|
||||
media: '5.fmp4'
|
||||
}],
|
||||
initialization: { sourceURL: 'init.fmp4' },
|
||||
periodIndex: 0,
|
||||
startNumber: 1,
|
||||
baseUrl: 'http://example.com/'
|
||||
};
|
||||
|
||||
const inputTimeline = [{
|
||||
t: 1000,
|
||||
d: 1000,
|
||||
r: 4
|
||||
}];
|
||||
|
||||
assert.deepEqual(segmentsFromList(inputAttributes, inputTimeline), [{
|
||||
duration: 1000,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/1.fmp4',
|
||||
timeline: 0,
|
||||
uri: '1.fmp4',
|
||||
number: 1
|
||||
}, {
|
||||
duration: 1000,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/2.fmp4',
|
||||
timeline: 0,
|
||||
uri: '2.fmp4',
|
||||
number: 2
|
||||
}, {
|
||||
duration: 1000,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/3.fmp4',
|
||||
timeline: 0,
|
||||
uri: '3.fmp4',
|
||||
number: 3
|
||||
}, {
|
||||
duration: 1000,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/4.fmp4',
|
||||
timeline: 0,
|
||||
uri: '4.fmp4',
|
||||
number: 4
|
||||
}, {
|
||||
duration: 1000,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/5.fmp4',
|
||||
timeline: 0,
|
||||
uri: '5.fmp4',
|
||||
number: 5
|
||||
}]);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
'truncates if segmentTimeline does not apply for all segments',
|
||||
function(assert) {
|
||||
const inputAttributes = {
|
||||
segmentUrls: [{
|
||||
media: '1.fmp4'
|
||||
}, {
|
||||
media: '2.fmp4'
|
||||
}, {
|
||||
media: '3.fmp4'
|
||||
}, {
|
||||
media: '4.fmp4'
|
||||
}, {
|
||||
media: '5.fmp4'
|
||||
}],
|
||||
initialization: { sourceURL: 'init.fmp4' },
|
||||
periodIndex: 0,
|
||||
startNumber: 1,
|
||||
baseUrl: 'http://example.com/'
|
||||
};
|
||||
|
||||
const inputTimeline = [{
|
||||
t: 1000,
|
||||
d: 1000,
|
||||
r: 1
|
||||
}];
|
||||
|
||||
assert.deepEqual(segmentsFromList(inputAttributes, inputTimeline), [{
|
||||
duration: 1000,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/1.fmp4',
|
||||
timeline: 0,
|
||||
uri: '1.fmp4',
|
||||
number: 1
|
||||
}, {
|
||||
duration: 1000,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/2.fmp4',
|
||||
timeline: 0,
|
||||
uri: '2.fmp4',
|
||||
number: 2
|
||||
}]);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
'if segment timeline is too long does not add extra blank segments',
|
||||
function(assert) {
|
||||
const inputAttributes = {
|
||||
segmentUrls: [{
|
||||
media: '1.fmp4'
|
||||
}, {
|
||||
media: '2.fmp4'
|
||||
}, {
|
||||
media: '3.fmp4'
|
||||
}, {
|
||||
media: '4.fmp4'
|
||||
}, {
|
||||
media: '5.fmp4'
|
||||
}],
|
||||
initialization: { sourceURL: 'init.fmp4' },
|
||||
periodIndex: 0,
|
||||
startNumber: 1,
|
||||
baseUrl: 'http://example.com/'
|
||||
};
|
||||
|
||||
const inputTimeline = [{
|
||||
t: 1000,
|
||||
d: 1000,
|
||||
r: 10
|
||||
}];
|
||||
|
||||
assert.deepEqual(segmentsFromList(inputAttributes, inputTimeline), [{
|
||||
duration: 1000,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/1.fmp4',
|
||||
timeline: 0,
|
||||
uri: '1.fmp4',
|
||||
number: 1
|
||||
}, {
|
||||
duration: 1000,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/2.fmp4',
|
||||
timeline: 0,
|
||||
uri: '2.fmp4',
|
||||
number: 2
|
||||
}, {
|
||||
duration: 1000,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/3.fmp4',
|
||||
timeline: 0,
|
||||
uri: '3.fmp4',
|
||||
number: 3
|
||||
}, {
|
||||
duration: 1000,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/4.fmp4',
|
||||
timeline: 0,
|
||||
uri: '4.fmp4',
|
||||
number: 4
|
||||
}, {
|
||||
duration: 1000,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/5.fmp4',
|
||||
timeline: 0,
|
||||
uri: '5.fmp4',
|
||||
number: 5
|
||||
}]);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test('uses duration to set segments', function(assert) {
|
||||
const inputAttributes = {
|
||||
segmentUrls: [{
|
||||
media: '1.fmp4'
|
||||
}, {
|
||||
media: '2.fmp4'
|
||||
}, {
|
||||
media: '3.fmp4'
|
||||
}, {
|
||||
media: '4.fmp4'
|
||||
}, {
|
||||
media: '5.fmp4'
|
||||
}],
|
||||
initialization: { sourceURL: 'init.fmp4' },
|
||||
duration: 10,
|
||||
periodIndex: 0,
|
||||
startNumber: 1,
|
||||
sourceDuration: 50,
|
||||
baseUrl: 'http://example.com/'
|
||||
};
|
||||
|
||||
assert.deepEqual(segmentsFromList(inputAttributes), [{
|
||||
duration: 10,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/1.fmp4',
|
||||
timeline: 0,
|
||||
uri: '1.fmp4',
|
||||
number: 1
|
||||
}, {
|
||||
duration: 10,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/2.fmp4',
|
||||
timeline: 0,
|
||||
uri: '2.fmp4',
|
||||
number: 2
|
||||
}, {
|
||||
duration: 10,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/3.fmp4',
|
||||
timeline: 0,
|
||||
uri: '3.fmp4',
|
||||
number: 3
|
||||
}, {
|
||||
duration: 10,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/4.fmp4',
|
||||
timeline: 0,
|
||||
uri: '4.fmp4',
|
||||
number: 4
|
||||
}, {
|
||||
duration: 10,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/5.fmp4',
|
||||
timeline: 0,
|
||||
uri: '5.fmp4',
|
||||
number: 5
|
||||
}]);
|
||||
});
|
||||
|
||||
QUnit.test('uses timescale to set segment duration', function(assert) {
|
||||
const inputAttributes = {
|
||||
segmentUrls: [{
|
||||
media: '1.fmp4'
|
||||
}, {
|
||||
media: '2.fmp4'
|
||||
}, {
|
||||
media: '3.fmp4'
|
||||
}, {
|
||||
media: '4.fmp4'
|
||||
}, {
|
||||
media: '5.fmp4'
|
||||
}],
|
||||
initialization: { sourceURL: 'init.fmp4' },
|
||||
duration: 10,
|
||||
timescale: 2,
|
||||
periodIndex: 0,
|
||||
startNumber: 1,
|
||||
sourceDuration: 25,
|
||||
baseUrl: 'http://example.com/'
|
||||
};
|
||||
|
||||
assert.deepEqual(segmentsFromList(inputAttributes), [{
|
||||
duration: 5,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/1.fmp4',
|
||||
timeline: 0,
|
||||
uri: '1.fmp4',
|
||||
number: 1
|
||||
}, {
|
||||
duration: 5,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/2.fmp4',
|
||||
timeline: 0,
|
||||
uri: '2.fmp4',
|
||||
number: 2
|
||||
}, {
|
||||
duration: 5,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/3.fmp4',
|
||||
timeline: 0,
|
||||
uri: '3.fmp4',
|
||||
number: 3
|
||||
}, {
|
||||
duration: 5,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/4.fmp4',
|
||||
timeline: 0,
|
||||
uri: '4.fmp4',
|
||||
number: 4
|
||||
}, {
|
||||
duration: 5,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/5.fmp4',
|
||||
timeline: 0,
|
||||
uri: '5.fmp4',
|
||||
number: 5
|
||||
}]);
|
||||
});
|
||||
|
||||
QUnit.test('timescale sets duration of last segment correctly', function(assert) {
|
||||
const inputAttributes = {
|
||||
segmentUrls: [{
|
||||
media: '1.fmp4'
|
||||
}, {
|
||||
media: '2.fmp4'
|
||||
}],
|
||||
initialization: { sourceURL: 'init.fmp4' },
|
||||
duration: 10,
|
||||
timescale: 1,
|
||||
periodIndex: 0,
|
||||
startNumber: 1,
|
||||
sourceDuration: 15,
|
||||
baseUrl: 'http://example.com/'
|
||||
};
|
||||
|
||||
assert.deepEqual(segmentsFromList(inputAttributes), [{
|
||||
duration: 10,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/1.fmp4',
|
||||
timeline: 0,
|
||||
uri: '1.fmp4',
|
||||
number: 1
|
||||
}, {
|
||||
duration: 5,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/2.fmp4',
|
||||
timeline: 0,
|
||||
uri: '2.fmp4',
|
||||
number: 2
|
||||
}]);
|
||||
});
|
||||
|
||||
QUnit.test('segmentUrl translates ranges correctly', function(assert) {
|
||||
const inputAttributes = {
|
||||
segmentUrls: [{
|
||||
media: '1.fmp4',
|
||||
mediaRange: '0-200'
|
||||
}, {
|
||||
media: '1.fmp4',
|
||||
mediaRange: '201-400'
|
||||
}],
|
||||
initialization: { sourceURL: 'init.fmp4' },
|
||||
duration: 10,
|
||||
timescale: 1,
|
||||
periodIndex: 0,
|
||||
startNumber: 1,
|
||||
sourceDuration: 20,
|
||||
baseUrl: 'http://example.com/'
|
||||
};
|
||||
|
||||
assert.deepEqual(segmentsFromList(inputAttributes), [{
|
||||
duration: 10,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
byterange: {
|
||||
length: 201,
|
||||
offset: 0
|
||||
},
|
||||
resolvedUri: 'http://example.com/1.fmp4',
|
||||
timeline: 0,
|
||||
uri: '1.fmp4',
|
||||
number: 1
|
||||
}, {
|
||||
duration: 10,
|
||||
byterange: {
|
||||
length: 200,
|
||||
offset: 201
|
||||
},
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
},
|
||||
resolvedUri: 'http://example.com/1.fmp4',
|
||||
timeline: 0,
|
||||
uri: '1.fmp4',
|
||||
number: 2
|
||||
}]);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
'throws error if more than 1 segment and no duration or timeline',
|
||||
function(assert) {
|
||||
const inputAttributes = {
|
||||
segmentUrls: [{
|
||||
media: '1.fmp4'
|
||||
}, {
|
||||
media: '2.fmp4'
|
||||
}],
|
||||
duration: 10,
|
||||
initialization: { sourceURL: 'init.fmp4' },
|
||||
timescale: 1,
|
||||
periodIndex: 0,
|
||||
startNumber: 1,
|
||||
sourceDuration: 20,
|
||||
baseUrl: 'http://example.com/'
|
||||
};
|
||||
|
||||
const inputTimeline = [{
|
||||
t: 1000,
|
||||
d: 1000,
|
||||
r: 4
|
||||
}];
|
||||
|
||||
assert.throws(
|
||||
() => segmentsFromList(inputAttributes, inputTimeline),
|
||||
new Error(errors.SEGMENT_TIME_UNSPECIFIED)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test('throws error if timeline and duration are both defined', function(assert) {
|
||||
const inputAttributes = {
|
||||
segmentUrls: [{
|
||||
media: '1.fmp4'
|
||||
}, {
|
||||
media: '2.fmp4'
|
||||
}],
|
||||
initialization: { sourceURL: 'init.fmp4' },
|
||||
timescale: 1,
|
||||
periodIndex: 0,
|
||||
startNumber: 1,
|
||||
sourceDuration: 20,
|
||||
baseUrl: 'http://example.com/'
|
||||
};
|
||||
|
||||
assert.throws(
|
||||
() => segmentsFromList(inputAttributes),
|
||||
new Error(errors.SEGMENT_TIME_UNSPECIFIED)
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('translates ranges in <Initialization> node', function(assert) {
|
||||
const inputAttributes = {
|
||||
segmentUrls: [{
|
||||
media: '1.fmp4'
|
||||
}, {
|
||||
media: '1.fmp4'
|
||||
}],
|
||||
initialization: { sourceURL: 'init.fmp4', range: '121-125' },
|
||||
duration: 10,
|
||||
timescale: 1,
|
||||
periodIndex: 0,
|
||||
startNumber: 1,
|
||||
sourceDuration: 20,
|
||||
baseUrl: 'http://example.com/'
|
||||
};
|
||||
|
||||
assert.deepEqual(segmentsFromList(inputAttributes), [{
|
||||
duration: 10,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4',
|
||||
byterange: {
|
||||
length: 5,
|
||||
offset: 121
|
||||
}
|
||||
},
|
||||
resolvedUri: 'http://example.com/1.fmp4',
|
||||
timeline: 0,
|
||||
uri: '1.fmp4',
|
||||
number: 1
|
||||
}, {
|
||||
duration: 10,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4',
|
||||
byterange: {
|
||||
length: 5,
|
||||
offset: 121
|
||||
}
|
||||
},
|
||||
resolvedUri: 'http://example.com/1.fmp4',
|
||||
timeline: 0,
|
||||
uri: '1.fmp4',
|
||||
number: 2
|
||||
}]);
|
||||
});
|
||||
1405
build/javascript/node_modules/mpd-parser/test/segment/segmentTemplate.test.js
generated
vendored
1405
build/javascript/node_modules/mpd-parser/test/segment/segmentTemplate.test.js
generated
vendored
File diff suppressed because it is too large
Load Diff
94
build/javascript/node_modules/mpd-parser/test/segment/urlType.test.js
generated
vendored
94
build/javascript/node_modules/mpd-parser/test/segment/urlType.test.js
generated
vendored
@@ -1,94 +0,0 @@
|
||||
import QUnit from 'qunit';
|
||||
import {
|
||||
urlTypeToSegment as urlTypeConverter,
|
||||
byteRangeToString
|
||||
} from '../../src/segment/urlType';
|
||||
|
||||
QUnit.module('urlType - urlTypeConverter');
|
||||
|
||||
QUnit.test('returns correct object if given baseUrl only', function(assert) {
|
||||
assert.deepEqual(urlTypeConverter({ baseUrl: 'http://example.com' }), {
|
||||
resolvedUri: 'http://example.com',
|
||||
uri: ''
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test('returns correct object if given baseUrl and source', function(assert) {
|
||||
assert.deepEqual(urlTypeConverter({
|
||||
baseUrl: 'http://example.com',
|
||||
source: 'init.fmp4'
|
||||
}), {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4'
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test('returns correct object if given baseUrl, source and range', function(assert) {
|
||||
assert.deepEqual(urlTypeConverter({
|
||||
baseUrl: 'http://example.com',
|
||||
source: 'init.fmp4',
|
||||
range: '101-105'
|
||||
}), {
|
||||
resolvedUri: 'http://example.com/init.fmp4',
|
||||
uri: 'init.fmp4',
|
||||
byterange: {
|
||||
offset: 101,
|
||||
length: 5
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test('returns correct object if given baseUrl, source and indexRange', function(assert) {
|
||||
assert.deepEqual(urlTypeConverter({
|
||||
baseUrl: 'http://example.com',
|
||||
source: 'sidx.fmp4',
|
||||
indexRange: '101-105'
|
||||
}), {
|
||||
resolvedUri: 'http://example.com/sidx.fmp4',
|
||||
uri: 'sidx.fmp4',
|
||||
byterange: {
|
||||
offset: 101,
|
||||
length: 5
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test('returns correct object if given baseUrl and range', function(assert) {
|
||||
assert.deepEqual(urlTypeConverter({
|
||||
baseUrl: 'http://example.com',
|
||||
range: '101-105'
|
||||
}), {
|
||||
resolvedUri: 'http://example.com',
|
||||
uri: '',
|
||||
byterange: {
|
||||
offset: 101,
|
||||
length: 5
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test('returns correct object if given baseUrl and indexRange', function(assert) {
|
||||
assert.deepEqual(urlTypeConverter({
|
||||
baseUrl: 'http://example.com',
|
||||
indexRange: '101-105'
|
||||
}), {
|
||||
resolvedUri: 'http://example.com',
|
||||
uri: '',
|
||||
byterange: {
|
||||
offset: 101,
|
||||
length: 5
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.module('urlType - byteRangeToString');
|
||||
|
||||
QUnit.test('returns correct string representing byterange object', function(assert) {
|
||||
assert.strictEqual(
|
||||
byteRangeToString({
|
||||
offset: 0,
|
||||
length: 100
|
||||
}),
|
||||
'0-99'
|
||||
);
|
||||
});
|
||||
21
build/javascript/node_modules/mpd-parser/test/stringToMpdXml.test.js
generated
vendored
21
build/javascript/node_modules/mpd-parser/test/stringToMpdXml.test.js
generated
vendored
@@ -1,21 +0,0 @@
|
||||
import { stringToMpdXml } from '../src/stringToMpdXml';
|
||||
import errors from '../src/errors';
|
||||
import QUnit from 'qunit';
|
||||
|
||||
QUnit.module('stringToMpdXml');
|
||||
|
||||
QUnit.test('simple mpd', function(assert) {
|
||||
assert.deepEqual(stringToMpdXml('<MPD></MPD>').tagName, 'MPD');
|
||||
});
|
||||
|
||||
QUnit.test('invalid xml', function(assert) {
|
||||
assert.throws(() => stringToMpdXml('<test'), new RegExp(errors.DASH_INVALID_XML));
|
||||
});
|
||||
|
||||
QUnit.test('invalid manifest', function(assert) {
|
||||
assert.throws(() => stringToMpdXml('<test>'), new RegExp(errors.DASH_INVALID_XML));
|
||||
});
|
||||
|
||||
QUnit.test('empty manifest', function(assert) {
|
||||
assert.throws(() => stringToMpdXml(''), new RegExp(errors.DASH_EMPTY_MANIFEST));
|
||||
});
|
||||
703
build/javascript/node_modules/mpd-parser/test/toM3u8.test.js
generated
vendored
703
build/javascript/node_modules/mpd-parser/test/toM3u8.test.js
generated
vendored
@@ -1,703 +0,0 @@
|
||||
import { toM3u8 } from '../src/toM3u8';
|
||||
import QUnit from 'qunit';
|
||||
|
||||
QUnit.module('toM3u8');
|
||||
|
||||
QUnit.test('playlists', function(assert) {
|
||||
const input = [{
|
||||
attributes: {
|
||||
id: '1',
|
||||
codecs: 'foo;bar',
|
||||
sourceDuration: 100,
|
||||
duration: 0,
|
||||
bandwidth: 20000,
|
||||
periodIndex: 1,
|
||||
mimeType: 'audio/mp4'
|
||||
},
|
||||
segments: []
|
||||
}, {
|
||||
attributes: {
|
||||
id: '2',
|
||||
codecs: 'foo;bar',
|
||||
sourceDuration: 100,
|
||||
duration: 0,
|
||||
bandwidth: 10000,
|
||||
periodIndex: 1,
|
||||
mimeType: 'audio/mp4'
|
||||
},
|
||||
segments: []
|
||||
}, {
|
||||
attributes: {
|
||||
sourceDuration: 100,
|
||||
id: '1',
|
||||
width: 800,
|
||||
height: 600,
|
||||
codecs: 'foo;bar',
|
||||
duration: 0,
|
||||
bandwidth: 10000,
|
||||
periodIndex: 1,
|
||||
mimeType: 'video/mp4'
|
||||
},
|
||||
segments: []
|
||||
}, {
|
||||
attributes: {
|
||||
sourceDuration: 100,
|
||||
id: '1',
|
||||
bandwidth: 20000,
|
||||
periodIndex: 1,
|
||||
mimeType: 'text/vtt',
|
||||
baseUrl: 'https://www.example.com/vtt'
|
||||
}
|
||||
}, {
|
||||
attributes: {
|
||||
sourceDuration: 100,
|
||||
id: '1',
|
||||
bandwidth: 10000,
|
||||
periodIndex: 1,
|
||||
mimeType: 'text/vtt',
|
||||
baseUrl: 'https://www.example.com/vtt'
|
||||
}
|
||||
}];
|
||||
|
||||
const expected = {
|
||||
allowCache: true,
|
||||
discontinuityStarts: [],
|
||||
duration: 100,
|
||||
endList: true,
|
||||
mediaGroups: {
|
||||
AUDIO: {
|
||||
audio: {
|
||||
main: {
|
||||
autoselect: true,
|
||||
default: true,
|
||||
language: '',
|
||||
playlists: [{
|
||||
attributes: {
|
||||
BANDWIDTH: 20000,
|
||||
CODECS: 'foo;bar',
|
||||
NAME: '1',
|
||||
['PROGRAM-ID']: 1
|
||||
},
|
||||
mediaSequence: 1,
|
||||
endList: true,
|
||||
resolvedUri: '',
|
||||
segments: [],
|
||||
timeline: 1,
|
||||
uri: '',
|
||||
targetDuration: 0
|
||||
}],
|
||||
uri: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
['CLOSED-CAPTIONS']: {},
|
||||
SUBTITLES: {
|
||||
subs: {
|
||||
text: {
|
||||
autoselect: false,
|
||||
default: false,
|
||||
language: 'text',
|
||||
playlists: [{
|
||||
attributes: {
|
||||
BANDWIDTH: 20000,
|
||||
NAME: '1',
|
||||
['PROGRAM-ID']: 1
|
||||
},
|
||||
mediaSequence: 0,
|
||||
targetDuration: 100,
|
||||
endList: true,
|
||||
resolvedUri: 'https://www.example.com/vtt',
|
||||
segments: [{
|
||||
duration: 100,
|
||||
resolvedUri: 'https://www.example.com/vtt',
|
||||
timeline: 1,
|
||||
uri: 'https://www.example.com/vtt',
|
||||
number: 0
|
||||
}],
|
||||
timeline: 1,
|
||||
uri: ''
|
||||
}],
|
||||
uri: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
VIDEO: {}
|
||||
},
|
||||
playlists: [{
|
||||
attributes: {
|
||||
AUDIO: 'audio',
|
||||
SUBTITLES: 'subs',
|
||||
BANDWIDTH: 10000,
|
||||
CODECS: 'foo;bar',
|
||||
NAME: '1',
|
||||
['PROGRAM-ID']: 1,
|
||||
RESOLUTION: {
|
||||
height: 600,
|
||||
width: 800
|
||||
}
|
||||
},
|
||||
endList: true,
|
||||
mediaSequence: 1,
|
||||
targetDuration: 0,
|
||||
resolvedUri: '',
|
||||
segments: [],
|
||||
timeline: 1,
|
||||
uri: ''
|
||||
}],
|
||||
segments: [],
|
||||
uri: ''
|
||||
};
|
||||
|
||||
assert.deepEqual(toM3u8(input), expected);
|
||||
});
|
||||
|
||||
QUnit.test('playlists with segments', function(assert) {
|
||||
const input = [{
|
||||
attributes: {
|
||||
id: '1',
|
||||
codecs: 'foo;bar',
|
||||
duration: 2,
|
||||
sourceDuration: 100,
|
||||
bandwidth: 20000,
|
||||
periodIndex: 1,
|
||||
mimeType: 'audio/mp4'
|
||||
},
|
||||
segments: [{
|
||||
uri: '',
|
||||
timeline: 1,
|
||||
duration: 2,
|
||||
resolvedUri: '',
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: ''
|
||||
},
|
||||
number: 1
|
||||
}, {
|
||||
uri: '',
|
||||
timeline: 1,
|
||||
duration: 2,
|
||||
resolvedUri: '',
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: ''
|
||||
},
|
||||
number: 2
|
||||
}]
|
||||
}, {
|
||||
attributes: {
|
||||
id: '2',
|
||||
codecs: 'foo;bar',
|
||||
sourceDuration: 100,
|
||||
duration: 2,
|
||||
bandwidth: 10000,
|
||||
periodIndex: 1,
|
||||
mimeType: 'audio/mp4'
|
||||
},
|
||||
segments: [{
|
||||
uri: '',
|
||||
timeline: 1,
|
||||
duration: 2,
|
||||
resolvedUri: '',
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: ''
|
||||
},
|
||||
number: 1
|
||||
}, {
|
||||
uri: '',
|
||||
timeline: 1,
|
||||
duration: 2,
|
||||
resolvedUri: '',
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: ''
|
||||
},
|
||||
number: 2
|
||||
}]
|
||||
}, {
|
||||
attributes: {
|
||||
sourceDuration: 100,
|
||||
id: '1',
|
||||
width: 800,
|
||||
duration: 2,
|
||||
height: 600,
|
||||
codecs: 'foo;bar',
|
||||
bandwidth: 10000,
|
||||
periodIndex: 1,
|
||||
mimeType: 'video/mp4'
|
||||
},
|
||||
segments: [{
|
||||
uri: '',
|
||||
timeline: 1,
|
||||
duration: 2,
|
||||
resolvedUri: '',
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: ''
|
||||
},
|
||||
number: 1
|
||||
}, {
|
||||
uri: '',
|
||||
timeline: 1,
|
||||
duration: 2,
|
||||
resolvedUri: '',
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: ''
|
||||
},
|
||||
number: 2
|
||||
}]
|
||||
}, {
|
||||
attributes: {
|
||||
sourceDuration: 100,
|
||||
id: '1',
|
||||
duration: 2,
|
||||
bandwidth: 20000,
|
||||
periodIndex: 1,
|
||||
mimeType: 'text/vtt',
|
||||
baseUrl: 'https://www.example.com/vtt'
|
||||
},
|
||||
segments: [{
|
||||
uri: '',
|
||||
timeline: 1,
|
||||
duration: 2,
|
||||
resolvedUri: '',
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: ''
|
||||
},
|
||||
number: 1
|
||||
}, {
|
||||
uri: '',
|
||||
timeline: 1,
|
||||
duration: 2,
|
||||
resolvedUri: '',
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: ''
|
||||
},
|
||||
number: 2
|
||||
}]
|
||||
}, {
|
||||
attributes: {
|
||||
sourceDuration: 100,
|
||||
duration: 2,
|
||||
id: '1',
|
||||
bandwidth: 10000,
|
||||
periodIndex: 1,
|
||||
mimeType: 'text/vtt',
|
||||
baseUrl: 'https://www.example.com/vtt'
|
||||
},
|
||||
segments: [{
|
||||
uri: '',
|
||||
timeline: 1,
|
||||
duration: 2,
|
||||
resolvedUri: '',
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: ''
|
||||
},
|
||||
number: 1
|
||||
}, {
|
||||
uri: '',
|
||||
timeline: 1,
|
||||
duration: 2,
|
||||
resolvedUri: '',
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: ''
|
||||
},
|
||||
number: 2
|
||||
}]
|
||||
}];
|
||||
|
||||
const expected = {
|
||||
allowCache: true,
|
||||
discontinuityStarts: [],
|
||||
duration: 100,
|
||||
endList: true,
|
||||
mediaGroups: {
|
||||
AUDIO: {
|
||||
audio: {
|
||||
main: {
|
||||
autoselect: true,
|
||||
default: true,
|
||||
language: '',
|
||||
playlists: [{
|
||||
attributes: {
|
||||
BANDWIDTH: 20000,
|
||||
CODECS: 'foo;bar',
|
||||
NAME: '1',
|
||||
['PROGRAM-ID']: 1
|
||||
},
|
||||
targetDuration: 2,
|
||||
mediaSequence: 1,
|
||||
endList: true,
|
||||
resolvedUri: '',
|
||||
segments: [{
|
||||
uri: '',
|
||||
timeline: 1,
|
||||
duration: 2,
|
||||
resolvedUri: '',
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: ''
|
||||
},
|
||||
number: 1
|
||||
}, {
|
||||
uri: '',
|
||||
timeline: 1,
|
||||
duration: 2,
|
||||
resolvedUri: '',
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: ''
|
||||
},
|
||||
number: 2
|
||||
}],
|
||||
timeline: 1,
|
||||
uri: ''
|
||||
}],
|
||||
uri: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
['CLOSED-CAPTIONS']: {},
|
||||
SUBTITLES: {
|
||||
subs: {
|
||||
text: {
|
||||
autoselect: false,
|
||||
default: false,
|
||||
language: 'text',
|
||||
playlists: [{
|
||||
attributes: {
|
||||
BANDWIDTH: 20000,
|
||||
NAME: '1',
|
||||
['PROGRAM-ID']: 1
|
||||
},
|
||||
endList: true,
|
||||
targetDuration: 2,
|
||||
mediaSequence: 1,
|
||||
resolvedUri: 'https://www.example.com/vtt',
|
||||
segments: [{
|
||||
uri: '',
|
||||
timeline: 1,
|
||||
duration: 2,
|
||||
resolvedUri: '',
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: ''
|
||||
},
|
||||
number: 1
|
||||
}, {
|
||||
uri: '',
|
||||
timeline: 1,
|
||||
duration: 2,
|
||||
resolvedUri: '',
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: ''
|
||||
},
|
||||
number: 2
|
||||
}],
|
||||
timeline: 1,
|
||||
uri: ''
|
||||
}],
|
||||
uri: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
VIDEO: {}
|
||||
},
|
||||
playlists: [{
|
||||
attributes: {
|
||||
AUDIO: 'audio',
|
||||
SUBTITLES: 'subs',
|
||||
BANDWIDTH: 10000,
|
||||
CODECS: 'foo;bar',
|
||||
NAME: '1',
|
||||
['PROGRAM-ID']: 1,
|
||||
RESOLUTION: {
|
||||
height: 600,
|
||||
width: 800
|
||||
}
|
||||
},
|
||||
endList: true,
|
||||
resolvedUri: '',
|
||||
mediaSequence: 1,
|
||||
targetDuration: 2,
|
||||
segments: [{
|
||||
uri: '',
|
||||
timeline: 1,
|
||||
duration: 2,
|
||||
resolvedUri: '',
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: ''
|
||||
},
|
||||
number: 1
|
||||
}, {
|
||||
uri: '',
|
||||
timeline: 1,
|
||||
duration: 2,
|
||||
resolvedUri: '',
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: ''
|
||||
},
|
||||
number: 2
|
||||
}],
|
||||
timeline: 1,
|
||||
uri: ''
|
||||
}],
|
||||
segments: [],
|
||||
uri: ''
|
||||
};
|
||||
|
||||
assert.deepEqual(toM3u8(input), expected);
|
||||
});
|
||||
|
||||
QUnit.test('playlists with sidx and sidxMapping', function(assert) {
|
||||
const input = [{
|
||||
attributes: {
|
||||
sourceDuration: 100,
|
||||
id: '1',
|
||||
width: 800,
|
||||
height: 600,
|
||||
codecs: 'foo;bar',
|
||||
duration: 0,
|
||||
bandwidth: 10000,
|
||||
periodIndex: 1,
|
||||
mimeType: 'video/mp4'
|
||||
},
|
||||
segments: [],
|
||||
sidx: {
|
||||
byterange: {
|
||||
offset: 10,
|
||||
length: 10
|
||||
},
|
||||
uri: 'sidx.mp4',
|
||||
resolvedUri: 'http://example.com/sidx.mp4',
|
||||
duration: 10
|
||||
},
|
||||
uri: 'http://example.com/fmp4.mp4'
|
||||
}];
|
||||
|
||||
const mapping = {
|
||||
'sidx.mp4-10-19': {
|
||||
sidx: {
|
||||
timescale: 1,
|
||||
firstOffset: 0,
|
||||
references: [{
|
||||
referenceType: 0,
|
||||
referencedSize: 5,
|
||||
subsegmentDuration: 2
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const expected = [{
|
||||
attributes: {
|
||||
AUDIO: 'audio',
|
||||
SUBTITLES: 'subs',
|
||||
BANDWIDTH: 10000,
|
||||
CODECS: 'foo;bar',
|
||||
NAME: '1',
|
||||
['PROGRAM-ID']: 1,
|
||||
RESOLUTION: {
|
||||
height: 600,
|
||||
width: 800
|
||||
}
|
||||
},
|
||||
sidx: {
|
||||
byterange: {
|
||||
offset: 10,
|
||||
length: 10
|
||||
},
|
||||
uri: 'sidx.mp4',
|
||||
resolvedUri: 'http://example.com/sidx.mp4',
|
||||
duration: 10
|
||||
},
|
||||
targetDuration: 0,
|
||||
timeline: 1,
|
||||
uri: '',
|
||||
segments: [{
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/sidx.mp4',
|
||||
uri: ''
|
||||
},
|
||||
byterange: {
|
||||
offset: 20,
|
||||
length: 5
|
||||
},
|
||||
uri: 'http://example.com/sidx.mp4',
|
||||
resolvedUri: 'http://example.com/sidx.mp4',
|
||||
duration: 2,
|
||||
number: 0,
|
||||
timeline: 1
|
||||
}],
|
||||
endList: true,
|
||||
mediaSequence: 1,
|
||||
resolvedUri: ''
|
||||
}];
|
||||
|
||||
assert.deepEqual(toM3u8(input, null, mapping).playlists, expected);
|
||||
});
|
||||
|
||||
QUnit.test('playlists without minimumUpdatePeriod dont assign default value', function(assert) {
|
||||
const input = [{
|
||||
attributes: {
|
||||
sourceDuration: 100,
|
||||
id: '1',
|
||||
width: 800,
|
||||
height: 600,
|
||||
codecs: 'foo;bar',
|
||||
duration: 0,
|
||||
bandwidth: 10000,
|
||||
periodIndex: 1,
|
||||
mimeType: 'video/mp4'
|
||||
},
|
||||
segments: [],
|
||||
sidx: {
|
||||
byterange: {
|
||||
offset: 10,
|
||||
length: 10
|
||||
},
|
||||
uri: 'sidx.mp4',
|
||||
resolvedUri: 'http://example.com/sidx.mp4',
|
||||
duration: 10
|
||||
},
|
||||
uri: 'http://example.com/fmp4.mp4'
|
||||
}];
|
||||
|
||||
assert.equal(toM3u8(input).minimumUpdatePeriod, undefined);
|
||||
});
|
||||
|
||||
QUnit.test('playlists with minimumUpdatePeriod = 0', function(assert) {
|
||||
const input = [{
|
||||
attributes: {
|
||||
sourceDuration: 100,
|
||||
id: '1',
|
||||
width: 800,
|
||||
height: 600,
|
||||
codecs: 'foo;bar',
|
||||
duration: 0,
|
||||
bandwidth: 10000,
|
||||
periodIndex: 1,
|
||||
mimeType: 'video/mp4',
|
||||
minimumUpdatePeriod: 0
|
||||
},
|
||||
segments: [],
|
||||
sidx: {
|
||||
byterange: {
|
||||
offset: 10,
|
||||
length: 10
|
||||
},
|
||||
uri: 'sidx.mp4',
|
||||
resolvedUri: 'http://example.com/sidx.mp4',
|
||||
duration: 10
|
||||
},
|
||||
uri: 'http://example.com/fmp4.mp4'
|
||||
}];
|
||||
|
||||
assert.equal(toM3u8(input).minimumUpdatePeriod, 0);
|
||||
});
|
||||
|
||||
QUnit.test('playlists with integer value for minimumUpdatePeriod', function(assert) {
|
||||
const input = [{
|
||||
attributes: {
|
||||
sourceDuration: 100,
|
||||
id: '1',
|
||||
width: 800,
|
||||
height: 600,
|
||||
codecs: 'foo;bar',
|
||||
duration: 0,
|
||||
bandwidth: 10000,
|
||||
periodIndex: 1,
|
||||
mimeType: 'video/mp4',
|
||||
minimumUpdatePeriod: 2
|
||||
},
|
||||
segments: [],
|
||||
sidx: {
|
||||
byterange: {
|
||||
offset: 10,
|
||||
length: 10
|
||||
},
|
||||
uri: 'sidx.mp4',
|
||||
resolvedUri: 'http://example.com/sidx.mp4',
|
||||
duration: 10
|
||||
},
|
||||
uri: 'http://example.com/fmp4.mp4'
|
||||
}];
|
||||
|
||||
assert.equal(toM3u8(input).minimumUpdatePeriod, 2000, 'converts update period to ms');
|
||||
});
|
||||
|
||||
QUnit.test('no playlists', function(assert) {
|
||||
assert.deepEqual(toM3u8([]), {});
|
||||
});
|
||||
|
||||
QUnit.test('dynamic playlists with suggestedPresentationDelay', function(assert) {
|
||||
const input = [{
|
||||
attributes: {
|
||||
id: '1',
|
||||
codecs: 'foo;bar',
|
||||
sourceDuration: 100,
|
||||
duration: 0,
|
||||
bandwidth: 20000,
|
||||
periodIndex: 1,
|
||||
mimeType: 'audio/mp4',
|
||||
type: 'dynamic',
|
||||
suggestedPresentationDelay: 18
|
||||
},
|
||||
segments: []
|
||||
}, {
|
||||
attributes: {
|
||||
id: '2',
|
||||
codecs: 'foo;bar',
|
||||
sourceDuration: 100,
|
||||
duration: 0,
|
||||
bandwidth: 10000,
|
||||
periodIndex: 1,
|
||||
mimeType: 'audio/mp4'
|
||||
},
|
||||
segments: []
|
||||
}, {
|
||||
attributes: {
|
||||
sourceDuration: 100,
|
||||
id: '1',
|
||||
width: 800,
|
||||
height: 600,
|
||||
codecs: 'foo;bar',
|
||||
duration: 0,
|
||||
bandwidth: 10000,
|
||||
periodIndex: 1,
|
||||
mimeType: 'video/mp4'
|
||||
},
|
||||
segments: []
|
||||
}, {
|
||||
attributes: {
|
||||
sourceDuration: 100,
|
||||
id: '1',
|
||||
bandwidth: 20000,
|
||||
periodIndex: 1,
|
||||
mimeType: 'text/vtt',
|
||||
baseUrl: 'https://www.example.com/vtt'
|
||||
}
|
||||
}, {
|
||||
attributes: {
|
||||
sourceDuration: 100,
|
||||
id: '1',
|
||||
bandwidth: 10000,
|
||||
periodIndex: 1,
|
||||
mimeType: 'text/vtt',
|
||||
baseUrl: 'https://www.example.com/vtt'
|
||||
}
|
||||
}];
|
||||
|
||||
const output = toM3u8(input);
|
||||
|
||||
assert.ok('suggestedPresentationDelay' in output);
|
||||
assert.deepEqual(output.suggestedPresentationDelay, 18);
|
||||
});
|
||||
171
build/javascript/node_modules/mpd-parser/test/toPlaylists.test.js
generated
vendored
171
build/javascript/node_modules/mpd-parser/test/toPlaylists.test.js
generated
vendored
@@ -1,171 +0,0 @@
|
||||
import {
|
||||
toPlaylists
|
||||
} from '../src/toPlaylists';
|
||||
import QUnit from 'qunit';
|
||||
|
||||
QUnit.module('toPlaylists');
|
||||
|
||||
QUnit.test('no representations', function(assert) {
|
||||
assert.deepEqual(toPlaylists([]), []);
|
||||
});
|
||||
|
||||
QUnit.test('pretty simple', function(assert) {
|
||||
const representations = [{
|
||||
attributes: { baseUrl: 'http://example.com/', periodIndex: 0, sourceDuration: 2 },
|
||||
segmentInfo: {
|
||||
template: { }
|
||||
}
|
||||
}];
|
||||
|
||||
const playlists = [{
|
||||
attributes: {
|
||||
baseUrl: 'http://example.com/',
|
||||
periodIndex: 0,
|
||||
sourceDuration: 2,
|
||||
duration: 2
|
||||
},
|
||||
segments: [{
|
||||
uri: '',
|
||||
timeline: 0,
|
||||
duration: 2,
|
||||
resolvedUri: 'http://example.com/',
|
||||
map: {
|
||||
uri: '',
|
||||
resolvedUri: 'http://example.com/'
|
||||
},
|
||||
number: 1
|
||||
}]
|
||||
}];
|
||||
|
||||
assert.deepEqual(toPlaylists(representations), playlists);
|
||||
});
|
||||
|
||||
QUnit.test('segment base', function(assert) {
|
||||
const representations = [{
|
||||
attributes: { baseUrl: 'http://example.com/', periodIndex: 0, sourceDuration: 2 },
|
||||
segmentInfo: {
|
||||
base: true
|
||||
}
|
||||
}];
|
||||
|
||||
const playlists = [{
|
||||
attributes: {
|
||||
baseUrl: 'http://example.com/',
|
||||
periodIndex: 0,
|
||||
sourceDuration: 2,
|
||||
duration: 2
|
||||
},
|
||||
segments: [{
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/',
|
||||
uri: ''
|
||||
},
|
||||
resolvedUri: 'http://example.com/',
|
||||
uri: 'http://example.com/',
|
||||
timeline: 0,
|
||||
duration: 2,
|
||||
number: 0
|
||||
}]
|
||||
}];
|
||||
|
||||
assert.deepEqual(toPlaylists(representations), playlists);
|
||||
});
|
||||
|
||||
QUnit.test('segment base with sidx', function(assert) {
|
||||
const representations = [{
|
||||
attributes: {
|
||||
baseUrl: 'http://example.com/',
|
||||
periodIndex: 0,
|
||||
sourceDuration: 2,
|
||||
indexRange: '10-19'
|
||||
},
|
||||
segmentInfo: {
|
||||
base: true
|
||||
}
|
||||
}];
|
||||
|
||||
const playlists = [{
|
||||
attributes: {
|
||||
baseUrl: 'http://example.com/',
|
||||
periodIndex: 0,
|
||||
sourceDuration: 2,
|
||||
duration: 2,
|
||||
indexRange: '10-19'
|
||||
},
|
||||
segments: [],
|
||||
sidx: {
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/',
|
||||
uri: ''
|
||||
},
|
||||
resolvedUri: 'http://example.com/',
|
||||
uri: 'http://example.com/',
|
||||
byterange: {
|
||||
offset: 10,
|
||||
length: 10
|
||||
},
|
||||
timeline: 0,
|
||||
duration: 2,
|
||||
number: 0
|
||||
}
|
||||
}];
|
||||
|
||||
assert.deepEqual(toPlaylists(representations), playlists);
|
||||
});
|
||||
|
||||
QUnit.test('segment list', function(assert) {
|
||||
const representations = [{
|
||||
attributes: {
|
||||
baseUrl: 'http://example.com/',
|
||||
duration: 10,
|
||||
sourceDuration: 11,
|
||||
periodIndex: 0
|
||||
},
|
||||
segmentInfo: {
|
||||
list: {
|
||||
segmentUrls: [{
|
||||
media: '1.fmp4'
|
||||
}, {
|
||||
media: '2.fmp4'
|
||||
}]
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
const playlists = [{
|
||||
attributes: {
|
||||
baseUrl: 'http://example.com/',
|
||||
duration: 10,
|
||||
sourceDuration: 11,
|
||||
segmentUrls: [{
|
||||
media: '1.fmp4'
|
||||
}, {
|
||||
media: '2.fmp4'
|
||||
}],
|
||||
periodIndex: 0
|
||||
},
|
||||
segments: [{
|
||||
duration: 10,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/',
|
||||
uri: ''
|
||||
},
|
||||
resolvedUri: 'http://example.com/1.fmp4',
|
||||
timeline: 0,
|
||||
uri: '1.fmp4',
|
||||
number: 1
|
||||
}, {
|
||||
duration: 1,
|
||||
map: {
|
||||
resolvedUri: 'http://example.com/',
|
||||
uri: ''
|
||||
},
|
||||
resolvedUri: 'http://example.com/2.fmp4',
|
||||
timeline: 0,
|
||||
uri: '2.fmp4',
|
||||
number: 2
|
||||
}]
|
||||
}];
|
||||
|
||||
assert.deepEqual(toPlaylists(representations), playlists);
|
||||
});
|
||||
219
build/javascript/node_modules/mpd-parser/test/utils.test.js
generated
vendored
219
build/javascript/node_modules/mpd-parser/test/utils.test.js
generated
vendored
@@ -1,219 +0,0 @@
|
||||
import { merge, values } from '../src/utils/object';
|
||||
import { parseDuration } from '../src/utils/time';
|
||||
import { flatten, range, from, findIndexes } from '../src/utils/list';
|
||||
import { findChildren, getContent } from '../src/utils/xml';
|
||||
import {DOMParser} from 'xmldom';
|
||||
import {JSDOM} from 'jsdom';
|
||||
import QUnit from 'qunit';
|
||||
|
||||
const document = new JSDOM().window.document;
|
||||
|
||||
QUnit.module('utils');
|
||||
|
||||
QUnit.module('merge');
|
||||
QUnit.test('empty', function(assert) {
|
||||
assert.deepEqual(merge({}, { a: 1 }), { a: 1 });
|
||||
assert.deepEqual(merge({ a: 1 }, { a: 1 }), { a: 1 });
|
||||
assert.deepEqual(merge({ a: 1 }, {}), { a: 1 });
|
||||
});
|
||||
|
||||
QUnit.test('append', function(assert) {
|
||||
assert.deepEqual(merge({ a: 1 }, { b: 3 }), { a: 1, b: 3 });
|
||||
});
|
||||
|
||||
QUnit.test('overwrite', function(assert) {
|
||||
assert.deepEqual(merge({ a: 1 }, { a: 2 }), { a: 2 });
|
||||
});
|
||||
|
||||
QUnit.test('empty', function(assert) {
|
||||
assert.deepEqual(merge({}, {}), {});
|
||||
assert.deepEqual(merge({}, 1), {});
|
||||
assert.deepEqual(merge(1, {}), {});
|
||||
});
|
||||
|
||||
QUnit.test('Test for checking the merge when multiple segment Information are present', function(assert) {
|
||||
|
||||
const adaptationSetInfo = {
|
||||
|
||||
base: { duration: '10'}
|
||||
};
|
||||
|
||||
const representationInfo = {
|
||||
|
||||
base: { duration: '25', indexRange: '230-252'}
|
||||
};
|
||||
|
||||
const expected = {
|
||||
|
||||
base: { duration: '25', indexRange: '230-252'}
|
||||
};
|
||||
|
||||
assert.deepEqual(
|
||||
merge(adaptationSetInfo, representationInfo), expected,
|
||||
'Merged SegmentBase info'
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
QUnit.test('Test for checking the merge when segment Information is present at a level and is undefined at another', function(assert) {
|
||||
const periodInfo = {
|
||||
base: {
|
||||
initialization: {
|
||||
range: '0-8888'
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const adaptationSetInfo = {
|
||||
|
||||
base: { duration: '10', indexRange: '230-252'}
|
||||
};
|
||||
|
||||
const representationInfo = {};
|
||||
|
||||
const expected = {
|
||||
|
||||
base: { duration: '10', indexRange: '230-252', initialization: {range: '0-8888'}}
|
||||
};
|
||||
|
||||
assert.deepEqual(
|
||||
merge(periodInfo, adaptationSetInfo, representationInfo), expected,
|
||||
'Merged SegmentBase info'
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
QUnit.module('values');
|
||||
|
||||
QUnit.test('empty', function(assert) {
|
||||
assert.deepEqual(values({}), []);
|
||||
});
|
||||
|
||||
QUnit.test('mixed', function(assert) {
|
||||
assert.deepEqual(values({ a: 1, b: true, c: 'foo'}), [1, true, 'foo']);
|
||||
});
|
||||
|
||||
QUnit.module('flatten');
|
||||
QUnit.test('empty', function(assert) {
|
||||
assert.deepEqual(flatten([]), []);
|
||||
});
|
||||
|
||||
QUnit.test('one item', function(assert) {
|
||||
assert.deepEqual(flatten([[1]]), [1]);
|
||||
});
|
||||
|
||||
QUnit.test('multiple items', function(assert) {
|
||||
assert.deepEqual(flatten([[1], [2], [3]]), [1, 2, 3]);
|
||||
});
|
||||
|
||||
QUnit.test('multiple multiple items', function(assert) {
|
||||
assert.deepEqual(flatten([[1], [2, 3], [4]]), [1, 2, 3, 4]);
|
||||
});
|
||||
|
||||
QUnit.test('nested nests', function(assert) {
|
||||
assert.deepEqual(flatten([[1], [[2]]]), [1, [2]]);
|
||||
});
|
||||
|
||||
QUnit.test('not a list of lists', function(assert) {
|
||||
assert.deepEqual(flatten([1, 2]), [1, 2]);
|
||||
assert.deepEqual(flatten([[1], 2]), [1, 2]);
|
||||
});
|
||||
|
||||
QUnit.module('parseDuration');
|
||||
QUnit.test('full date', function(assert) {
|
||||
assert.deepEqual(parseDuration('P10Y10M10DT10H10M10.1S'), 342180610.1);
|
||||
});
|
||||
|
||||
QUnit.test('time only', function(assert) {
|
||||
assert.deepEqual(parseDuration('PT10H10M10.1S'), 36610.1);
|
||||
});
|
||||
|
||||
QUnit.test('empty', function(assert) {
|
||||
assert.deepEqual(parseDuration(''), 0);
|
||||
});
|
||||
|
||||
QUnit.test('invalid', function(assert) {
|
||||
assert.deepEqual(parseDuration('foo'), 0);
|
||||
});
|
||||
|
||||
QUnit.module('range');
|
||||
QUnit.test('simple', function(assert) {
|
||||
assert.deepEqual(range(1, 4), [1, 2, 3]);
|
||||
});
|
||||
|
||||
QUnit.test('single number range', function(assert) {
|
||||
assert.deepEqual(range(1, 1), []);
|
||||
});
|
||||
|
||||
QUnit.test('negative', function(assert) {
|
||||
assert.deepEqual(range(-1, 2), [-1, 0, 1]);
|
||||
});
|
||||
|
||||
QUnit.module('from');
|
||||
|
||||
QUnit.test('simple array', function(assert) {
|
||||
assert.deepEqual(from([1]), [1]);
|
||||
});
|
||||
|
||||
QUnit.test('empty array', function(assert) {
|
||||
assert.deepEqual(from([]), []);
|
||||
});
|
||||
|
||||
QUnit.test('non-array', function(assert) {
|
||||
assert.deepEqual(from(1), []);
|
||||
});
|
||||
|
||||
QUnit.test('array-like', function(assert) {
|
||||
const fixture = document.createElement('div');
|
||||
|
||||
fixture.innerHTML = '<div></div><div></div>';
|
||||
|
||||
const result = from(fixture.getElementsByTagName('div'));
|
||||
|
||||
assert.ok(result.map);
|
||||
assert.deepEqual(result.length, 2);
|
||||
});
|
||||
|
||||
QUnit.module('findIndexes');
|
||||
|
||||
QUnit.test('index not found', function(assert) {
|
||||
assert.deepEqual(findIndexes([], 'a'), []);
|
||||
assert.deepEqual(findIndexes([], ''), []);
|
||||
assert.deepEqual(findIndexes([{ a: true}], 'b'), []);
|
||||
});
|
||||
|
||||
QUnit.test('indexes found', function(assert) {
|
||||
assert.deepEqual(findIndexes([{ a: true}], 'a'), [0]);
|
||||
assert.deepEqual(findIndexes([
|
||||
{ a: true },
|
||||
{ b: true },
|
||||
{ b: true, c: true }
|
||||
], 'b'), [1, 2]);
|
||||
});
|
||||
|
||||
QUnit.module('xml', {
|
||||
beforeEach() {
|
||||
const parser = new DOMParser();
|
||||
const xmlString = `
|
||||
<fix>
|
||||
<test>foo </test>
|
||||
<div>bar</div>
|
||||
<div>baz</div>
|
||||
</fix>`;
|
||||
|
||||
this.fixture = parser.parseFromString(xmlString, 'text/xml').documentElement;
|
||||
}
|
||||
});
|
||||
|
||||
QUnit.test('findChildren', function(assert) {
|
||||
assert.deepEqual(findChildren(this.fixture, 'test').length, 1, 'single');
|
||||
assert.deepEqual(findChildren(this.fixture, 'div').length, 2, 'multiple');
|
||||
assert.deepEqual(findChildren(this.fixture, 'el').length, 0, 'none');
|
||||
});
|
||||
|
||||
QUnit.test('getContent', function(assert) {
|
||||
const result = findChildren(this.fixture, 'test')[0];
|
||||
|
||||
assert.deepEqual(getContent(result), 'foo', 'gets text and trims');
|
||||
});
|
||||
Reference in New Issue
Block a user