1
0
Fork 0
mirror of https://github.com/DanielnetoDotCom/YouPHPTube synced 2025-10-05 19:42:38 +02:00
Daniel Neto 2023-06-30 08:55:17 -03:00
parent 746e163d01
commit 1c7ea28b46
808 changed files with 316395 additions and 381162 deletions

32
node_modules/mpd-parser/CHANGELOG.md generated vendored
View file

@ -1,5 +1,24 @@
<a name="0.22.1"></a>
## [0.22.1](https://github.com/videojs/mpd-parser/compare/v0.21.1...v0.22.1) (2022-10-14)
<a name="1.1.1"></a>
## [1.1.1](https://github.com/videojs/mpd-parser/compare/v1.1.0...v1.1.1) (2023-03-31)
### Bug Fixes
* get event tag content ([ed7a1d7](https://github.com/videojs/mpd-parser/commit/ed7a1d7))
<a name="1.1.0"></a>
# [1.1.0](https://github.com/videojs/mpd-parser/compare/v1.0.0...v1.1.0) (2023-03-20)
### Features
* add EventStream support ([f1a09ca](https://github.com/videojs/mpd-parser/commit/f1a09ca))
* set label for vttPlaylist from label when available ([#161](https://github.com/videojs/mpd-parser/issues/161)) ([3fc0486](https://github.com/videojs/mpd-parser/commit/3fc0486))
### Chores
* update xmldom dependency ([cfcb568](https://github.com/videojs/mpd-parser/commit/cfcb568))
<a name="1.0.0"></a>
# [1.0.0](https://github.com/videojs/mpd-parser/compare/v0.21.1...v1.0.0) (2022-08-19)
### Features
@ -7,14 +26,13 @@
### Chores
* update xmldom dependency [0.x] ([fceb6b9](https://github.com/videojs/mpd-parser/commit/fceb6b9))
* do not run es-check on publish ([#162](https://github.com/videojs/mpd-parser/issues/162)) ([f92659d](https://github.com/videojs/mpd-parser/commit/f92659d))
* remove IE11 support ([#160](https://github.com/videojs/mpd-parser/issues/160)) ([b528b61](https://github.com/videojs/mpd-parser/commit/b528b61))
<a name="0.22.0"></a>
# [0.22.0](https://github.com/videojs/mpd-parser/compare/v0.21.1...v0.22.0) (2022-09-09)
### Features
### BREAKING CHANGES
* add support for a frame-rate attribute ([#159](https://github.com/videojs/mpd-parser/issues/159)) ([cd75be1](https://github.com/videojs/mpd-parser/commit/cd75be1))
* Internet Explorer is no longer supported.
<a name="0.21.1"></a>
## [0.21.1](https://github.com/videojs/mpd-parser/compare/v0.21.0...v0.21.1) (2022-04-05)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

14
node_modules/mpd-parser/package.json generated vendored
View file

@ -1,6 +1,6 @@
{
"name": "mpd-parser",
"version": "0.22.1",
"version": "1.1.1",
"description": "mpd parser",
"main": "dist/mpd-parser.cjs.js",
"module": "dist/mpd-parser.es.js",
@ -20,7 +20,7 @@
"build:js": "rollup -c scripts/rollup.config.js",
"clean": "shx rm -rf ./dist ./test/dist && shx mkdir -p ./dist ./test/dist",
"lint": "vjsstandard",
"prepublishOnly": "npm-run-all build-prod && vjsverify --verbose",
"prepublishOnly": "npm-run-all build-prod && vjsverify --verbose --skip-es-check",
"start": "npm-run-all -p server watch",
"server": "karma start scripts/karma.conf.js --singleRun=false --auto-watch",
"test": "npm-run-all lint build-test && npm-run-all test:*",
@ -65,21 +65,17 @@
"@videojs/generator-helpers": "~2.0.1",
"jsdom": "^16.4.0",
"karma": "^5.2.3",
"rollup": "^2.36.1",
"rollup": "^2.38.0",
"rollup-plugin-string": "^3.0.0",
"sinon": "^9.2.3",
"videojs-generate-karma-config": "~7.0.0",
"videojs-generate-rollup-config": "^6.2.2",
"videojs-generate-karma-config": "^8.0.1",
"videojs-generate-rollup-config": "~7.0.0",
"videojs-generator-verify": "~3.0.2",
"videojs-standard": "^9.0.1"
},
"generator-videojs-plugin": {
"version": "7.7.3"
},
"browserslist": [
"defaults",
"ie 11"
],
"lint-staged": {
"*.js": "vjsstandard --fix",
"README.md": "doctoc --notitle"

View file

@ -29,7 +29,8 @@ const parse = (manifestString, options = {}) => {
dashPlaylists: playlists,
locations: parsedManifestInfo.locations,
sidxMapping: options.sidxMapping,
previousManifest: options.previousManifest
previousManifest: options.previousManifest,
eventStream: parsedManifestInfo.eventStream
});
};

View file

@ -287,6 +287,42 @@ export const parseCaptionServiceMetadata = (service) => {
}
};
/**
* A map callback that will parse all event stream data for a collection of periods
* DASH ISO_IEC_23009 5.10.2.2
* https://dashif-documents.azurewebsites.net/Events/master/event.html#mpd-event-timing
*
* @param {PeriodInformation} period object containing necessary period information
* @return a collection of parsed eventstream event objects
*/
export const toEventStream = (period) => {
// get and flatten all EventStreams tags and parse attributes and children
return flatten(findChildren(period.node, 'EventStream').map((eventStream) => {
const eventStreamAttributes = parseAttributes(eventStream);
const schemeIdUri = eventStreamAttributes.schemeIdUri;
// find all Events per EventStream tag and map to return objects
return findChildren(eventStream, 'Event').map((event) => {
const eventAttributes = parseAttributes(event);
const presentationTime = eventAttributes.presentationTime || 0;
const timescale = eventStreamAttributes.timescale || 1;
const duration = eventAttributes.duration || 0;
const start = (presentationTime / timescale) + period.attributes.start;
return {
schemeIdUri,
value: eventStreamAttributes.value,
id: eventAttributes.id,
start,
end: start + (duration / timescale),
messageData: getContent(event) || eventAttributes.messageData,
contentEncoding: eventStreamAttributes.contentEncoding,
presentationTimeOffset: eventStreamAttributes.presentationTimeOffset || 0
};
});
}));
};
/**
* Maps an AdaptationSet node to a list of Representation information objects
*
@ -531,6 +567,7 @@ export const inheritAttributes = (mpd, options = {}) => {
return {
locations: mpdAttributes.locations,
representationInfo: flatten(periods.map(toAdaptationSets(mpdAttributes, mpdBaseUrls)))
representationInfo: flatten(periods.map(toAdaptationSets(mpdAttributes, mpdBaseUrls))),
eventStream: flatten(periods.map(toEventStream))
};
};

View file

@ -241,6 +241,19 @@ export const parsers = {
return parseInt(value, 10);
},
/**
* Specifies the presentationTime.
*
* @param {string} value
* value of the attribute as a string
*
* @return {number}
* The parsed presentationTime
*/
presentationTime(value) {
return parseInt(value, 10);
},
/**
* Default parser for all other attributes. Acts as a no-op and just returns the value
* as a string

View file

@ -1,5 +1,5 @@
import { forEachMediaGroup } from '@videojs/vhs-utils/es/media-groups';
import { findIndex, union } from './utils/list';
import { union } from './utils/list';
const SUPPORTED_MEDIA_TYPES = ['AUDIO', 'SUBTITLES'];
// allow one 60fps frame as leniency (arbitrarily chosen)
@ -82,10 +82,11 @@ export const updateMediaSequenceForPlaylist = ({ playlist, mediaSequence }) => {
*/
export const updateSequenceNumbers = ({ oldPlaylists, newPlaylists, timelineStarts }) => {
newPlaylists.forEach((playlist) => {
playlist.discontinuitySequence = findIndex(
timelineStarts,
({ timeline }) => timeline === playlist.timeline
);
playlist.discontinuitySequence = timelineStarts.findIndex(function({
timeline
}) {
return timeline === playlist.timeline;
});
// Playlists NAMEs come from DASH Representation IDs, which are mandatory
// (see ISO_23009-1-2012 5.3.5.2).
@ -116,9 +117,11 @@ export const updateSequenceNumbers = ({ oldPlaylists, newPlaylists, timelineStar
// Since we don't yet support early available timelines, we don't need to support
// playlists with no segments.
const firstNewSegment = playlist.segments[0];
const oldMatchingSegmentIndex = findIndex(oldPlaylist.segments, (oldSegment) =>
Math.abs(oldSegment.presentationTime - firstNewSegment.presentationTime) <
TIME_FUDGE);
const oldMatchingSegmentIndex = oldPlaylist.segments.findIndex(function(oldSegment) {
return (
Math.abs(oldSegment.presentationTime - firstNewSegment.presentationTime) < TIME_FUDGE
);
});
// No matching segment from the old playlist means the entire playlist was refreshed.
// In this case the media sequence should account for this update, and the new segments

View file

@ -1,5 +1,5 @@
import { values } from './utils/object';
import { findIndex, findIndexes } from './utils/list';
import { findIndexes } from './utils/list';
import { addSidxSegmentsToPlaylist as addSidxSegmentsToPlaylist_ } from './segment/segmentBase';
import { byteRangeToString } from './segment/urlType';
import {
@ -217,7 +217,7 @@ export const organizeAudioPlaylists = (playlists, sidxMapping = {}, isAudioOnly
export const organizeVttPlaylists = (playlists, sidxMapping = {}) => {
return playlists.reduce((a, playlist) => {
const label = playlist.attributes.lang || 'text';
const label = playlist.attributes.label || playlist.attributes.lang || 'text';
if (!a[label]) {
a[label] = {
@ -352,7 +352,11 @@ export const addMediaSequenceValues = (playlists, timelineStarts) => {
// increment all segments sequentially
playlists.forEach((playlist) => {
playlist.mediaSequence = 0;
playlist.discontinuitySequence = findIndex(timelineStarts, ({ timeline }) => timeline === playlist.timeline);
playlist.discontinuitySequence = timelineStarts.findIndex(function({
timeline
}) {
return timeline === playlist.timeline;
});
if (!playlist.segments) {
return;
@ -389,7 +393,8 @@ export const toM3u8 = ({
dashPlaylists,
locations,
sidxMapping = {},
previousManifest
previousManifest,
eventStream
}) => {
if (!dashPlaylists.length) {
return {};
@ -436,6 +441,10 @@ export const toM3u8 = ({
manifest.suggestedPresentationDelay = suggestedPresentationDelay;
}
if (eventStream && eventStream.length > 0) {
manifest.eventStream = eventStream;
}
const isAudioOnly = manifest.playlists.length === 0;
const organizedAudioGroup = audioPlaylists.length ?
organizeAudioPlaylists(audioPlaylists, sidxMapping, isAudioOnly) : null;

View file

@ -34,40 +34,6 @@ export const findIndexes = (l, key) => l.reduce((a, e, i) => {
return a;
}, []);
/**
* Returns the first index that satisfies the matching function, or -1 if not found.
*
* Only necessary because of IE11 support.
*
* @param {Array} list - the list to search through
* @param {Function} matchingFunction - the matching function
*
* @return {number} the matching index or -1 if not found
*/
export const findIndex = (list, matchingFunction) => {
for (let i = 0; i < list.length; i++) {
if (matchingFunction(list[i])) {
return i;
}
}
return -1;
};
/**
* Returns whether the list contains the search element.
*
* Only necessary because of IE11 support.
*
* @param {Array} list - the list to search through
* @param {*} searchElement - the element to look for
*
* @return {boolean} whether the list includes the search element or not
*/
export const includes = (list, searchElement) => {
return list.some((element) => element === searchElement);
};
/**
* Returns a union of the included lists provided each element can be identified by a key.
*

View file

@ -3,13 +3,15 @@ import {
buildBaseUrls,
parseCaptionServiceMetadata,
getSegmentInformation,
getPeriodStart
getPeriodStart,
toEventStream
} from '../src/inheritAttributes';
import { stringToMpdXml } from '../src/stringToMpdXml';
import errors from '../src/errors';
import QUnit from 'qunit';
import { toPlaylists } from '../src/toPlaylists';
import decodeB64ToUint8Array from '@videojs/vhs-utils/es/decode-b64-to-uint8-array';
import { findChildren } from '../src/utils/xml';
QUnit.module('buildBaseUrls');
@ -544,6 +546,7 @@ QUnit.test('end to end - basic', function(assert) {
`), { NOW });
const expected = {
eventStream: [],
locations: undefined,
representationInfo: [{
attributes: {
@ -618,6 +621,7 @@ QUnit.test('end to end - basic dynamic', function(assert) {
`), { NOW });
const expected = {
eventStream: [],
locations: undefined,
representationInfo: [{
attributes: {
@ -699,6 +703,7 @@ QUnit.test('end to end - basic multiperiod', function(assert) {
`), { NOW });
const expected = {
eventStream: [],
locations: undefined,
representationInfo: [{
attributes: {
@ -785,6 +790,7 @@ QUnit.test('end to end - inherits BaseURL from all levels', function(assert) {
`), { NOW });
const expected = {
eventStream: [],
locations: undefined,
representationInfo: [{
attributes: {
@ -861,6 +867,7 @@ QUnit.test('end to end - alternate BaseURLs', function(assert) {
`), { NOW });
const expected = {
eventStream: [],
locations: undefined,
representationInfo: [{
attributes: {
@ -1028,6 +1035,7 @@ QUnit.test(
`), { NOW });
const expected = {
eventStream: [],
locations: undefined,
representationInfo: [{
attributes: {
@ -1140,6 +1148,7 @@ QUnit.test(
`), { NOW });
const expected = {
eventStream: [],
locations: undefined,
representationInfo: [{
attributes: {
@ -1263,6 +1272,7 @@ QUnit.test(
`), { NOW });
const expected = {
eventStream: [],
locations: undefined,
representationInfo: [{
attributes: {
@ -2106,6 +2116,7 @@ QUnit.test('keySystem info for representation - lowercase UUIDs', function(asser
// inconsistent quoting because of quote-props
const expected = {
eventStream: [],
locations: undefined,
representationInfo: [{
attributes: {
@ -2192,6 +2203,7 @@ QUnit.test('keySystem info for representation - uppercase UUIDs', function(asser
// inconsistent quoting because of quote-props
const expected = {
eventStream: [],
locations: undefined,
representationInfo: [{
attributes: {
@ -2238,3 +2250,274 @@ QUnit.test('keySystem info for representation - uppercase UUIDs', function(asser
assert.equal(actual.representationInfo.length, 1);
assert.deepEqual(actual, expected);
});
QUnit.test('gets EventStream data from toEventStream', function(assert) {
const mpd = stringToMpdXml(`
<MPD mediaPresentationDuration="PT30S" xmlns:cenc="urn:mpeg:cenc:2013">
<Period id="dai_pod-0001065804-ad-1" start="PT17738H17M14.156S" duration="PT9.977S">
<BaseURL>https://www.example.com/base/</BaseURL>
<SegmentTemplate media="$RepresentationID$/$Number$.mp4" initialization="$RepresentationID$/init.mp4"/>
<EventStream schemeIdUri="urn:google:dai:2018" timescale="1000" contentEncoding="foo" presentationTimeOffset="1">
<Event presentationTime="100" duration="0" id="0" messageData="foo"/>
<Event presentationTime="900" duration="0" id="5" messageData="bar"/>
<Event presentationTime="1900" duration="0" id="6" messageData="foo_bar"/>
</EventStream>
</Period>
</MPD>`);
const expected = [
{
end: 2.1,
id: '0',
messageData: 'foo',
schemeIdUri: 'urn:google:dai:2018',
start: 2.1,
value: undefined,
contentEncoding: 'foo',
presentationTimeOffset: 1
},
{
end: 2.9,
id: '5',
messageData: 'bar',
schemeIdUri: 'urn:google:dai:2018',
start: 2.9,
value: undefined,
contentEncoding: 'foo',
presentationTimeOffset: 1
},
{
end: 3.9,
id: '6',
messageData: 'foo_bar',
schemeIdUri: 'urn:google:dai:2018',
start: 3.9,
value: undefined,
contentEncoding: 'foo',
presentationTimeOffset: 1
}
];
const firstPeriod = { node: findChildren(mpd, 'Period')[0], attributes: { start: 2 } };
const eventStreams = toEventStream(firstPeriod);
assert.deepEqual(eventStreams, expected, 'toEventStream returns the expected object');
});
QUnit.test('can get EventStream data from toEventStream with no schemeIdUri', function(assert) {
const mpd = stringToMpdXml(`
<MPD mediaPresentationDuration="PT30S" xmlns:cenc="urn:mpeg:cenc:2013">
<Period id="dai_pod-0001065804-ad-1" start="PT17738H17M14.156S" duration="PT9.977S">
<BaseURL>https://www.example.com/base/</BaseURL>
<SegmentTemplate media="$RepresentationID$/$Number$.mp4" initialization="$RepresentationID$/init.mp4"/>
<EventStream timescale="1000">
<Event presentationTime="100" duration="0" id="0" messageData="foo"/>
<Event presentationTime="900" duration="0" id="5" messageData="bar"/>
<Event presentationTime="1900" duration="0" id="6" messageData="foo_bar"/>
</EventStream>
</Period>
</MPD>`);
const expected = [
{
end: 2.1,
id: '0',
messageData: 'foo',
schemeIdUri: undefined,
start: 2.1,
value: undefined,
contentEncoding: undefined,
presentationTimeOffset: 0
},
{
end: 2.9,
id: '5',
messageData: 'bar',
schemeIdUri: undefined,
start: 2.9,
value: undefined,
contentEncoding: undefined,
presentationTimeOffset: 0
},
{
end: 3.9,
id: '6',
messageData: 'foo_bar',
schemeIdUri: undefined,
start: 3.9,
value: undefined,
contentEncoding: undefined,
presentationTimeOffset: 0
}
];
const firstPeriod = { node: findChildren(mpd, 'Period')[0], attributes: { start: 2} };
const eventStreams = toEventStream(firstPeriod);
assert.deepEqual(eventStreams, expected, 'toEventStream returns the expected object');
});
QUnit.test('gets eventStream from inheritAttributes', function(assert) {
const mpd = stringToMpdXml(`
<MPD mediaPresentationDuration="PT30S" xmlns:cenc="urn:mpeg:cenc:2013">
<Period id="dai_pod-0001065804-ad-1" start="PT0H0M14.9S" duration="PT9.977S">
<BaseURL>https://www.example.com/base/</BaseURL>
<SegmentTemplate media="$RepresentationID$/$Number$.mp4" initialization="$RepresentationID$/init.mp4"/>
<EventStream schemeIdUri="urn:google:dai:2018" timescale="1000" value="foo">
<Event presentationTime="100" duration="0" id="0" messageData="foo"/>
<Event presentationTime="1100" duration="0" id="5" messageData="bar"/>
<Event presentationTime="2100" duration="0" id="6" messageData="foo_bar"/>
</EventStream>
</Period>
</MPD>`);
const expected = {
eventStream: [
{
end: 15,
id: '0',
messageData: 'foo',
schemeIdUri: 'urn:google:dai:2018',
start: 15,
value: 'foo',
contentEncoding: undefined,
presentationTimeOffset: 0
},
{
end: 16,
id: '5',
messageData: 'bar',
schemeIdUri: 'urn:google:dai:2018',
start: 16,
value: 'foo',
contentEncoding: undefined,
presentationTimeOffset: 0
},
{
end: 17,
id: '6',
messageData: 'foo_bar',
schemeIdUri: 'urn:google:dai:2018',
start: 17,
value: 'foo',
contentEncoding: undefined,
presentationTimeOffset: 0
}
],
locations: undefined,
representationInfo: []
};
const eventStreams = inheritAttributes(mpd);
assert.deepEqual(eventStreams, expected, 'inheritAttributes returns the expected object');
});
QUnit.test('can get EventStream data from toEventStream with data in Event tags', function(assert) {
const mpd = stringToMpdXml(`
<MPD mediaPresentationDuration="PT30S" xmlns:cenc="urn:mpeg:cenc:2013">
<Period id="dai_pod-0001065804-ad-1" start="PT17738H17M14.156S" duration="PT9.977S">
<BaseURL>https://www.example.com/base/</BaseURL>
<SegmentTemplate media="$RepresentationID$/$Number$.mp4" initialization="$RepresentationID$/init.mp4"/>
<EventStream timescale="1000">
<Event presentationTime="100" duration="0" id="0">foo</Event>
<Event presentationTime="900" duration="0" id="5">bar</Event>
<Event presentationTime="1900" duration="0" id="6">foo_bar</Event>
</EventStream>
</Period>
</MPD>`);
const expected = [
{
end: 2.1,
id: '0',
messageData: 'foo',
schemeIdUri: undefined,
start: 2.1,
value: undefined,
contentEncoding: undefined,
presentationTimeOffset: 0
},
{
end: 2.9,
id: '5',
messageData: 'bar',
schemeIdUri: undefined,
start: 2.9,
value: undefined,
contentEncoding: undefined,
presentationTimeOffset: 0
},
{
end: 3.9,
id: '6',
messageData: 'foo_bar',
schemeIdUri: undefined,
start: 3.9,
value: undefined,
contentEncoding: undefined,
presentationTimeOffset: 0
}
];
const firstPeriod = { node: findChildren(mpd, 'Period')[0], attributes: { start: 2} };
const eventStreams = toEventStream(firstPeriod);
assert.deepEqual(eventStreams, expected, 'toEventStream returns the expected object');
});
QUnit.test('gets eventStream from inheritAttributes with data in Event tags', function(assert) {
const mpd = stringToMpdXml(`
<MPD mediaPresentationDuration="PT30S" xmlns:cenc="urn:mpeg:cenc:2013">
<Period id="dai_pod-0001065804-ad-1" start="PT0H0M14.9S" duration="PT9.977S">
<BaseURL>https://www.example.com/base/</BaseURL>
<SegmentTemplate media="$RepresentationID$/$Number$.mp4" initialization="$RepresentationID$/init.mp4"/>
<EventStream schemeIdUri="urn:google:dai:2018" timescale="1000" value="foo">
<Event presentationTime="100" duration="0" id="0">foo</Event>
<Event presentationTime="1100" duration="0" id="5">bar</Event>
<Event presentationTime="2100" duration="0" id="6">foo_bar</Event>
</EventStream>
</Period>
</MPD>`);
const expected = {
eventStream: [
{
end: 15,
id: '0',
messageData: 'foo',
schemeIdUri: 'urn:google:dai:2018',
start: 15,
value: 'foo',
contentEncoding: undefined,
presentationTimeOffset: 0
},
{
end: 16,
id: '5',
messageData: 'bar',
schemeIdUri: 'urn:google:dai:2018',
start: 16,
value: 'foo',
contentEncoding: undefined,
presentationTimeOffset: 0
},
{
end: 17,
id: '6',
messageData: 'foo_bar',
schemeIdUri: 'urn:google:dai:2018',
start: 17,
value: 'foo',
contentEncoding: undefined,
presentationTimeOffset: 0
}
],
locations: undefined,
representationInfo: []
};
const eventStreams = inheritAttributes(mpd);
assert.deepEqual(eventStreams, expected, 'inheritAttributes returns the expected object');
});

View file

@ -911,10 +911,27 @@ QUnit.test('playlists with label', function(assert) {
type: 'static'
},
segments: []
}, {
attributes: {
sourceDuration: 100,
id: '1',
width: 800,
height: 600,
codecs: 'foo;bar',
duration: 0,
bandwidth: 10000,
periodStart: 0,
mimeType: 'text/vtt',
type: 'static',
label
},
segments: []
}];
const output = toM3u8({ dashPlaylists });
assert.ok(label in output.mediaGroups.AUDIO.audio, 'label exists');
assert.ok(label in output.mediaGroups.SUBTITLES.subs, 'label exists');
});
QUnit.test('608 captions', function(assert) {
@ -1114,3 +1131,263 @@ QUnit.test('includes all media group playlists', function(assert) {
'included all media group playlists'
);
});
QUnit.module('eventStream');
QUnit.test('eventStreams with playlists', function(assert) {
const dashPlaylists = [{
attributes: {
id: '1',
codecs: 'foo;bar',
sourceDuration: 100,
duration: 0,
bandwidth: 20000,
periodStart: 0,
mimeType: 'audio/mp4',
type: 'static'
},
segments: []
}, {
attributes: {
id: '2',
codecs: 'foo;bar',
sourceDuration: 100,
duration: 0,
bandwidth: 10000,
periodStart: 0,
mimeType: 'audio/mp4',
type: 'static'
},
segments: []
}, {
attributes: {
sourceDuration: 100,
id: '1',
width: 800,
height: 600,
codecs: 'foo;bar',
duration: 0,
bandwidth: 10000,
frameRate: 30,
periodStart: 0,
mimeType: 'video/mp4',
type: 'static'
},
segments: []
}, {
attributes: {
sourceDuration: 100,
id: '1',
bandwidth: 20000,
periodStart: 0,
mimeType: 'text/vtt',
type: 'static',
baseUrl: 'https://www.example.com/vtt'
}
}, {
attributes: {
sourceDuration: 100,
id: '2',
bandwidth: 10000,
periodStart: 0,
mimeType: 'text/vtt',
type: 'static',
baseUrl: 'https://www.example.com/vtt'
}
}];
const eventStream = [
{
end: 1,
id: 'one',
messageData: 'foo',
schemeIdUri: 'urn:foo.bar.2023',
start: 1,
value: 'bar'
},
{
end: 2,
id: 'two',
messageData: 'bar',
schemeIdUri: 'urn:foo.bar.2023',
start: 2,
value: 'foo'
},
{
end: 3,
id: 'three',
messageData: 'foo_bar',
schemeIdUri: 'urn:foo.bar.2023',
start: 3,
value: 'bar_foo'
}
];
const expected = {
allowCache: true,
discontinuityStarts: [],
timelineStarts: [{ start: 0, timeline: 0 }],
duration: 100,
endList: true,
eventStream: [
{
end: 1,
id: 'one',
messageData: 'foo',
schemeIdUri: 'urn:foo.bar.2023',
start: 1,
value: 'bar'
},
{
end: 2,
id: 'two',
messageData: 'bar',
schemeIdUri: 'urn:foo.bar.2023',
start: 2,
value: 'foo'
},
{
end: 3,
id: 'three',
messageData: 'foo_bar',
schemeIdUri: 'urn:foo.bar.2023',
start: 3,
value: 'bar_foo'
}
],
mediaGroups: {
AUDIO: {
audio: {
main: {
autoselect: true,
default: true,
language: '',
playlists: [{
attributes: {
BANDWIDTH: 20000,
CODECS: 'foo;bar',
NAME: '1',
['PROGRAM-ID']: 1
},
mediaSequence: 0,
discontinuitySequence: 0,
discontinuityStarts: [],
timelineStarts: [{ start: 0, timeline: 0 }],
endList: true,
resolvedUri: '',
segments: [],
timeline: 0,
uri: '',
targetDuration: 0
}, {
attributes: {
BANDWIDTH: 10000,
CODECS: 'foo;bar',
NAME: '2',
['PROGRAM-ID']: 1
},
mediaSequence: 0,
discontinuitySequence: 0,
discontinuityStarts: [],
timelineStarts: [{ start: 0, timeline: 0 }],
endList: true,
resolvedUri: '',
segments: [],
timeline: 0,
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,
discontinuitySequence: 0,
discontinuityStarts: [],
timelineStarts: [{ start: 0, timeline: 0 }],
targetDuration: 100,
endList: true,
resolvedUri: 'https://www.example.com/vtt',
segments: [{
duration: 100,
resolvedUri: 'https://www.example.com/vtt',
timeline: 0,
uri: 'https://www.example.com/vtt',
number: 0
}],
timeline: 0,
uri: ''
}, {
attributes: {
BANDWIDTH: 10000,
NAME: '2',
['PROGRAM-ID']: 1
},
mediaSequence: 0,
discontinuitySequence: 0,
discontinuityStarts: [],
timelineStarts: [{ start: 0, timeline: 0 }],
targetDuration: 100,
endList: true,
resolvedUri: 'https://www.example.com/vtt',
segments: [{
duration: 100,
resolvedUri: 'https://www.example.com/vtt',
timeline: 0,
uri: 'https://www.example.com/vtt',
number: 0
}],
timeline: 0,
uri: ''
}],
uri: ''
}
}
},
VIDEO: {}
},
playlists: [{
attributes: {
AUDIO: 'audio',
SUBTITLES: 'subs',
BANDWIDTH: 10000,
CODECS: 'foo;bar',
NAME: '1',
['FRAME-RATE']: 30,
['PROGRAM-ID']: 1,
RESOLUTION: {
height: 600,
width: 800
}
},
endList: true,
mediaSequence: 0,
discontinuitySequence: 0,
discontinuityStarts: [],
timelineStarts: [{ start: 0, timeline: 0 }],
targetDuration: 0,
resolvedUri: '',
segments: [],
timeline: 0,
uri: ''
}],
segments: [],
uri: ''
};
assert.deepEqual(toM3u8({ dashPlaylists, eventStream }), expected);
});

View file

@ -4,9 +4,7 @@ import {
flatten,
range,
from,
findIndexes,
findIndex,
includes
findIndexes
} from '../src/utils/list';
import { findChildren, getContent } from '../src/utils/xml';
import {DOMParser} from '@xmldom/xmldom';
@ -199,26 +197,6 @@ QUnit.test('indexes found', function(assert) {
], 'b'), [1, 2]);
});
QUnit.module('findIndex');
QUnit.test('match', function(assert) {
assert.equal(findIndex([2, 'b', 'a'], (el) => el === 'a'), 2, 'returned index');
});
QUnit.test('no match', function(assert) {
assert.equal(findIndex([], (el) => el === 'a'), -1, 'no match');
});
QUnit.module('includes');
QUnit.test('match', function(assert) {
assert.ok(includes([2, 'b', 'a'], 'a'), 'match found');
});
QUnit.test('no match', function(assert) {
assert.notOk(includes([], 'a'), 'no match');
});
QUnit.module('xml', {
beforeEach() {
const parser = new DOMParser();