mirror of
https://github.com/DanielnetoDotCom/YouPHPTube
synced 2025-10-03 17:59:55 +02:00
Update node modules
This commit is contained in:
parent
d429e6f7d8
commit
c05a371397
1993 changed files with 9729 additions and 44041 deletions
542
node_modules/@videojs/http-streaming/dist/videojs-http-streaming.js
generated
vendored
542
node_modules/@videojs/http-streaming/dist/videojs-http-streaming.js
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
/*! @name @videojs/http-streaming @version 3.13.3 @license Apache-2.0 */
|
||||
/*! @name @videojs/http-streaming @version 3.14.2 @license Apache-2.0 */
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('video.js'), require('@xmldom/xmldom')) :
|
||||
typeof define === 'function' && define.amd ? define(['exports', 'video.js', '@xmldom/xmldom'], factory) :
|
||||
|
@ -27,181 +27,7 @@
|
|||
return _extends.apply(this, arguments);
|
||||
}
|
||||
|
||||
var urlToolkit = {exports: {}};
|
||||
|
||||
(function (module, exports) {
|
||||
// see https://tools.ietf.org/html/rfc1808
|
||||
(function (root) {
|
||||
var URL_REGEX = /^((?:[a-zA-Z0-9+\-.]+:)?)(\/\/[^\/?#]*)?((?:[^\/?#]*\/)*[^;?#]*)?(;[^?#]*)?(\?[^#]*)?(#[^]*)?$/;
|
||||
var FIRST_SEGMENT_REGEX = /^([^\/?#]*)([^]*)$/;
|
||||
var SLASH_DOT_REGEX = /(?:\/|^)\.(?=\/)/g;
|
||||
var SLASH_DOT_DOT_REGEX = /(?:\/|^)\.\.\/(?!\.\.\/)[^\/]*(?=\/)/g;
|
||||
var URLToolkit = {
|
||||
// If opts.alwaysNormalize is true then the path will always be normalized even when it starts with / or //
|
||||
// E.g
|
||||
// With opts.alwaysNormalize = false (default, spec compliant)
|
||||
// http://a.com/b/cd + /e/f/../g => http://a.com/e/f/../g
|
||||
// With opts.alwaysNormalize = true (not spec compliant)
|
||||
// http://a.com/b/cd + /e/f/../g => http://a.com/e/g
|
||||
buildAbsoluteURL: function (baseURL, relativeURL, opts) {
|
||||
opts = opts || {}; // remove any remaining space and CRLF
|
||||
|
||||
baseURL = baseURL.trim();
|
||||
relativeURL = relativeURL.trim();
|
||||
|
||||
if (!relativeURL) {
|
||||
// 2a) If the embedded URL is entirely empty, it inherits the
|
||||
// entire base URL (i.e., is set equal to the base URL)
|
||||
// and we are done.
|
||||
if (!opts.alwaysNormalize) {
|
||||
return baseURL;
|
||||
}
|
||||
|
||||
var basePartsForNormalise = URLToolkit.parseURL(baseURL);
|
||||
|
||||
if (!basePartsForNormalise) {
|
||||
throw new Error('Error trying to parse base URL.');
|
||||
}
|
||||
|
||||
basePartsForNormalise.path = URLToolkit.normalizePath(basePartsForNormalise.path);
|
||||
return URLToolkit.buildURLFromParts(basePartsForNormalise);
|
||||
}
|
||||
|
||||
var relativeParts = URLToolkit.parseURL(relativeURL);
|
||||
|
||||
if (!relativeParts) {
|
||||
throw new Error('Error trying to parse relative URL.');
|
||||
}
|
||||
|
||||
if (relativeParts.scheme) {
|
||||
// 2b) If the embedded URL starts with a scheme name, it is
|
||||
// interpreted as an absolute URL and we are done.
|
||||
if (!opts.alwaysNormalize) {
|
||||
return relativeURL;
|
||||
}
|
||||
|
||||
relativeParts.path = URLToolkit.normalizePath(relativeParts.path);
|
||||
return URLToolkit.buildURLFromParts(relativeParts);
|
||||
}
|
||||
|
||||
var baseParts = URLToolkit.parseURL(baseURL);
|
||||
|
||||
if (!baseParts) {
|
||||
throw new Error('Error trying to parse base URL.');
|
||||
}
|
||||
|
||||
if (!baseParts.netLoc && baseParts.path && baseParts.path[0] !== '/') {
|
||||
// If netLoc missing and path doesn't start with '/', assume everthing before the first '/' is the netLoc
|
||||
// This causes 'example.com/a' to be handled as '//example.com/a' instead of '/example.com/a'
|
||||
var pathParts = FIRST_SEGMENT_REGEX.exec(baseParts.path);
|
||||
baseParts.netLoc = pathParts[1];
|
||||
baseParts.path = pathParts[2];
|
||||
}
|
||||
|
||||
if (baseParts.netLoc && !baseParts.path) {
|
||||
baseParts.path = '/';
|
||||
}
|
||||
|
||||
var builtParts = {
|
||||
// 2c) Otherwise, the embedded URL inherits the scheme of
|
||||
// the base URL.
|
||||
scheme: baseParts.scheme,
|
||||
netLoc: relativeParts.netLoc,
|
||||
path: null,
|
||||
params: relativeParts.params,
|
||||
query: relativeParts.query,
|
||||
fragment: relativeParts.fragment
|
||||
};
|
||||
|
||||
if (!relativeParts.netLoc) {
|
||||
// 3) If the embedded URL's <net_loc> is non-empty, we skip to
|
||||
// Step 7. Otherwise, the embedded URL inherits the <net_loc>
|
||||
// (if any) of the base URL.
|
||||
builtParts.netLoc = baseParts.netLoc; // 4) If the embedded URL path is preceded by a slash "/", the
|
||||
// path is not relative and we skip to Step 7.
|
||||
|
||||
if (relativeParts.path[0] !== '/') {
|
||||
if (!relativeParts.path) {
|
||||
// 5) If the embedded URL path is empty (and not preceded by a
|
||||
// slash), then the embedded URL inherits the base URL path
|
||||
builtParts.path = baseParts.path; // 5a) if the embedded URL's <params> is non-empty, we skip to
|
||||
// step 7; otherwise, it inherits the <params> of the base
|
||||
// URL (if any) and
|
||||
|
||||
if (!relativeParts.params) {
|
||||
builtParts.params = baseParts.params; // 5b) if the embedded URL's <query> is non-empty, we skip to
|
||||
// step 7; otherwise, it inherits the <query> of the base
|
||||
// URL (if any) and we skip to step 7.
|
||||
|
||||
if (!relativeParts.query) {
|
||||
builtParts.query = baseParts.query;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 6) The last segment of the base URL's path (anything
|
||||
// following the rightmost slash "/", or the entire path if no
|
||||
// slash is present) is removed and the embedded URL's path is
|
||||
// appended in its place.
|
||||
var baseURLPath = baseParts.path;
|
||||
var newPath = baseURLPath.substring(0, baseURLPath.lastIndexOf('/') + 1) + relativeParts.path;
|
||||
builtParts.path = URLToolkit.normalizePath(newPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (builtParts.path === null) {
|
||||
builtParts.path = opts.alwaysNormalize ? URLToolkit.normalizePath(relativeParts.path) : relativeParts.path;
|
||||
}
|
||||
|
||||
return URLToolkit.buildURLFromParts(builtParts);
|
||||
},
|
||||
parseURL: function (url) {
|
||||
var parts = URL_REGEX.exec(url);
|
||||
|
||||
if (!parts) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
scheme: parts[1] || '',
|
||||
netLoc: parts[2] || '',
|
||||
path: parts[3] || '',
|
||||
params: parts[4] || '',
|
||||
query: parts[5] || '',
|
||||
fragment: parts[6] || ''
|
||||
};
|
||||
},
|
||||
normalizePath: function (path) {
|
||||
// The following operations are
|
||||
// then applied, in order, to the new path:
|
||||
// 6a) All occurrences of "./", where "." is a complete path
|
||||
// segment, are removed.
|
||||
// 6b) If the path ends with "." as a complete path segment,
|
||||
// that "." is removed.
|
||||
path = path.split('').reverse().join('').replace(SLASH_DOT_REGEX, ''); // 6c) All occurrences of "<segment>/../", where <segment> is a
|
||||
// complete path segment not equal to "..", are removed.
|
||||
// Removal of these path segments is performed iteratively,
|
||||
// removing the leftmost matching pattern on each iteration,
|
||||
// until no matching pattern remains.
|
||||
// 6d) If the path ends with "<segment>/..", where <segment> is a
|
||||
// complete path segment not equal to "..", that
|
||||
// "<segment>/.." is removed.
|
||||
|
||||
while (path.length !== (path = path.replace(SLASH_DOT_DOT_REGEX, '')).length) {}
|
||||
|
||||
return path.split('').reverse().join('');
|
||||
},
|
||||
buildURLFromParts: function (parts) {
|
||||
return parts.scheme + parts.netLoc + parts.path + parts.params + parts.query + parts.fragment;
|
||||
}
|
||||
};
|
||||
module.exports = URLToolkit;
|
||||
})();
|
||||
})(urlToolkit);
|
||||
|
||||
var URLToolkit = urlToolkit.exports;
|
||||
|
||||
var DEFAULT_LOCATION = 'http://example.com';
|
||||
var DEFAULT_LOCATION = 'https://example.com';
|
||||
|
||||
var resolveUrl$1 = function resolveUrl(baseUrl, relativeUrl) {
|
||||
// return early if we don't need to resolve
|
||||
|
@ -212,37 +38,25 @@
|
|||
|
||||
if (/^data:/.test(baseUrl)) {
|
||||
baseUrl = window.location && window.location.href || '';
|
||||
} // IE11 supports URL but not the URL constructor
|
||||
// feature detect the behavior we want
|
||||
}
|
||||
|
||||
|
||||
var nativeURL = typeof window.URL === 'function';
|
||||
var protocolLess = /^\/\//.test(baseUrl); // remove location if window.location isn't available (i.e. we're in node)
|
||||
// and if baseUrl isn't an absolute url
|
||||
|
||||
var removeLocation = !window.location && !/\/\//i.test(baseUrl); // if the base URL is relative then combine with the current location
|
||||
|
||||
if (nativeURL) {
|
||||
baseUrl = new window.URL(baseUrl, window.location || DEFAULT_LOCATION);
|
||||
} else if (!/\/\//i.test(baseUrl)) {
|
||||
baseUrl = URLToolkit.buildAbsoluteURL(window.location && window.location.href || '', baseUrl);
|
||||
baseUrl = new window.URL(baseUrl, window.location || DEFAULT_LOCATION);
|
||||
var newUrl = new URL(relativeUrl, baseUrl); // if we're a protocol-less url, remove the protocol
|
||||
// and if we're location-less, remove the location
|
||||
// otherwise, return the url unmodified
|
||||
|
||||
if (removeLocation) {
|
||||
return newUrl.href.slice(DEFAULT_LOCATION.length);
|
||||
} else if (protocolLess) {
|
||||
return newUrl.href.slice(newUrl.protocol.length);
|
||||
}
|
||||
|
||||
if (nativeURL) {
|
||||
var newUrl = new URL(relativeUrl, baseUrl); // if we're a protocol-less url, remove the protocol
|
||||
// and if we're location-less, remove the location
|
||||
// otherwise, return the url unmodified
|
||||
|
||||
if (removeLocation) {
|
||||
return newUrl.href.slice(DEFAULT_LOCATION.length);
|
||||
} else if (protocolLess) {
|
||||
return newUrl.href.slice(newUrl.protocol.length);
|
||||
}
|
||||
|
||||
return newUrl.href;
|
||||
}
|
||||
|
||||
return URLToolkit.buildAbsoluteURL(baseUrl, relativeUrl);
|
||||
return newUrl.href;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -415,7 +229,7 @@
|
|||
return array;
|
||||
}
|
||||
|
||||
/*! @name m3u8-parser @version 7.1.0 @license Apache-2.0 */
|
||||
/*! @name m3u8-parser @version 7.2.0 @license Apache-2.0 */
|
||||
/**
|
||||
* @file m3u8/line-stream.js
|
||||
*/
|
||||
|
@ -522,6 +336,30 @@
|
|||
|
||||
return result;
|
||||
};
|
||||
/**
|
||||
* Converts a string into a resolution object
|
||||
*
|
||||
* @param {string} resolution a string such as 3840x2160
|
||||
*
|
||||
* @return {Object} An object representing the resolution
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
const parseResolution = resolution => {
|
||||
const split = resolution.split('x');
|
||||
const result = {};
|
||||
|
||||
if (split[0]) {
|
||||
result.width = parseInt(split[0], 10);
|
||||
}
|
||||
|
||||
if (split[1]) {
|
||||
result.height = parseInt(split[1], 10);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
/**
|
||||
* A line-level M3U8 parser event stream. It expects to receive input one
|
||||
* line at a time and performs a context-free parse of its contents. A stream
|
||||
|
@ -784,18 +622,7 @@
|
|||
event.attributes = parseAttributes$1(match[1]);
|
||||
|
||||
if (event.attributes.RESOLUTION) {
|
||||
const split = event.attributes.RESOLUTION.split('x');
|
||||
const resolution = {};
|
||||
|
||||
if (split[0]) {
|
||||
resolution.width = parseInt(split[0], 10);
|
||||
}
|
||||
|
||||
if (split[1]) {
|
||||
resolution.height = parseInt(split[1], 10);
|
||||
}
|
||||
|
||||
event.attributes.RESOLUTION = resolution;
|
||||
event.attributes.RESOLUTION = parseResolution(event.attributes.RESOLUTION);
|
||||
}
|
||||
|
||||
if (event.attributes.BANDWIDTH) {
|
||||
|
@ -951,7 +778,7 @@
|
|||
return;
|
||||
}
|
||||
|
||||
match = /^#EXT-X-CUE-IN:(.*)?$/.exec(newLine);
|
||||
match = /^#EXT-X-CUE-IN:?(.*)?$/.exec(newLine);
|
||||
|
||||
if (match) {
|
||||
event = {
|
||||
|
@ -1154,6 +981,16 @@
|
|||
return;
|
||||
}
|
||||
|
||||
match = /^#EXT-X-I-FRAMES-ONLY/.exec(newLine);
|
||||
|
||||
if (match) {
|
||||
this.trigger('data', {
|
||||
type: 'tag',
|
||||
tagType: 'i-frames-only'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
match = /^#EXT-X-CONTENT-STEERING:(.*)$/.exec(newLine);
|
||||
|
||||
if (match) {
|
||||
|
@ -1164,6 +1001,51 @@
|
|||
event.attributes = parseAttributes$1(match[1]);
|
||||
this.trigger('data', event);
|
||||
return;
|
||||
}
|
||||
|
||||
match = /^#EXT-X-I-FRAME-STREAM-INF:(.*)$/.exec(newLine);
|
||||
|
||||
if (match) {
|
||||
event = {
|
||||
type: 'tag',
|
||||
tagType: 'i-frame-playlist'
|
||||
};
|
||||
event.attributes = parseAttributes$1(match[1]);
|
||||
|
||||
if (event.attributes.URI) {
|
||||
event.uri = event.attributes.URI;
|
||||
}
|
||||
|
||||
if (event.attributes.BANDWIDTH) {
|
||||
event.attributes.BANDWIDTH = parseInt(event.attributes.BANDWIDTH, 10);
|
||||
}
|
||||
|
||||
if (event.attributes.RESOLUTION) {
|
||||
event.attributes.RESOLUTION = parseResolution(event.attributes.RESOLUTION);
|
||||
}
|
||||
|
||||
if (event.attributes['AVERAGE-BANDWIDTH']) {
|
||||
event.attributes['AVERAGE-BANDWIDTH'] = parseInt(event.attributes['AVERAGE-BANDWIDTH'], 10);
|
||||
}
|
||||
|
||||
if (event.attributes['FRAME-RATE']) {
|
||||
event.attributes['FRAME-RATE'] = parseFloat(event.attributes['FRAME-RATE']);
|
||||
}
|
||||
|
||||
this.trigger('data', event);
|
||||
return;
|
||||
}
|
||||
|
||||
match = /^#EXT-X-DEFINE:(.*)$/.exec(newLine);
|
||||
|
||||
if (match) {
|
||||
event = {
|
||||
type: 'tag',
|
||||
tagType: 'define'
|
||||
};
|
||||
event.attributes = parseAttributes$1(match[1]);
|
||||
this.trigger('data', event);
|
||||
return;
|
||||
} // unknown tag type
|
||||
|
||||
|
||||
|
@ -1314,16 +1196,21 @@
|
|||
* requires some property of the manifest object to be defaulted.
|
||||
*
|
||||
* @class Parser
|
||||
* @param {Object} [opts] Options for the constructor, needed for substitutions
|
||||
* @param {string} [opts.uri] URL to check for query params
|
||||
* @param {Object} [opts.mainDefinitions] Definitions on main playlist that can be imported
|
||||
* @extends Stream
|
||||
*/
|
||||
|
||||
|
||||
class Parser extends Stream {
|
||||
constructor() {
|
||||
constructor(opts = {}) {
|
||||
super();
|
||||
this.lineStream = new LineStream();
|
||||
this.parseStream = new ParseStream();
|
||||
this.lineStream.pipe(this.parseStream);
|
||||
this.mainDefinitions = opts.mainDefinitions || {};
|
||||
this.params = new URL(opts.uri, 'https://a.com').searchParams;
|
||||
this.lastProgramDateTime = null;
|
||||
/* eslint-disable consistent-this */
|
||||
|
||||
|
@ -1356,6 +1243,7 @@
|
|||
allowCache: true,
|
||||
discontinuityStarts: [],
|
||||
dateRanges: [],
|
||||
iFramePlaylists: [],
|
||||
segments: []
|
||||
}; // keep track of the last seen segment's byte range end, as segments are not required
|
||||
// to provide the offset, in which case it defaults to the next byte after the
|
||||
|
@ -1389,7 +1277,24 @@
|
|||
|
||||
this.parseStream.on('data', function (entry) {
|
||||
let mediaGroup;
|
||||
let rendition;
|
||||
let rendition; // Replace variables in uris and attributes as defined in #EXT-X-DEFINE tags
|
||||
|
||||
if (self.manifest.definitions) {
|
||||
for (const def in self.manifest.definitions) {
|
||||
if (entry.uri) {
|
||||
entry.uri = entry.uri.replace(`{$${def}}`, self.manifest.definitions[def]);
|
||||
}
|
||||
|
||||
if (entry.attributes) {
|
||||
for (const attr in entry.attributes) {
|
||||
if (typeof entry.attributes[attr] === 'string') {
|
||||
entry.attributes[attr] = entry.attributes[attr].replace(`{$${def}}`, self.manifest.definitions[def]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
({
|
||||
tag() {
|
||||
// switch based on the tag type
|
||||
|
@ -1962,9 +1867,121 @@
|
|||
this.manifest.independentSegments = true;
|
||||
},
|
||||
|
||||
'i-frames-only'() {
|
||||
this.manifest.iFramesOnly = true;
|
||||
this.requiredCompatibilityversion(this.manifest.version, 4);
|
||||
},
|
||||
|
||||
'content-steering'() {
|
||||
this.manifest.contentSteering = camelCaseKeys(entry.attributes);
|
||||
this.warnOnMissingAttributes_('#EXT-X-CONTENT-STEERING', entry.attributes, ['SERVER-URI']);
|
||||
},
|
||||
|
||||
/** @this {Parser} */
|
||||
define() {
|
||||
this.manifest.definitions = this.manifest.definitions || {};
|
||||
|
||||
const addDef = (n, v) => {
|
||||
if (n in this.manifest.definitions) {
|
||||
// An EXT-X-DEFINE tag MUST NOT specify the same Variable Name as any other
|
||||
// EXT-X-DEFINE tag in the same Playlist. Parsers that encounter duplicate
|
||||
// Variable Name declarations MUST fail to parse the Playlist.
|
||||
this.trigger('error', {
|
||||
message: `EXT-X-DEFINE: Duplicate name ${n}`
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.manifest.definitions[n] = v;
|
||||
};
|
||||
|
||||
if ('QUERYPARAM' in entry.attributes) {
|
||||
if ('NAME' in entry.attributes || 'IMPORT' in entry.attributes) {
|
||||
// An EXT-X-DEFINE tag MUST contain either a NAME, an IMPORT, or a
|
||||
// QUERYPARAM attribute, but only one of the three. Otherwise, the
|
||||
// client MUST fail to parse the Playlist.
|
||||
this.trigger('error', {
|
||||
message: 'EXT-X-DEFINE: Invalid attributes'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const val = this.params.get(entry.attributes.QUERYPARAM);
|
||||
|
||||
if (!val) {
|
||||
// If the QUERYPARAM attribute value does not match any query parameter in
|
||||
// the URI or the matching parameter has no associated value, the parser
|
||||
// MUST fail to parse the Playlist. If more than one parameter matches,
|
||||
// any of the associated values MAY be used.
|
||||
this.trigger('error', {
|
||||
message: `EXT-X-DEFINE: No query param ${entry.attributes.QUERYPARAM}`
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
addDef(entry.attributes.QUERYPARAM, decodeURIComponent(val));
|
||||
return;
|
||||
}
|
||||
|
||||
if ('NAME' in entry.attributes) {
|
||||
if ('IMPORT' in entry.attributes) {
|
||||
// An EXT-X-DEFINE tag MUST contain either a NAME, an IMPORT, or a
|
||||
// QUERYPARAM attribute, but only one of the three. Otherwise, the
|
||||
// client MUST fail to parse the Playlist.
|
||||
this.trigger('error', {
|
||||
message: 'EXT-X-DEFINE: Invalid attributes'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!('VALUE' in entry.attributes) || typeof entry.attributes.VALUE !== 'string') {
|
||||
// This attribute is REQUIRED if the EXT-X-DEFINE tag has a NAME attribute.
|
||||
// The quoted-string MAY be empty.
|
||||
this.trigger('error', {
|
||||
message: `EXT-X-DEFINE: No value for ${entry.attributes.NAME}`
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
addDef(entry.attributes.NAME, entry.attributes.VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
if ('IMPORT' in entry.attributes) {
|
||||
if (!this.mainDefinitions[entry.attributes.IMPORT]) {
|
||||
// Covers two conditions, as mainDefinitions will always be empty on main
|
||||
//
|
||||
// EXT-X-DEFINE tags containing the IMPORT attribute MUST NOT occur in
|
||||
// Multivariant Playlists; they are only allowed in Media Playlists.
|
||||
//
|
||||
// If the IMPORT attribute value does not match any Variable Name in the
|
||||
// Multivariant Playlist, or if the Media Playlist loaded from a
|
||||
// Multivariant Playlist, the parser MUST fail the Playlist.
|
||||
this.trigger('error', {
|
||||
message: `EXT-X-DEFINE: No value ${entry.attributes.IMPORT} to import, or IMPORT used on main playlist`
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
addDef(entry.attributes.IMPORT, this.mainDefinitions[entry.attributes.IMPORT]);
|
||||
return;
|
||||
} // An EXT-X-DEFINE tag MUST contain either a NAME, an IMPORT, or a QUERYPARAM
|
||||
// attribute, but only one of the three. Otherwise, the client MUST fail to
|
||||
// parse the Playlist.
|
||||
|
||||
|
||||
this.trigger('error', {
|
||||
message: 'EXT-X-DEFINE: No attribute'
|
||||
});
|
||||
},
|
||||
|
||||
'i-frame-playlist'() {
|
||||
this.manifest.iFramePlaylists.push({
|
||||
attributes: entry.attributes,
|
||||
uri: entry.uri,
|
||||
timeline: currentTimeline
|
||||
});
|
||||
this.warnOnMissingAttributes_('#EXT-X-I-FRAME-STREAM-INF', entry.attributes, ['BANDWIDTH', 'URI']);
|
||||
}
|
||||
|
||||
})[entry.tagType] || noop).call(self);
|
||||
|
@ -2022,6 +2039,14 @@
|
|||
});
|
||||
}
|
||||
|
||||
requiredCompatibilityversion(currentVersion, targetVersion) {
|
||||
if (currentVersion < targetVersion || !currentVersion) {
|
||||
this.trigger('warn', {
|
||||
message: `manifest must be at least version ${targetVersion}`
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
warnOnMissingAttributes_(identifier, attributes, required) {
|
||||
const missing = [];
|
||||
required.forEach(function (key) {
|
||||
|
@ -2282,12 +2307,27 @@
|
|||
|
||||
return type + "/" + container + ";codecs=\"" + codecString + "\"";
|
||||
};
|
||||
var browserSupportsCodec = function browserSupportsCodec(codecString) {
|
||||
/**
|
||||
* Tests whether the codec is supported by MediaSource. Optionally also tests ManagedMediaSource.
|
||||
*
|
||||
* @param {string} codecString
|
||||
* Codec to test
|
||||
* @param {boolean} [withMMS]
|
||||
* Whether to check if ManagedMediaSource supports it
|
||||
* @return {boolean}
|
||||
* Codec is supported
|
||||
*/
|
||||
|
||||
var browserSupportsCodec = function browserSupportsCodec(codecString, withMMS) {
|
||||
if (codecString === void 0) {
|
||||
codecString = '';
|
||||
}
|
||||
|
||||
return window.MediaSource && window.MediaSource.isTypeSupported && window.MediaSource.isTypeSupported(getMimeForCodec(codecString)) || false;
|
||||
if (withMMS === void 0) {
|
||||
withMMS = false;
|
||||
}
|
||||
|
||||
return window.MediaSource && window.MediaSource.isTypeSupported && window.MediaSource.isTypeSupported(getMimeForCodec(codecString)) || withMMS && window.ManagedMediaSource && window.ManagedMediaSource.isTypeSupported && window.ManagedMediaSource.isTypeSupported(getMimeForCodec(codecString)) || false;
|
||||
};
|
||||
var muxerSupportsCodec = function muxerSupportsCodec(codecString) {
|
||||
if (codecString === void 0) {
|
||||
|
@ -9813,7 +9853,7 @@
|
|||
|
||||
const removeOldMediaGroupLabels = (update, newMain) => {
|
||||
forEachMediaGroup$1(update, (properties, type, group, label) => {
|
||||
if (!(label in newMain.mediaGroups[type][group])) {
|
||||
if (!newMain.mediaGroups[type][group] || !(label in newMain.mediaGroups[type][group])) {
|
||||
delete update.mediaGroups[type][group][label];
|
||||
}
|
||||
});
|
||||
|
@ -23356,8 +23396,7 @@
|
|||
});
|
||||
|
||||
if (waitingForTimelineChange && shouldFixBadTimelineChanges(segmentLoader.timelineChangeController_)) {
|
||||
// Audio being behind should only happen on DASH sources.
|
||||
if (segmentLoader.sourceType_ === 'dash' && isAudioTimelineBehind(segmentLoader)) {
|
||||
if (isAudioTimelineBehind(segmentLoader)) {
|
||||
segmentLoader.timelineChangeController_.trigger('audioTimelineBehind');
|
||||
return;
|
||||
}
|
||||
|
@ -27748,7 +27787,7 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|||
const diff = mpegTsInSeconds - LOCAL + mappingObj.mapping;
|
||||
segmentInfo.cues.forEach(cue => {
|
||||
const duration = cue.endTime - cue.startTime;
|
||||
const startTime = MPEGTS === 0 ? cue.startTime + diff : this.handleRollover_(cue.startTime + diff, mappingObj.time);
|
||||
const startTime = this.handleRollover_(cue.startTime + diff, mappingObj.time);
|
||||
cue.startTime = Math.max(startTime, 0);
|
||||
cue.endTime = Math.max(startTime + duration, 0);
|
||||
});
|
||||
|
@ -29037,7 +29076,7 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|||
function unpad(padded) {
|
||||
return padded.subarray(0, padded.byteLength - padded[padded.byteLength - 1]);
|
||||
}
|
||||
/*! @name aes-decrypter @version 4.0.1 @license Apache-2.0 */
|
||||
/*! @name aes-decrypter @version 4.0.2 @license Apache-2.0 */
|
||||
|
||||
/**
|
||||
* @file aes.js
|
||||
|
@ -31113,7 +31152,8 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|||
cacheEncryptionKeys,
|
||||
bufferBasedABR,
|
||||
leastPixelDiffSelector,
|
||||
captionServices
|
||||
captionServices,
|
||||
experimentalUseMMS
|
||||
} = options;
|
||||
|
||||
if (!src) {
|
||||
|
@ -31153,7 +31193,16 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|||
};
|
||||
this.on('error', this.pauseLoading);
|
||||
this.mediaTypes_ = createMediaTypes();
|
||||
this.mediaSource = new window.MediaSource();
|
||||
|
||||
if (experimentalUseMMS && window.ManagedMediaSource) {
|
||||
// Airplay source not yet implemented. Remote playback must be disabled.
|
||||
this.tech_.el_.disableRemotePlayback = true;
|
||||
this.mediaSource = new window.ManagedMediaSource();
|
||||
videojs__default["default"].log('Using ManagedMediaSource');
|
||||
} else if (window.MediaSource) {
|
||||
this.mediaSource = new window.MediaSource();
|
||||
}
|
||||
|
||||
this.handleDurationChange_ = this.handleDurationChange_.bind(this);
|
||||
this.handleSourceOpen_ = this.handleSourceOpen_.bind(this);
|
||||
this.handleSourceEnded_ = this.handleSourceEnded_.bind(this);
|
||||
|
@ -31859,28 +31908,25 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|||
this.mainSegmentLoader_.on('ended', () => {
|
||||
this.logger_('main segment loader ended');
|
||||
this.onEndOfStream();
|
||||
}); // In DASH, there is the possibility of the video segment and the audio segment
|
||||
}); // There is the possibility of the video segment and the audio segment
|
||||
// at a current time to be on different timelines. When this occurs, the player
|
||||
// forwards playback to a point where these two segment types are back on the same
|
||||
// timeline. This time will be just after the end of the audio segment that is on
|
||||
// a previous timeline.
|
||||
|
||||
if (this.sourceType_ === 'dash') {
|
||||
this.timelineChangeController_.on('audioTimelineBehind', () => {
|
||||
const segmentInfo = this.audioSegmentLoader_.pendingSegment_;
|
||||
this.timelineChangeController_.on('audioTimelineBehind', () => {
|
||||
const segmentInfo = this.audioSegmentLoader_.pendingSegment_;
|
||||
|
||||
if (!segmentInfo || !segmentInfo.segment || !segmentInfo.segment.syncInfo) {
|
||||
return;
|
||||
} // Update the current time to just after the faulty audio segment.
|
||||
// This moves playback to a spot where both audio and video segments
|
||||
// are on the same timeline.
|
||||
if (!segmentInfo || !segmentInfo.segment || !segmentInfo.segment.syncInfo) {
|
||||
return;
|
||||
} // Update the current time to just after the faulty audio segment.
|
||||
// This moves playback to a spot where both audio and video segments
|
||||
// are on the same timeline.
|
||||
|
||||
|
||||
const newTime = segmentInfo.segment.syncInfo.end + 0.01;
|
||||
this.tech_.setCurrentTime(newTime);
|
||||
});
|
||||
}
|
||||
|
||||
const newTime = segmentInfo.segment.syncInfo.end + 0.01;
|
||||
this.tech_.setCurrentTime(newTime);
|
||||
});
|
||||
this.mainSegmentLoader_.on('earlyabort', event => {
|
||||
// never try to early abort with the new ABR algorithm
|
||||
if (this.bufferBasedABR) {
|
||||
|
@ -34319,15 +34365,15 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|||
initPlugin(this, options);
|
||||
};
|
||||
|
||||
var version$4 = "3.13.3";
|
||||
var version$4 = "3.14.2";
|
||||
|
||||
var version$3 = "7.0.3";
|
||||
|
||||
var version$2 = "1.3.0";
|
||||
|
||||
var version$1 = "7.1.0";
|
||||
var version$1 = "7.2.0";
|
||||
|
||||
var version = "4.0.1";
|
||||
var version = "4.0.2";
|
||||
|
||||
const Vhs = {
|
||||
PlaylistLoader,
|
||||
|
@ -35587,7 +35633,12 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|||
VERSION: version$4,
|
||||
|
||||
canHandleSource(srcObj, options = {}) {
|
||||
const localOptions = merge$1(videojs__default["default"].options, options);
|
||||
const localOptions = merge$1(videojs__default["default"].options, options); // If not opting to experimentalUseMMS, and playback is only supported with MediaSource, cannot handle source
|
||||
|
||||
if (!localOptions.vhs.experimentalUseMMS && !browserSupportsCodec('avc1.4d400d,mp4a.40.2', false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return VhsSourceHandler.canPlayType(srcObj.type, localOptions);
|
||||
},
|
||||
|
||||
|
@ -35626,14 +35677,15 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|||
|
||||
};
|
||||
/**
|
||||
* Check to see if the native MediaSource object exists and supports
|
||||
* an MP4 container with both H.264 video and AAC-LC audio.
|
||||
* Check to see if either the native MediaSource or ManagedMediaSource
|
||||
* objectx exist and support an MP4 container with both H.264 video
|
||||
* and AAC-LC audio.
|
||||
*
|
||||
* @return {boolean} if native media sources are supported
|
||||
*/
|
||||
|
||||
const supportsNativeMediaSources = () => {
|
||||
return browserSupportsCodec('avc1.4d400d,mp4a.40.2');
|
||||
return browserSupportsCodec('avc1.4d400d,mp4a.40.2', true);
|
||||
}; // register source handlers with the appropriate techs
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue