mirror of
https://github.com/DanielnetoDotCom/YouPHPTube
synced 2025-10-04 18:29:39 +02:00
also npm update
This commit is contained in:
parent
b6d47e94c8
commit
65f15c7e46
2882 changed files with 382239 additions and 10785 deletions
219
node_modules/mpd-parser/dist/mpd-parser.js
generated
vendored
219
node_modules/mpd-parser/dist/mpd-parser.js
generated
vendored
|
@ -1,11 +1,11 @@
|
|||
/*! @name mpd-parser @version 1.1.1 @license Apache-2.0 */
|
||||
/*! @name mpd-parser @version 1.2.2 @license Apache-2.0 */
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@xmldom/xmldom')) :
|
||||
typeof define === 'function' && define.amd ? define(['exports', '@xmldom/xmldom'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.mpdParser = {}, global.window));
|
||||
}(this, (function (exports, xmldom) { 'use strict';
|
||||
|
||||
var version = "1.1.1";
|
||||
var version = "1.2.2";
|
||||
|
||||
const isObject = obj => {
|
||||
return !!obj && typeof obj === 'object';
|
||||
|
@ -81,6 +81,7 @@
|
|||
|
||||
var errors = {
|
||||
INVALID_NUMBER_OF_PERIOD: 'INVALID_NUMBER_OF_PERIOD',
|
||||
INVALID_NUMBER_OF_CONTENT_STEERING: 'INVALID_NUMBER_OF_CONTENT_STEERING',
|
||||
DASH_EMPTY_MANIFEST: 'DASH_EMPTY_MANIFEST',
|
||||
DASH_INVALID_XML: 'DASH_INVALID_XML',
|
||||
NO_BASE_URL: 'NO_BASE_URL',
|
||||
|
@ -987,43 +988,56 @@
|
|||
const generateSidxKey = sidx => sidx && sidx.uri + '-' + byteRangeToString(sidx.byterange);
|
||||
|
||||
const mergeDiscontiguousPlaylists = playlists => {
|
||||
const mergedPlaylists = values(playlists.reduce((acc, playlist) => {
|
||||
// assuming playlist IDs are the same across periods
|
||||
// TODO: handle multiperiod where representation sets are not the same
|
||||
// across periods
|
||||
const name = playlist.attributes.id + (playlist.attributes.lang || '');
|
||||
|
||||
if (!acc[name]) {
|
||||
// First Period
|
||||
acc[name] = playlist;
|
||||
acc[name].attributes.timelineStarts = [];
|
||||
} else {
|
||||
// Subsequent Periods
|
||||
if (playlist.segments) {
|
||||
// first segment of subsequent periods signal a discontinuity
|
||||
if (playlist.segments[0]) {
|
||||
playlist.segments[0].discontinuity = true;
|
||||
}
|
||||
|
||||
acc[name].segments.push(...playlist.segments);
|
||||
} // bubble up contentProtection, this assumes all DRM content
|
||||
// has the same contentProtection
|
||||
|
||||
|
||||
if (playlist.attributes.contentProtection) {
|
||||
acc[name].attributes.contentProtection = playlist.attributes.contentProtection;
|
||||
}
|
||||
// Break out playlists into groups based on their baseUrl
|
||||
const playlistsByBaseUrl = playlists.reduce(function (acc, cur) {
|
||||
if (!acc[cur.attributes.baseUrl]) {
|
||||
acc[cur.attributes.baseUrl] = [];
|
||||
}
|
||||
|
||||
acc[name].attributes.timelineStarts.push({
|
||||
// Although they represent the same number, it's important to have both to make it
|
||||
// compatible with HLS potentially having a similar attribute.
|
||||
start: playlist.attributes.periodStart,
|
||||
timeline: playlist.attributes.periodStart
|
||||
});
|
||||
acc[cur.attributes.baseUrl].push(cur);
|
||||
return acc;
|
||||
}, {}));
|
||||
return mergedPlaylists.map(playlist => {
|
||||
}, {});
|
||||
let allPlaylists = [];
|
||||
Object.values(playlistsByBaseUrl).forEach(playlistGroup => {
|
||||
const mergedPlaylists = values(playlistGroup.reduce((acc, playlist) => {
|
||||
// assuming playlist IDs are the same across periods
|
||||
// TODO: handle multiperiod where representation sets are not the same
|
||||
// across periods
|
||||
const name = playlist.attributes.id + (playlist.attributes.lang || '');
|
||||
|
||||
if (!acc[name]) {
|
||||
// First Period
|
||||
acc[name] = playlist;
|
||||
acc[name].attributes.timelineStarts = [];
|
||||
} else {
|
||||
// Subsequent Periods
|
||||
if (playlist.segments) {
|
||||
// first segment of subsequent periods signal a discontinuity
|
||||
if (playlist.segments[0]) {
|
||||
playlist.segments[0].discontinuity = true;
|
||||
}
|
||||
|
||||
acc[name].segments.push(...playlist.segments);
|
||||
} // bubble up contentProtection, this assumes all DRM content
|
||||
// has the same contentProtection
|
||||
|
||||
|
||||
if (playlist.attributes.contentProtection) {
|
||||
acc[name].attributes.contentProtection = playlist.attributes.contentProtection;
|
||||
}
|
||||
}
|
||||
|
||||
acc[name].attributes.timelineStarts.push({
|
||||
// Although they represent the same number, it's important to have both to make it
|
||||
// compatible with HLS potentially having a similar attribute.
|
||||
start: playlist.attributes.periodStart,
|
||||
timeline: playlist.attributes.periodStart
|
||||
});
|
||||
return acc;
|
||||
}, {}));
|
||||
allPlaylists = allPlaylists.concat(mergedPlaylists);
|
||||
});
|
||||
return allPlaylists.map(playlist => {
|
||||
playlist.discontinuityStarts = findIndexes(playlist.segments || [], 'discontinuity');
|
||||
return playlist;
|
||||
});
|
||||
|
@ -1068,7 +1082,7 @@
|
|||
uri: '',
|
||||
endList: attributes.type === 'static',
|
||||
timeline: attributes.periodStart,
|
||||
resolvedUri: '',
|
||||
resolvedUri: attributes.baseUrl || '',
|
||||
targetDuration: attributes.duration,
|
||||
discontinuitySequence,
|
||||
discontinuityStarts,
|
||||
|
@ -1081,6 +1095,10 @@
|
|||
playlist.contentProtection = attributes.contentProtection;
|
||||
}
|
||||
|
||||
if (attributes.serviceLocation) {
|
||||
playlist.attributes.serviceLocation = attributes.serviceLocation;
|
||||
}
|
||||
|
||||
if (sidx) {
|
||||
playlist.sidx = sidx;
|
||||
}
|
||||
|
@ -1122,7 +1140,7 @@
|
|||
m3u8Attributes.CODECS = attributes.codecs;
|
||||
}
|
||||
|
||||
return {
|
||||
const vttPlaylist = {
|
||||
attributes: m3u8Attributes,
|
||||
uri: '',
|
||||
endList: attributes.type === 'static',
|
||||
|
@ -1135,6 +1153,12 @@
|
|||
mediaSequence,
|
||||
segments
|
||||
};
|
||||
|
||||
if (attributes.serviceLocation) {
|
||||
vttPlaylist.attributes.serviceLocation = attributes.serviceLocation;
|
||||
}
|
||||
|
||||
return vttPlaylist;
|
||||
};
|
||||
const organizeAudioPlaylists = (playlists, sidxMapping = {}, isAudioOnly = false) => {
|
||||
let mainPlaylist;
|
||||
|
@ -1249,7 +1273,7 @@
|
|||
uri: '',
|
||||
endList: attributes.type === 'static',
|
||||
timeline: attributes.periodStart,
|
||||
resolvedUri: '',
|
||||
resolvedUri: attributes.baseUrl || '',
|
||||
targetDuration: attributes.duration,
|
||||
discontinuityStarts,
|
||||
timelineStarts: attributes.timelineStarts,
|
||||
|
@ -1264,6 +1288,10 @@
|
|||
playlist.contentProtection = attributes.contentProtection;
|
||||
}
|
||||
|
||||
if (attributes.serviceLocation) {
|
||||
playlist.attributes.serviceLocation = attributes.serviceLocation;
|
||||
}
|
||||
|
||||
if (sidx) {
|
||||
playlist.sidx = sidx;
|
||||
}
|
||||
|
@ -1356,6 +1384,7 @@
|
|||
const toM3u8 = ({
|
||||
dashPlaylists,
|
||||
locations,
|
||||
contentSteering,
|
||||
sidxMapping = {},
|
||||
previousManifest,
|
||||
eventStream
|
||||
|
@ -1399,6 +1428,10 @@
|
|||
manifest.locations = locations;
|
||||
}
|
||||
|
||||
if (contentSteering) {
|
||||
manifest.contentSteering = contentSteering;
|
||||
}
|
||||
|
||||
if (type === 'dynamic') {
|
||||
manifest.suggestedPresentationDelay = suggestedPresentationDelay;
|
||||
}
|
||||
|
@ -2248,22 +2281,33 @@
|
|||
/**
|
||||
* Builds a list of urls that is the product of the reference urls and BaseURL values
|
||||
*
|
||||
* @param {string[]} referenceUrls
|
||||
* List of reference urls to resolve to
|
||||
* @param {Object[]} references
|
||||
* List of objects containing the reference URL as well as its attributes
|
||||
* @param {Node[]} baseUrlElements
|
||||
* List of BaseURL nodes from the mpd
|
||||
* @return {string[]}
|
||||
* List of resolved urls
|
||||
* @return {Object[]}
|
||||
* List of objects with resolved urls and attributes
|
||||
*/
|
||||
|
||||
const buildBaseUrls = (referenceUrls, baseUrlElements) => {
|
||||
const buildBaseUrls = (references, baseUrlElements) => {
|
||||
if (!baseUrlElements.length) {
|
||||
return referenceUrls;
|
||||
return references;
|
||||
}
|
||||
|
||||
return flatten(referenceUrls.map(function (reference) {
|
||||
return flatten(references.map(function (reference) {
|
||||
return baseUrlElements.map(function (baseUrlElement) {
|
||||
return resolveUrl(reference, getContent(baseUrlElement));
|
||||
const initialBaseUrl = getContent(baseUrlElement);
|
||||
const resolvedBaseUrl = resolveUrl(reference.baseUrl, initialBaseUrl);
|
||||
const finalBaseUrl = merge(parseAttributes(baseUrlElement), {
|
||||
baseUrl: resolvedBaseUrl
|
||||
}); // If the URL is resolved, we want to get the serviceLocation from the reference
|
||||
// assuming there is no serviceLocation on the initialBaseUrl
|
||||
|
||||
if (resolvedBaseUrl !== initialBaseUrl && !finalBaseUrl.serviceLocation && reference.serviceLocation) {
|
||||
finalBaseUrl.serviceLocation = reference.serviceLocation;
|
||||
}
|
||||
|
||||
return finalBaseUrl;
|
||||
});
|
||||
}));
|
||||
};
|
||||
|
@ -2365,8 +2409,9 @@
|
|||
*
|
||||
* @param {Object} adaptationSetAttributes
|
||||
* Contains attributes inherited by the AdaptationSet
|
||||
* @param {string[]} adaptationSetBaseUrls
|
||||
* Contains list of resolved base urls inherited by the AdaptationSet
|
||||
* @param {Object[]} adaptationSetBaseUrls
|
||||
* List of objects containing resolved base URLs and attributes
|
||||
* inherited by the AdaptationSet
|
||||
* @param {SegmentInformation} adaptationSetSegmentInfo
|
||||
* Contains Segment information for the AdaptationSet
|
||||
* @return {inheritBaseUrlsCallback}
|
||||
|
@ -2381,9 +2426,7 @@
|
|||
return repBaseUrls.map(baseUrl => {
|
||||
return {
|
||||
segmentInfo: merge(adaptationSetSegmentInfo, representationSegmentInfo),
|
||||
attributes: merge(attributes, {
|
||||
baseUrl
|
||||
})
|
||||
attributes: merge(attributes, baseUrl)
|
||||
};
|
||||
});
|
||||
};
|
||||
|
@ -2550,8 +2593,9 @@
|
|||
*
|
||||
* @param {Object} periodAttributes
|
||||
* Contains attributes inherited by the Period
|
||||
* @param {string[]} periodBaseUrls
|
||||
* Contains list of resolved base urls inherited by the Period
|
||||
* @param {Object[]} periodBaseUrls
|
||||
* Contains list of objects with resolved base urls and attributes
|
||||
* inherited by the Period
|
||||
* @param {string[]} periodSegmentInfo
|
||||
* Contains Segment Information at the period level
|
||||
* @return {toRepresentationsCallback}
|
||||
|
@ -2627,8 +2671,9 @@
|
|||
*
|
||||
* @param {Object} mpdAttributes
|
||||
* Contains attributes inherited by the mpd
|
||||
* @param {string[]} mpdBaseUrls
|
||||
* Contains list of resolved base urls inherited by the mpd
|
||||
* @param {Object[]} mpdBaseUrls
|
||||
* Contains list of objects with resolved base urls and attributes
|
||||
* inherited by the mpd
|
||||
* @return {toAdaptationSetsCallback}
|
||||
* Callback map function
|
||||
*/
|
||||
|
@ -2647,6 +2692,43 @@
|
|||
const periodSegmentInfo = getSegmentInformation(period.node);
|
||||
return flatten(adaptationSets.map(toRepresentations(periodAttributes, periodBaseUrls, periodSegmentInfo)));
|
||||
};
|
||||
/**
|
||||
* Tranforms an array of content steering nodes into an object
|
||||
* containing CDN content steering information from the MPD manifest.
|
||||
*
|
||||
* For more information on the DASH spec for Content Steering parsing, see:
|
||||
* https://dashif.org/docs/DASH-IF-CTS-00XX-Content-Steering-Community-Review.pdf
|
||||
*
|
||||
* @param {Node[]} contentSteeringNodes
|
||||
* Content steering nodes
|
||||
* @param {Function} eventHandler
|
||||
* The event handler passed into the parser options to handle warnings
|
||||
* @return {Object}
|
||||
* Object containing content steering data
|
||||
*/
|
||||
|
||||
const generateContentSteeringInformation = (contentSteeringNodes, eventHandler) => {
|
||||
// If there are more than one ContentSteering tags, throw an error
|
||||
if (contentSteeringNodes.length > 1) {
|
||||
eventHandler({
|
||||
type: 'warn',
|
||||
message: 'The MPD manifest should contain no more than one ContentSteering tag'
|
||||
});
|
||||
} // Return a null value if there are no ContentSteering tags
|
||||
|
||||
|
||||
if (!contentSteeringNodes.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const infoFromContentSteeringTag = merge({
|
||||
serverURL: getContent(contentSteeringNodes[0])
|
||||
}, parseAttributes(contentSteeringNodes[0])); // Converts `queryBeforeStart` to a boolean, as well as setting the default value
|
||||
// to `false` if it doesn't exist
|
||||
|
||||
infoFromContentSteeringTag.queryBeforeStart = infoFromContentSteeringTag.queryBeforeStart === 'true';
|
||||
return infoFromContentSteeringTag;
|
||||
};
|
||||
/**
|
||||
* Gets Period@start property for a given period.
|
||||
*
|
||||
|
@ -2726,7 +2808,14 @@
|
|||
const {
|
||||
manifestUri = '',
|
||||
NOW = Date.now(),
|
||||
clientOffset = 0
|
||||
clientOffset = 0,
|
||||
// TODO: For now, we are expecting an eventHandler callback function
|
||||
// to be passed into the mpd parser as an option.
|
||||
// In the future, we should enable stream parsing by using the Stream class from vhs-utils.
|
||||
// This will support new features including a standardized event handler.
|
||||
// See the m3u8 parser for examples of how stream parsing is currently used for HLS parsing.
|
||||
// https://github.com/videojs/vhs-utils/blob/88d6e10c631e57a5af02c5a62bc7376cd456b4f5/src/stream.js#L9
|
||||
eventHandler = function () {}
|
||||
} = options;
|
||||
const periodNodes = findChildren(mpd, 'Period');
|
||||
|
||||
|
@ -2736,7 +2825,10 @@
|
|||
|
||||
const locations = findChildren(mpd, 'Location');
|
||||
const mpdAttributes = parseAttributes(mpd);
|
||||
const mpdBaseUrls = buildBaseUrls([manifestUri], findChildren(mpd, 'BaseURL')); // See DASH spec section 5.3.1.2, Semantics of MPD element. Default type to 'static'.
|
||||
const mpdBaseUrls = buildBaseUrls([{
|
||||
baseUrl: manifestUri
|
||||
}], findChildren(mpd, 'BaseURL'));
|
||||
const contentSteeringNodes = findChildren(mpd, 'ContentSteering'); // See DASH spec section 5.3.1.2, Semantics of MPD element. Default type to 'static'.
|
||||
|
||||
mpdAttributes.type = mpdAttributes.type || 'static';
|
||||
mpdAttributes.sourceDuration = mpdAttributes.mediaPresentationDuration || 0;
|
||||
|
@ -2769,6 +2861,14 @@
|
|||
});
|
||||
return {
|
||||
locations: mpdAttributes.locations,
|
||||
contentSteeringInfo: generateContentSteeringInformation(contentSteeringNodes, eventHandler),
|
||||
// TODO: There are occurences where this `representationInfo` array contains undesired
|
||||
// duplicates. This generally occurs when there are multiple BaseURL nodes that are
|
||||
// direct children of the MPD node. When we attempt to resolve URLs from a combination of the
|
||||
// parent BaseURL and a child BaseURL, and the value does not resolve,
|
||||
// we end up returning the child BaseURL multiple times.
|
||||
// We need to determine a way to remove these duplicates in a safe way.
|
||||
// See: https://github.com/videojs/mpd-parser/pull/17#discussion_r162750527
|
||||
representationInfo: flatten(periods.map(toAdaptationSets(mpdAttributes, mpdBaseUrls))),
|
||||
eventStream: flatten(periods.map(toEventStream))
|
||||
};
|
||||
|
@ -2786,7 +2886,7 @@
|
|||
try {
|
||||
xml = parser.parseFromString(manifestString, 'application/xml');
|
||||
mpd = xml && xml.documentElement.tagName === 'MPD' ? xml.documentElement : null;
|
||||
} catch (e) {// ie 11 throwsw on invalid xml
|
||||
} catch (e) {// ie 11 throws on invalid xml
|
||||
}
|
||||
|
||||
if (!mpd || mpd && mpd.getElementsByTagName('parsererror').length > 0) {
|
||||
|
@ -2864,6 +2964,7 @@
|
|||
return toM3u8({
|
||||
dashPlaylists: playlists,
|
||||
locations: parsedManifestInfo.locations,
|
||||
contentSteering: parsedManifestInfo.contentSteeringInfo,
|
||||
sidxMapping: options.sidxMapping,
|
||||
previousManifest: options.previousManifest,
|
||||
eventStream: parsedManifestInfo.eventStream
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue