First release

This commit is contained in:
Owen Quinlan 2021-07-02 19:29:34 +10:00
commit fa6c85266e
2339 changed files with 761050 additions and 0 deletions

122
node_modules/mpd-parser/test/index.test.js generated vendored Normal file
View file

@ -0,0 +1,122 @@
import { parse, VERSION } from '../src';
import QUnit from 'qunit';
QUnit.dump.maxDepth = Infinity;
// manifests
import vttCodecsTemplate from './manifests/vtt_codecs.mpd';
import maatVttSegmentTemplate from './manifests/maat_vtt_segmentTemplate.mpd';
import segmentBaseTemplate from './manifests/segmentBase.mpd';
import segmentListTemplate from './manifests/segmentList.mpd';
import cc608CaptionsTemplate from './manifests/608-captions.mpd';
import cc708CaptionsTemplate from './manifests/708-captions.mpd';
import locationTemplate from './manifests/location.mpd';
import locationsTemplate from './manifests/locations.mpd';
import multiperiod from './manifests/multiperiod.mpd';
import webmsegments from './manifests/webmsegments.mpd';
import multiperiodDynamic from './manifests/multiperiod-dynamic.mpd';
import audioOnly from './manifests/audio-only.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 cc608CaptionsManifest
} from './manifests/608-captions.js';
import {
parsedManifest as cc708CaptionsManifest
} from './manifests/708-captions.js';
import {
parsedManifest as multiperiodManifest
} from './manifests/multiperiod.js';
import {
parsedManifest as webmsegmentsManifest
} from './manifests/webmsegments.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';
import {
parsedManifest as vttCodecsManifest
} from './manifests/vtt_codecs.js';
import {
parsedManifest as audioOnlyManifest
} from './manifests/audio-only.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: '608-captions',
input: cc608CaptionsTemplate,
expected: cc608CaptionsManifest
}, {
name: '708-captions',
input: cc708CaptionsTemplate,
expected: cc708CaptionsManifest
}, {
name: 'multiperiod',
input: multiperiod,
expected: multiperiodManifest
}, {
name: 'webmsegments',
input: webmsegments,
expected: webmsegmentsManifest
}, {
name: 'multiperiod_dynamic',
input: multiperiodDynamic,
expected: multiperiodDynamicManifest
}, {
name: 'location',
input: locationTemplate,
expected: locationManifest
}, {
name: 'locations',
input: locationsTemplate,
expected: locationsManifest
}, {
name: 'vtt_codecs',
input: vttCodecsTemplate,
expected: vttCodecsManifest
}, {
name: 'audio-only',
input: audioOnly,
expected: audioOnlyManifest
}].forEach(({ name, input, expected }) => {
QUnit.test(`${name} test manifest`, function(assert) {
const actual = parse(input);
assert.deepEqual(actual, expected);
});
});

1758
node_modules/mpd-parser/test/inheritAttributes.test.js generated vendored Normal file

File diff suppressed because it is too large Load diff

70
node_modules/mpd-parser/test/manifests/608-captions.js generated vendored Normal file
View file

@ -0,0 +1,70 @@
export const parsedManifest = {
allowCache: true,
discontinuityStarts: [],
duration: 6,
endList: true,
mediaGroups: {
'AUDIO': {},
'CLOSED-CAPTIONS': {
cc: {
eng: {
autoselect: false,
default: false,
instreamId: 'CC1',
language: 'eng'
},
swe: {
autoselect: false,
default: false,
instreamId: 'CC3',
language: 'swe'
},
Hello: {
autoselect: false,
default: false,
instreamId: 'CC4',
language: 'Hello'
}
}
},
'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: ''
};

View file

@ -0,0 +1,17 @@
<?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">
<Accessibility schemeIdUri="urn:scte:dash:cc:cea-608:2015" value="CC1=eng;CC3=swe;CC4=Hello"></Accessibility>
<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>

71
node_modules/mpd-parser/test/manifests/708-captions.js generated vendored Normal file
View file

@ -0,0 +1,71 @@
export const parsedManifest = {
allowCache: true,
discontinuityStarts: [],
duration: 6,
endList: true,
mediaGroups: {
'AUDIO': {},
'CLOSED-CAPTIONS': {
cc: {
// eng: {
// autoselect: false,
// default: false,
// instreamId: '1',
// language: 'eng',
// aspectRatio: 1,
// easyReader: 0,
// '3D': 0
// },
// TODO only this one ends up being represented and not both
eng: {
'autoselect': false,
'default': false,
'instreamId': 'SERVICE2',
'language': 'eng',
'aspectRatio': 1,
'easyReader': 1,
'3D': 0
}
}
},
'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: ''
};

View file

@ -0,0 +1,17 @@
<?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">
<Accessibility schemeIdUri="urn:scte:dash:cc:cea-708:2015" value="1=lang:eng;2=lang:eng,war:1,er:1"></Accessibility>
<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>

106
node_modules/mpd-parser/test/manifests/audio-only.js generated vendored Normal file
View file

@ -0,0 +1,106 @@
export const parsedManifest = {
allowCache: true,
discontinuityStarts: [],
segments: [],
endList: true,
mediaGroups: {
'AUDIO': {
audio: {
en: {
language: 'en',
autoselect: true,
default: true,
playlists: [
{
attributes: {
'NAME': '0',
'BANDWIDTH': 130803,
'CODECS': 'mp4a.40.2',
'PROGRAM-ID': 1,
'AUDIO': 'audio',
'SUBTITLES': 'subs'
},
uri: '',
endList: true,
timeline: 0,
resolvedUri: '',
targetDuration: 60,
segments: [],
mediaSequence: 1,
sidx: {
uri: 'http://example.com/audio_en_2c_128k_aac.mp4',
resolvedUri: 'http://example.com/audio_en_2c_128k_aac.mp4',
byterange: {
length: 224,
offset: 786
},
map: {
uri: '',
resolvedUri: 'http://example.com/audio_en_2c_128k_aac.mp4',
byterange: {
length: 786,
offset: 0
}
},
duration: 60,
timeline: 0,
number: 0
}
}
],
uri: ''
},
es: {
language: 'es',
autoselect: true,
default: false,
playlists: [
{
attributes: {
'NAME': '1',
'BANDWIDTH': 130405,
'CODECS': 'mp4a.40.2',
'PROGRAM-ID': 1,
'AUDIO': 'audio',
'SUBTITLES': 'subs'
},
uri: '',
endList: true,
timeline: 0,
resolvedUri: '',
targetDuration: 60,
segments: [],
mediaSequence: 1,
sidx: {
uri: 'http://example.com/audio_es_2c_128k_aac.mp4',
resolvedUri: 'http://example.com/audio_es_2c_128k_aac.mp4',
byterange: {
length: 224,
offset: 786
},
map: {
uri: '',
resolvedUri: 'http://example.com/audio_es_2c_128k_aac.mp4',
byterange: {
length: 786,
offset: 0
}
},
duration: 60,
timeline: 0,
number: 0
}
}
],
uri: ''
}
}
},
'VIDEO': {},
'CLOSED-CAPTIONS': {},
'SUBTITLES': {}
},
uri: '',
duration: 60,
playlists: []
};

25
node_modules/mpd-parser/test/manifests/audio-only.mpd generated vendored Normal file
View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version v2.4.1-c731217-release-->
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT60S">
<Period id="0">
<AdaptationSet id="0" contentType="audio" lang="en" subsegmentAlignment="true">
<Representation id="0" bandwidth="130803" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="48000">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<BaseURL>http://example.com/audio_en_2c_128k_aac.mp4</BaseURL>
<SegmentBase indexRange="786-1009" timescale="48000">
<Initialization range="0-785"/>
</SegmentBase>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="audio" lang="es" subsegmentAlignment="true">
<Representation id="1" bandwidth="130405" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="48000">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<BaseURL>http://example.com/audio_es_2c_128k_aac.mp4</BaseURL>
<SegmentBase indexRange="786-1009" timescale="48000">
<Initialization range="0-785"/>
</SegmentBase>
</Representation>
</AdaptationSet>
</Period>
</MPD>

52
node_modules/mpd-parser/test/manifests/location.js generated vendored Normal file
View file

@ -0,0 +1,52 @@
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
node_modules/mpd-parser/test/manifests/location.mpd generated vendored Normal file
View file

@ -0,0 +1,17 @@
<?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
node_modules/mpd-parser/test/manifests/locations.js generated vendored Normal file
View file

@ -0,0 +1,53 @@
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
node_modules/mpd-parser/test/manifests/locations.mpd generated vendored Normal file
View file

@ -0,0 +1,18 @@
<?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>

View file

@ -0,0 +1,518 @@
export const parsedManifest = {
allowCache: true,
discontinuityStarts: [],
segments: [],
endList: true,
mediaGroups: {
'AUDIO': {
audio: {
'en (main)': {
language: 'en',
autoselect: true,
default: true,
playlists: [
{
attributes: {
'NAME': '63000',
'BANDWIDTH': 63000,
'CODECS': 'mp4a.40.2',
'PROGRAM-ID': 1
},
uri: '',
endList: true,
timeline: 0,
resolvedUri: '',
targetDuration: 1.984,
segments: [
{
uri: '63000/0.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/63000/0.m4f',
map: {
uri: '63000/init.m4f',
resolvedUri: 'https://www.example.com/63000/init.m4f'
},
number: 0
},
{
uri: '63000/1.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/63000/1.m4f',
map: {
uri: '63000/init.m4f',
resolvedUri: 'https://www.example.com/63000/init.m4f'
},
number: 1
},
{
uri: '63000/2.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/63000/2.m4f',
map: {
uri: '63000/init.m4f',
resolvedUri: 'https://www.example.com/63000/init.m4f'
},
number: 2
},
{
uri: '63000/3.m4f',
timeline: 0,
duration: 0.04800000000000004,
resolvedUri: 'https://www.example.com/63000/3.m4f',
map: {
uri: '63000/init.m4f',
resolvedUri: 'https://www.example.com/63000/init.m4f'
},
number: 3
}
],
mediaSequence: 0,
contentProtection: {
'com.widevine.alpha': {
attributes: {
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
},
pssh: new Uint8Array([181, 235, 45])
}
}
},
{
attributes: {
'NAME': '125000',
'BANDWIDTH': 125000,
'CODECS': 'mp4a.40.2',
'PROGRAM-ID': 1
},
uri: '',
endList: true,
timeline: 0,
resolvedUri: '',
targetDuration: 1.984,
segments: [
{
uri: '125000/0.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/125000/0.m4f',
map: {
uri: '125000/init.m4f',
resolvedUri: 'https://www.example.com/125000/init.m4f'
},
number: 0
},
{
uri: '125000/1.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/125000/1.m4f',
map: {
uri: '125000/init.m4f',
resolvedUri: 'https://www.example.com/125000/init.m4f'
},
number: 1
},
{
uri: '125000/2.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/125000/2.m4f',
map: {
uri: '125000/init.m4f',
resolvedUri: 'https://www.example.com/125000/init.m4f'
},
number: 2
},
{
uri: '125000/3.m4f',
timeline: 0,
duration: 0.04800000000000004,
resolvedUri: 'https://www.example.com/125000/3.m4f',
map: {
uri: '125000/init.m4f',
resolvedUri: 'https://www.example.com/125000/init.m4f'
},
number: 3
}
],
mediaSequence: 0,
contentProtection: {
'com.widevine.alpha': {
attributes: {
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
},
pssh: new Uint8Array([181, 235, 45])
}
}
}
],
uri: ''
},
'es': {
language: 'es',
autoselect: true,
default: false,
playlists: [
{
attributes: {
'NAME': '63000',
'BANDWIDTH': 63000,
'CODECS': 'mp4a.40.2',
'PROGRAM-ID': 1
},
uri: '',
endList: true,
timeline: 0,
resolvedUri: '',
targetDuration: 1.984,
segments: [
{
uri: '63000/es/0.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/63000/es/0.m4f',
map: {
uri: '63000/es/init.m4f',
resolvedUri: 'https://www.example.com/63000/es/init.m4f'
},
number: 0
},
{
uri: '63000/es/1.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/63000/es/1.m4f',
map: {
uri: '63000/es/init.m4f',
resolvedUri: 'https://www.example.com/63000/es/init.m4f'
},
number: 1
},
{
uri: '63000/es/2.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/63000/es/2.m4f',
map: {
uri: '63000/es/init.m4f',
resolvedUri: 'https://www.example.com/63000/es/init.m4f'
},
number: 2
},
{
uri: '63000/es/3.m4f',
timeline: 0,
duration: 0.04800000000000004,
resolvedUri: 'https://www.example.com/63000/es/3.m4f',
map: {
uri: '63000/es/init.m4f',
resolvedUri: 'https://www.example.com/63000/es/init.m4f'
},
number: 3
}
],
mediaSequence: 0,
contentProtection: {
'com.widevine.alpha': {
attributes: {
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
},
pssh: new Uint8Array([181, 235, 45])
}
}
},
{
attributes: {
'NAME': '125000',
'BANDWIDTH': 125000,
'CODECS': 'mp4a.40.2',
'PROGRAM-ID': 1
},
uri: '',
endList: true,
timeline: 0,
resolvedUri: '',
targetDuration: 1.984,
segments: [
{
uri: '125000/es/0.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/125000/es/0.m4f',
map: {
uri: '125000/es/init.m4f',
resolvedUri: 'https://www.example.com/125000/es/init.m4f'
},
number: 0
},
{
uri: '125000/es/1.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/125000/es/1.m4f',
map: {
uri: '125000/es/init.m4f',
resolvedUri: 'https://www.example.com/125000/es/init.m4f'
},
number: 1
},
{
uri: '125000/es/2.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/125000/es/2.m4f',
map: {
uri: '125000/es/init.m4f',
resolvedUri: 'https://www.example.com/125000/es/init.m4f'
},
number: 2
},
{
uri: '125000/es/3.m4f',
timeline: 0,
duration: 0.04800000000000004,
resolvedUri: 'https://www.example.com/125000/es/3.m4f',
map: {
uri: '125000/es/init.m4f',
resolvedUri: 'https://www.example.com/125000/es/init.m4f'
},
number: 3
}
],
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': {
subs: {
en: {
language: 'en',
default: false,
autoselect: false,
playlists: [
{
attributes: {
'NAME': 'en',
'BANDWIDTH': 256,
'PROGRAM-ID': 1
},
uri: '',
endList: true,
timeline: 0,
resolvedUri: 'https://example.com/en.vtt',
targetDuration: 6,
segments: [
{
uri: 'https://example.com/en.vtt',
timeline: 0,
resolvedUri: 'https://example.com/en.vtt',
duration: 6,
number: 0
}
],
mediaSequence: 0
}
],
uri: ''
},
es: {
language: 'es',
default: false,
autoselect: false,
playlists: [
{
attributes: {
'NAME': 'es',
'BANDWIDTH': 256,
'PROGRAM-ID': 1
},
uri: '',
endList: true,
timeline: 0,
resolvedUri: 'https://example.com/es.vtt',
targetDuration: 6,
segments: [
{
uri: 'https://example.com/es.vtt',
timeline: 0,
resolvedUri: 'https://example.com/es.vtt',
duration: 6,
number: 0
}
],
mediaSequence: 0
}
],
uri: ''
}
}
}
},
uri: '',
duration: 6,
playlists: [
{
attributes: {
'NAME': '482',
'AUDIO': 'audio',
'SUBTITLES': 'subs',
'RESOLUTION': {
width: 482,
height: 270
},
'CODECS': 'avc1.420015',
'BANDWIDTH': 449000,
'PROGRAM-ID': 1
},
uri: '',
endList: true,
timeline: 0,
resolvedUri: '',
targetDuration: 1.9185833333333333,
segments: [
{
uri: '482/0.m4f',
timeline: 0,
duration: 1.9185833333333333,
resolvedUri: 'https://www.example.com/482/0.m4f',
map: {
uri: '482/init.m4f',
resolvedUri: 'https://www.example.com/482/init.m4f'
},
number: 0
},
{
uri: '482/1.m4f',
timeline: 0,
duration: 1.9185833333333333,
resolvedUri: 'https://www.example.com/482/1.m4f',
map: {
uri: '482/init.m4f',
resolvedUri: 'https://www.example.com/482/init.m4f'
},
number: 1
},
{
uri: '482/2.m4f',
timeline: 0,
duration: 1.9185833333333333,
resolvedUri: 'https://www.example.com/482/2.m4f',
map: {
uri: '482/init.m4f',
resolvedUri: 'https://www.example.com/482/init.m4f'
},
number: 2
},
{
uri: '482/3.m4f',
timeline: 0,
duration: 0.24425000000000008,
resolvedUri: 'https://www.example.com/482/3.m4f',
map: {
uri: '482/init.m4f',
resolvedUri: 'https://www.example.com/482/init.m4f'
},
number: 3
}
],
mediaSequence: 0,
contentProtection: {
'com.widevine.alpha': {
attributes: {
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
},
pssh: new Uint8Array([181, 235, 45])
}
}
},
{
attributes: {
'NAME': '720',
'AUDIO': 'audio',
'SUBTITLES': 'subs',
'RESOLUTION': {
width: 720,
height: 404
},
'CODECS': 'avc1.64001e',
'BANDWIDTH': 3971000,
'PROGRAM-ID': 1
},
uri: '',
endList: true,
timeline: 0,
resolvedUri: '',
targetDuration: 1.9185833333333333,
segments: [
{
uri: '720/0.m4f',
timeline: 0,
duration: 1.9185833333333333,
resolvedUri: 'https://www.example.com/720/0.m4f',
map: {
uri: '720/init.m4f',
resolvedUri: 'https://www.example.com/720/init.m4f'
},
number: 0
},
{
uri: '720/1.m4f',
timeline: 0,
duration: 1.9185833333333333,
resolvedUri: 'https://www.example.com/720/1.m4f',
map: {
uri: '720/init.m4f',
resolvedUri: 'https://www.example.com/720/init.m4f'
},
number: 1
},
{
uri: '720/2.m4f',
timeline: 0,
duration: 1.9185833333333333,
resolvedUri: 'https://www.example.com/720/2.m4f',
map: {
uri: '720/init.m4f',
resolvedUri: 'https://www.example.com/720/init.m4f'
},
number: 2
},
{
uri: '720/3.m4f',
timeline: 0,
duration: 0.24425000000000008,
resolvedUri: 'https://www.example.com/720/3.m4f',
map: {
uri: '720/init.m4f',
resolvedUri: 'https://www.example.com/720/init.m4f'
},
number: 3
}
],
mediaSequence: 0,
contentProtection: {
'com.widevine.alpha': {
attributes: {
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
},
pssh: new Uint8Array([181, 235, 45])
}
}
}
]
};

View file

@ -0,0 +1,60 @@
<?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>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,143 @@
<?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>

1298
node_modules/mpd-parser/test/manifests/multiperiod.js generated vendored Normal file

File diff suppressed because it is too large Load diff

143
node_modules/mpd-parser/test/manifests/multiperiod.mpd generated vendored Normal file
View file

@ -0,0 +1,143 @@
<?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
node_modules/mpd-parser/test/manifests/segmentBase.js generated vendored Normal file
View file

@ -0,0 +1,49 @@
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
node_modules/mpd-parser/test/manifests/segmentBase.mpd generated vendored Normal file
View file

@ -0,0 +1,16 @@
<?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
node_modules/mpd-parser/test/manifests/segmentList.js generated vendored Normal file
View file

@ -0,0 +1,236 @@
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
node_modules/mpd-parser/test/manifests/segmentList.mpd generated vendored Normal file
View file

@ -0,0 +1,47 @@
<?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>

519
node_modules/mpd-parser/test/manifests/vtt_codecs.js generated vendored Normal file
View file

@ -0,0 +1,519 @@
export const parsedManifest = {
allowCache: true,
discontinuityStarts: [],
segments: [],
endList: true,
mediaGroups: {
'AUDIO': {
audio: {
'en (main)': {
language: 'en',
autoselect: true,
default: true,
playlists: [
{
attributes: {
'NAME': '63000',
'BANDWIDTH': 63000,
'CODECS': 'mp4a.40.2',
'PROGRAM-ID': 1
},
uri: '',
endList: true,
timeline: 0,
resolvedUri: '',
targetDuration: 1.984,
segments: [
{
uri: '63000/0.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/63000/0.m4f',
map: {
uri: '63000/init.m4f',
resolvedUri: 'https://www.example.com/63000/init.m4f'
},
number: 0
},
{
uri: '63000/1.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/63000/1.m4f',
map: {
uri: '63000/init.m4f',
resolvedUri: 'https://www.example.com/63000/init.m4f'
},
number: 1
},
{
uri: '63000/2.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/63000/2.m4f',
map: {
uri: '63000/init.m4f',
resolvedUri: 'https://www.example.com/63000/init.m4f'
},
number: 2
},
{
uri: '63000/3.m4f',
timeline: 0,
duration: 0.04800000000000004,
resolvedUri: 'https://www.example.com/63000/3.m4f',
map: {
uri: '63000/init.m4f',
resolvedUri: 'https://www.example.com/63000/init.m4f'
},
number: 3
}
],
mediaSequence: 0,
contentProtection: {
'com.widevine.alpha': {
attributes: {
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
},
pssh: new Uint8Array([181, 235, 45])
}
}
},
{
attributes: {
'NAME': '125000',
'BANDWIDTH': 125000,
'CODECS': 'mp4a.40.2',
'PROGRAM-ID': 1
},
uri: '',
endList: true,
timeline: 0,
resolvedUri: '',
targetDuration: 1.984,
segments: [
{
uri: '125000/0.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/125000/0.m4f',
map: {
uri: '125000/init.m4f',
resolvedUri: 'https://www.example.com/125000/init.m4f'
},
number: 0
},
{
uri: '125000/1.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/125000/1.m4f',
map: {
uri: '125000/init.m4f',
resolvedUri: 'https://www.example.com/125000/init.m4f'
},
number: 1
},
{
uri: '125000/2.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/125000/2.m4f',
map: {
uri: '125000/init.m4f',
resolvedUri: 'https://www.example.com/125000/init.m4f'
},
number: 2
},
{
uri: '125000/3.m4f',
timeline: 0,
duration: 0.04800000000000004,
resolvedUri: 'https://www.example.com/125000/3.m4f',
map: {
uri: '125000/init.m4f',
resolvedUri: 'https://www.example.com/125000/init.m4f'
},
number: 3
}
],
mediaSequence: 0,
contentProtection: {
'com.widevine.alpha': {
attributes: {
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
},
pssh: new Uint8Array([181, 235, 45])
}
}
}
],
uri: ''
},
'es': {
language: 'es',
autoselect: true,
default: false,
playlists: [
{
attributes: {
'NAME': '63000',
'BANDWIDTH': 63000,
'CODECS': 'mp4a.40.2',
'PROGRAM-ID': 1
},
uri: '',
endList: true,
timeline: 0,
resolvedUri: '',
targetDuration: 1.984,
segments: [
{
uri: '63000/es/0.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/63000/es/0.m4f',
map: {
uri: '63000/es/init.m4f',
resolvedUri: 'https://www.example.com/63000/es/init.m4f'
},
number: 0
},
{
uri: '63000/es/1.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/63000/es/1.m4f',
map: {
uri: '63000/es/init.m4f',
resolvedUri: 'https://www.example.com/63000/es/init.m4f'
},
number: 1
},
{
uri: '63000/es/2.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/63000/es/2.m4f',
map: {
uri: '63000/es/init.m4f',
resolvedUri: 'https://www.example.com/63000/es/init.m4f'
},
number: 2
},
{
uri: '63000/es/3.m4f',
timeline: 0,
duration: 0.04800000000000004,
resolvedUri: 'https://www.example.com/63000/es/3.m4f',
map: {
uri: '63000/es/init.m4f',
resolvedUri: 'https://www.example.com/63000/es/init.m4f'
},
number: 3
}
],
mediaSequence: 0,
contentProtection: {
'com.widevine.alpha': {
attributes: {
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
},
pssh: new Uint8Array([181, 235, 45])
}
}
},
{
attributes: {
'NAME': '125000',
'BANDWIDTH': 125000,
'CODECS': 'mp4a.40.2',
'PROGRAM-ID': 1
},
uri: '',
endList: true,
timeline: 0,
resolvedUri: '',
targetDuration: 1.984,
segments: [
{
uri: '125000/es/0.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/125000/es/0.m4f',
map: {
uri: '125000/es/init.m4f',
resolvedUri: 'https://www.example.com/125000/es/init.m4f'
},
number: 0
},
{
uri: '125000/es/1.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/125000/es/1.m4f',
map: {
uri: '125000/es/init.m4f',
resolvedUri: 'https://www.example.com/125000/es/init.m4f'
},
number: 1
},
{
uri: '125000/es/2.m4f',
timeline: 0,
duration: 1.984,
resolvedUri: 'https://www.example.com/125000/es/2.m4f',
map: {
uri: '125000/es/init.m4f',
resolvedUri: 'https://www.example.com/125000/es/init.m4f'
},
number: 2
},
{
uri: '125000/es/3.m4f',
timeline: 0,
duration: 0.04800000000000004,
resolvedUri: 'https://www.example.com/125000/es/3.m4f',
map: {
uri: '125000/es/init.m4f',
resolvedUri: 'https://www.example.com/125000/es/init.m4f'
},
number: 3
}
],
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': {
subs: {
en: {
language: 'en',
default: false,
autoselect: false,
playlists: [
{
attributes: {
'NAME': 'en',
'BANDWIDTH': 256,
'PROGRAM-ID': 1,
'CODECS': 'stpp.ttml.im1t'
},
uri: '',
endList: true,
timeline: 0,
resolvedUri: 'https://example.com/en.dash',
targetDuration: 6,
segments: [
{
uri: 'https://example.com/en.dash',
timeline: 0,
resolvedUri: 'https://example.com/en.dash',
duration: 6,
number: 0
}
],
mediaSequence: 0
}
],
uri: ''
},
es: {
language: 'es',
default: false,
autoselect: false,
playlists: [
{
attributes: {
'NAME': 'es',
'BANDWIDTH': 256,
'PROGRAM-ID': 1
},
uri: '',
endList: true,
timeline: 0,
resolvedUri: 'https://example.com/es.vtt',
targetDuration: 6,
segments: [
{
uri: 'https://example.com/es.vtt',
timeline: 0,
resolvedUri: 'https://example.com/es.vtt',
duration: 6,
number: 0
}
],
mediaSequence: 0
}
],
uri: ''
}
}
}
},
uri: '',
duration: 6,
playlists: [
{
attributes: {
'NAME': '482',
'AUDIO': 'audio',
'SUBTITLES': 'subs',
'RESOLUTION': {
width: 482,
height: 270
},
'CODECS': 'avc1.420015',
'BANDWIDTH': 449000,
'PROGRAM-ID': 1
},
uri: '',
endList: true,
timeline: 0,
resolvedUri: '',
targetDuration: 1.9185833333333333,
segments: [
{
uri: '482/0.m4f',
timeline: 0,
duration: 1.9185833333333333,
resolvedUri: 'https://www.example.com/482/0.m4f',
map: {
uri: '482/init.m4f',
resolvedUri: 'https://www.example.com/482/init.m4f'
},
number: 0
},
{
uri: '482/1.m4f',
timeline: 0,
duration: 1.9185833333333333,
resolvedUri: 'https://www.example.com/482/1.m4f',
map: {
uri: '482/init.m4f',
resolvedUri: 'https://www.example.com/482/init.m4f'
},
number: 1
},
{
uri: '482/2.m4f',
timeline: 0,
duration: 1.9185833333333333,
resolvedUri: 'https://www.example.com/482/2.m4f',
map: {
uri: '482/init.m4f',
resolvedUri: 'https://www.example.com/482/init.m4f'
},
number: 2
},
{
uri: '482/3.m4f',
timeline: 0,
duration: 0.24425000000000008,
resolvedUri: 'https://www.example.com/482/3.m4f',
map: {
uri: '482/init.m4f',
resolvedUri: 'https://www.example.com/482/init.m4f'
},
number: 3
}
],
mediaSequence: 0,
contentProtection: {
'com.widevine.alpha': {
attributes: {
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
},
pssh: new Uint8Array([181, 235, 45])
}
}
},
{
attributes: {
'NAME': '720',
'AUDIO': 'audio',
'SUBTITLES': 'subs',
'RESOLUTION': {
width: 720,
height: 404
},
'CODECS': 'avc1.64001e',
'BANDWIDTH': 3971000,
'PROGRAM-ID': 1
},
uri: '',
endList: true,
timeline: 0,
resolvedUri: '',
targetDuration: 1.9185833333333333,
segments: [
{
uri: '720/0.m4f',
timeline: 0,
duration: 1.9185833333333333,
resolvedUri: 'https://www.example.com/720/0.m4f',
map: {
uri: '720/init.m4f',
resolvedUri: 'https://www.example.com/720/init.m4f'
},
number: 0
},
{
uri: '720/1.m4f',
timeline: 0,
duration: 1.9185833333333333,
resolvedUri: 'https://www.example.com/720/1.m4f',
map: {
uri: '720/init.m4f',
resolvedUri: 'https://www.example.com/720/init.m4f'
},
number: 1
},
{
uri: '720/2.m4f',
timeline: 0,
duration: 1.9185833333333333,
resolvedUri: 'https://www.example.com/720/2.m4f',
map: {
uri: '720/init.m4f',
resolvedUri: 'https://www.example.com/720/init.m4f'
},
number: 2
},
{
uri: '720/3.m4f',
timeline: 0,
duration: 0.24425000000000008,
resolvedUri: 'https://www.example.com/720/3.m4f',
map: {
uri: '720/init.m4f',
resolvedUri: 'https://www.example.com/720/init.m4f'
},
number: 3
}
],
mediaSequence: 0,
contentProtection: {
'com.widevine.alpha': {
attributes: {
schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
},
pssh: new Uint8Array([181, 235, 45])
}
}
}
]
};

60
node_modules/mpd-parser/test/manifests/vtt_codecs.mpd generated vendored Normal file
View file

@ -0,0 +1,60 @@
<?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 contentType="text" mimeType="application/mp4" lang="en" codecs="stpp.ttml.im1t">
<Representation bandwidth="256" id="en">
<BaseURL>https://example.com/en.dash</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>

153
node_modules/mpd-parser/test/manifests/webmsegments.js generated vendored Normal file
View file

@ -0,0 +1,153 @@
export const parsedManifest = {
allowCache: true,
discontinuityStarts: [],
segments: [],
endList: true,
mediaGroups: {
'AUDIO': {
audio: {
en: {
language: 'en',
autoselect: true,
default: true,
playlists: [
{
attributes: {
'NAME': '2',
'BANDWIDTH': 32000,
'CODECS': 'opus',
'PROGRAM-ID': 1
},
uri: '',
endList: true,
timeline: 1,
resolvedUri: '',
targetDuration: 4,
segments: [
{
uri: 'audio/segment_0.chk',
timeline: 1,
duration: 4,
resolvedUri: 'https://www.example.com/audio/segment_0.chk',
map: {
uri: 'audio/init.hdr',
resolvedUri: 'https://www.example.com/audio/init.hdr'
},
number: 0
},
{
uri: 'audio/segment_1.chk',
timeline: 1,
duration: 4,
resolvedUri: 'https://www.example.com/audio/segment_1.chk',
map: {
uri: 'audio/init.hdr',
resolvedUri: 'https://www.example.com/audio/init.hdr'
},
number: 1
},
{
uri: 'audio/segment_2.chk',
timeline: 1,
duration: 4,
resolvedUri: 'https://www.example.com/audio/segment_2.chk',
map: {
uri: 'audio/init.hdr',
resolvedUri: 'https://www.example.com/audio/init.hdr'
},
number: 2
},
{
uri: 'audio/segment_3.chk',
timeline: 1,
duration: 4,
resolvedUri: 'https://www.example.com/audio/segment_3.chk',
map: {
uri: 'audio/init.hdr',
resolvedUri: 'https://www.example.com/audio/init.hdr'
},
number: 3
}
],
mediaSequence: 0
}
],
uri: ''
}
}
},
'VIDEO': {},
'CLOSED-CAPTIONS': {},
'SUBTITLES': {}
},
uri: '',
duration: 16,
playlists: [
{
attributes: {
'NAME': '1',
'AUDIO': 'audio',
'SUBTITLES': 'subs',
'RESOLUTION': {
width: 480,
height: 200
},
'CODECS': 'av1',
'BANDWIDTH': 100000,
'PROGRAM-ID': 1
},
uri: '',
endList: true,
timeline: 1,
resolvedUri: '',
targetDuration: 4,
segments: [
{
uri: 'video/segment_0.chk',
timeline: 1,
duration: 4,
resolvedUri: 'https://www.example.com/video/segment_0.chk',
map: {
uri: 'video/init.hdr',
resolvedUri: 'https://www.example.com/video/init.hdr'
},
number: 0
},
{
uri: 'video/segment_1.chk',
timeline: 1,
duration: 4,
resolvedUri: 'https://www.example.com/video/segment_1.chk',
map: {
uri: 'video/init.hdr',
resolvedUri: 'https://www.example.com/video/init.hdr'
},
number: 1
},
{
uri: 'video/segment_2.chk',
timeline: 1,
duration: 4,
resolvedUri: 'https://www.example.com/video/segment_2.chk',
map: {
uri: 'video/init.hdr',
resolvedUri: 'https://www.example.com/video/init.hdr'
},
number: 2
},
{
uri: 'video/segment_3.chk',
timeline: 1,
duration: 4,
resolvedUri: 'https://www.example.com/video/segment_3.chk',
map: {
uri: 'video/init.hdr',
resolvedUri: 'https://www.example.com/video/init.hdr'
},
number: 3
}
],
mediaSequence: 0
}
]
};

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MPD id="a467fa27-2820-41d1-89e2-a43216770daa" profiles="urn:mpeg:dash:profile:full:2011" type="static"
mediaPresentationDuration="P0Y0M0DT0H0M16S" minBufferTime="P0Y0M0DT0H0M2.000S"
xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:ns2="http://www.w3.org/1999/xlink">
<Period id="1" start="P0Y0M0DT0H0M0.000S">
<BaseURL>https://www.example.com/base</BaseURL>
<AdaptationSet mimeType="video/webm">
<Representation id="1" bandwidth="100000" width="480" height="200" frameRate="24" codecs="av1">
<SegmentTemplate media="video/segment_$Number$.chk" initialization="video/init.hdr" duration="96000"
startNumber="0" timescale="24000"/>
</Representation>
</AdaptationSet>
<AdaptationSet lang="en" mimeType="audio/webm">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<Representation id="2" bandwidth="32000" audioSamplingRate="48000" codecs="opus">
<SegmentTemplate media="audio/segment_$Number$.chk" initialization="audio/init.hdr" duration="192000"
startNumber="0" timescale="48000"/>
</Representation>
</AdaptationSet>
</Period>
</MPD>

21
node_modules/mpd-parser/test/parseAttributes.test.js generated vendored Normal file
View file

@ -0,0 +1,21 @@
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), {});
});

View file

@ -0,0 +1,201 @@
import QUnit from 'qunit';
import {
segmentsFromBase,
addSidxSegmentsToPlaylist
} 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 - addSidxSegmentsToPlaylist');
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(addSidxSegmentsToPlaylist(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
}]);
});

View file

@ -0,0 +1,553 @@
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
}]);
});

File diff suppressed because it is too large Load diff

94
node_modules/mpd-parser/test/segment/urlType.test.js generated vendored Normal file
View file

@ -0,0 +1,94 @@
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
node_modules/mpd-parser/test/stringToMpdXml.test.js generated vendored Normal file
View file

@ -0,0 +1,21 @@
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));
});

935
node_modules/mpd-parser/test/toM3u8.test.js generated vendored Normal file
View file

@ -0,0 +1,935 @@
import { toM3u8, generateSidxKey } 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
}, {
attributes: {
BANDWIDTH: 10000,
CODECS: 'foo;bar',
NAME: '2',
['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: ''
}, {
attributes: {
BANDWIDTH: 10000,
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: '2',
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: ''
}, {
attributes: {
BANDWIDTH: 10000,
CODECS: 'foo;bar',
NAME: '2',
['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: ''
}, {
attributes: {
BANDWIDTH: 10000,
NAME: '2',
['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);
});
QUnit.test('playlists with label', function(assert) {
const label = 'English with commentary';
const input = [{
attributes: {
id: '1',
codecs: 'foo;bar',
sourceDuration: 100,
duration: 0,
bandwidth: 20000,
periodIndex: 1,
mimeType: 'audio/mp4',
type: 'dynamic',
label
},
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: []
}];
const output = toM3u8(input);
assert.ok(label in output.mediaGroups.AUDIO.audio, 'label exists');
});
QUnit.test('608 captions', function(assert) {
const input = [{
attributes: {
captionServices: [{
channel: 'CC1',
language: 'CC1'
}, {
channel: 'CC2',
language: 'CC2'
}, {
channel: undefined,
language: 'English'
}, {
channel: 'CC4',
language: 'eng'
}],
id: '1',
codecs: 'foo;bar',
sourceDuration: 100,
duration: 0,
bandwidth: 20000,
periodIndex: 1,
mimeType: 'audio/mp4',
type: 'dynamic'
},
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: []
}];
const output = toM3u8(input);
const cc = output.mediaGroups['CLOSED-CAPTIONS'].cc;
Object.keys(cc).forEach((key) => {
assert.notOk(cc[key].autoselect, 'no autoselect');
assert.notOk(cc[key].default, 'no default');
});
assert.deepEqual(Object.keys(cc), ['CC1', 'CC2', 'English', 'eng'], 'we have 4 channels');
assert.equal(cc.CC1.instreamId, 'CC1', 'CC1 has an instreamId of CC1');
assert.equal(cc.CC2.instreamId, 'CC2', 'CC2 has an instreamId of CC1');
assert.equal(cc.English.instreamId, undefined, 'English captions dont have an instreamId');
assert.equal(cc.eng.instreamId, 'CC4', 'eng captions have an instreamId of CC4');
});
QUnit.module('generateSidxKey');
QUnit.test('generates correct key', function(assert) {
const sidxInfo = {
byterange: {
offset: 1,
length: 5
},
uri: 'uri'
};
assert.strictEqual(
generateSidxKey(sidxInfo),
'uri-1-5',
'the key byterange should have a inclusive end'
);
});

211
node_modules/mpd-parser/test/toPlaylists.test.js generated vendored Normal file
View file

@ -0,0 +1,211 @@
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);
});
QUnit.test('presentationTimeOffset', function(assert) {
const representations = [{
attributes: { baseUrl: 'http://example.com/', periodIndex: 0, sourceDuration: 2 },
segmentInfo: {
template: {
presentationTimeOffset: 100,
timescale: 4
}
}
}];
// the presentationTimeOffset output should be the value in the template
// divided by the timescale in the template.
// It should be available on segments
const playlists = [{
attributes: {
baseUrl: 'http://example.com/',
periodIndex: 0,
sourceDuration: 2,
duration: 2,
presentationTimeOffset: 25,
timescale: 4
},
segments: [{
uri: '',
timeline: 0,
duration: 2,
presentationTimeOffset: 25,
resolvedUri: 'http://example.com/',
map: {
uri: '',
resolvedUri: 'http://example.com/'
},
number: 1
}]
}];
assert.deepEqual(toPlaylists(representations), playlists);
});

219
node_modules/mpd-parser/test/utils.test.js generated vendored Normal file
View file

@ -0,0 +1,219 @@
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');
});