hls.js 1.6.6-0.canary.11352 → 1.6.6-0.canary.11353
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hls.d.mts +1 -0
- package/dist/hls.d.ts +1 -0
- package/dist/hls.js +126 -72
- package/dist/hls.js.d.ts +1 -0
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +135 -89
- package/dist/hls.light.js.map +1 -1
- package/dist/hls.light.min.js +1 -1
- package/dist/hls.light.min.js.map +1 -1
- package/dist/hls.light.mjs +125 -80
- package/dist/hls.light.mjs.map +1 -1
- package/dist/hls.min.js +1 -1
- package/dist/hls.min.js.map +1 -1
- package/dist/hls.mjs +117 -68
- package/dist/hls.mjs.map +1 -1
- package/dist/hls.worker.js +1 -1
- package/package.json +1 -1
- package/src/controller/abr-controller.ts +21 -7
- package/src/utils/mediacapabilities-helper.ts +135 -81
package/dist/hls.light.mjs
CHANGED
@@ -523,7 +523,7 @@ function enableLogs(debugConfig, context, id) {
|
|
523
523
|
// Some browsers don't allow to use bind on console object anyway
|
524
524
|
// fallback to default if needed
|
525
525
|
try {
|
526
|
-
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.6-0.canary.
|
526
|
+
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.6-0.canary.11353"}`);
|
527
527
|
} catch (e) {
|
528
528
|
/* log fn threw an exception. All logger methods are no-ops. */
|
529
529
|
return createLogger();
|
@@ -560,6 +560,22 @@ function requireEmptyEs() {
|
|
560
560
|
var emptyEsExports = requireEmptyEs();
|
561
561
|
var Cues = /*@__PURE__*/getDefaultExportFromCjs(emptyEsExports);
|
562
562
|
|
563
|
+
function getMediaSource(preferManagedMediaSource = true) {
|
564
|
+
if (typeof self === 'undefined') return undefined;
|
565
|
+
const mms = (preferManagedMediaSource || !self.MediaSource) && self.ManagedMediaSource;
|
566
|
+
return mms || self.MediaSource || self.WebKitMediaSource;
|
567
|
+
}
|
568
|
+
function isManagedMediaSource(source) {
|
569
|
+
return typeof self !== 'undefined' && source === self.ManagedMediaSource;
|
570
|
+
}
|
571
|
+
function isCompatibleTrackChange(currentTracks, requiredTracks) {
|
572
|
+
const trackNames = Object.keys(currentTracks);
|
573
|
+
const requiredTrackNames = Object.keys(requiredTracks);
|
574
|
+
const trackCount = trackNames.length;
|
575
|
+
const requiredTrackCount = requiredTrackNames.length;
|
576
|
+
return !trackCount || !requiredTrackCount || trackCount === requiredTrackCount && !trackNames.some(name => requiredTrackNames.indexOf(name) === -1);
|
577
|
+
}
|
578
|
+
|
563
579
|
// http://stackoverflow.com/questions/8936984/uint8array-to-string-in-javascript/22373197
|
564
580
|
// http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
|
565
581
|
/* utf.js - UTF-8 <=> UTF-16 convertion
|
@@ -2252,22 +2268,6 @@ function parseEmsg(data) {
|
|
2252
2268
|
};
|
2253
2269
|
}
|
2254
2270
|
|
2255
|
-
function getMediaSource(preferManagedMediaSource = true) {
|
2256
|
-
if (typeof self === 'undefined') return undefined;
|
2257
|
-
const mms = (preferManagedMediaSource || !self.MediaSource) && self.ManagedMediaSource;
|
2258
|
-
return mms || self.MediaSource || self.WebKitMediaSource;
|
2259
|
-
}
|
2260
|
-
function isManagedMediaSource(source) {
|
2261
|
-
return typeof self !== 'undefined' && source === self.ManagedMediaSource;
|
2262
|
-
}
|
2263
|
-
function isCompatibleTrackChange(currentTracks, requiredTracks) {
|
2264
|
-
const trackNames = Object.keys(currentTracks);
|
2265
|
-
const requiredTrackNames = Object.keys(requiredTracks);
|
2266
|
-
const trackCount = trackNames.length;
|
2267
|
-
const requiredTrackCount = requiredTrackNames.length;
|
2268
|
-
return !trackCount || !requiredTrackCount || trackCount === requiredTrackCount && !trackNames.some(name => requiredTrackNames.indexOf(name) === -1);
|
2269
|
-
}
|
2270
|
-
|
2271
2271
|
const userAgentHevcSupportIsInaccurate = () => {
|
2272
2272
|
return /\(Windows.+Firefox\//i.test(navigator.userAgent);
|
2273
2273
|
};
|
@@ -2958,6 +2958,7 @@ class AbrController extends Logger {
|
|
2958
2958
|
this.partCurrent = null;
|
2959
2959
|
this.bitrateTestDelay = 0;
|
2960
2960
|
this.rebufferNotice = -1;
|
2961
|
+
this.supportedCache = {};
|
2961
2962
|
this.bwEstimator = void 0;
|
2962
2963
|
/*
|
2963
2964
|
This method monitors the download rate of the current fragment, and will downswitch if that fragment will not load
|
@@ -3168,13 +3169,14 @@ class AbrController extends Logger {
|
|
3168
3169
|
this.unregisterListeners();
|
3169
3170
|
this.clearTimer();
|
3170
3171
|
// @ts-ignore
|
3171
|
-
this.hls = this._abandonRulesCheck = null;
|
3172
|
+
this.hls = this._abandonRulesCheck = this.supportedCache = null;
|
3172
3173
|
this.fragCurrent = this.partCurrent = null;
|
3173
3174
|
}
|
3174
3175
|
onManifestLoading(event, data) {
|
3175
3176
|
this.lastLoadedFragLevel = -1;
|
3176
3177
|
this.firstSelection = -1;
|
3177
3178
|
this.lastLevelLoadSec = 0;
|
3179
|
+
this.supportedCache = {};
|
3178
3180
|
this.fragCurrent = this.partCurrent = null;
|
3179
3181
|
this.onLevelsUpdated();
|
3180
3182
|
this.clearTimer();
|
@@ -3535,7 +3537,7 @@ class AbrController extends Logger {
|
|
3535
3537
|
const ttfbEstimateSec = this.bwEstimator.getEstimateTTFB() / 1000;
|
3536
3538
|
const levelsSkipped = [];
|
3537
3539
|
for (let i = maxAutoLevel; i >= minAutoLevel; i--) {
|
3538
|
-
var _levelInfo$supportedR;
|
3540
|
+
var _levelInfo$supportedR, _levelInfo$supportedR2;
|
3539
3541
|
const levelInfo = levels[i];
|
3540
3542
|
const upSwitch = i > selectionBaseLevel;
|
3541
3543
|
if (!levelInfo) {
|
@@ -3544,7 +3546,7 @@ class AbrController extends Logger {
|
|
3544
3546
|
|
3545
3547
|
// skip candidates which change codec-family or video-range,
|
3546
3548
|
// and which decrease or increase frame-rate for up and down-switch respectfully
|
3547
|
-
if (currentCodecSet && levelInfo.codecSet !== currentCodecSet || currentVideoRange && levelInfo.videoRange !== currentVideoRange || upSwitch && currentFrameRate > levelInfo.frameRate || !upSwitch && currentFrameRate > 0 && currentFrameRate < levelInfo.frameRate || levelInfo.supportedResult &&
|
3549
|
+
if (currentCodecSet && levelInfo.codecSet !== currentCodecSet || currentVideoRange && levelInfo.videoRange !== currentVideoRange || upSwitch && currentFrameRate > levelInfo.frameRate || !upSwitch && currentFrameRate > 0 && currentFrameRate < levelInfo.frameRate || (_levelInfo$supportedR = levelInfo.supportedResult) != null && (_levelInfo$supportedR2 = _levelInfo$supportedR.decodingInfoResults) != null && _levelInfo$supportedR2.some(info => info.smooth === false)) {
|
3548
3550
|
if (!firstSelection || i !== minStartIndex) {
|
3549
3551
|
levelsSkipped.push(i);
|
3550
3552
|
continue;
|
@@ -19889,7 +19891,7 @@ function assignTrackIdsByGroup(tracks) {
|
|
19889
19891
|
});
|
19890
19892
|
}
|
19891
19893
|
|
19892
|
-
const version = "1.6.6-0.canary.
|
19894
|
+
const version = "1.6.6-0.canary.11353";
|
19893
19895
|
|
19894
19896
|
// ensure the worker ends up in the bundle
|
19895
19897
|
// If the worker should not be included this gets aliased to empty.js
|
@@ -22442,68 +22444,43 @@ function getUnsupportedResult(error, configurations) {
|
|
22442
22444
|
error
|
22443
22445
|
};
|
22444
22446
|
}
|
22445
|
-
|
22446
|
-
function getMediaDecodingInfoPromise(level, audioTracksByGroup, mediaCapabilities) {
|
22447
|
+
function getMediaDecodingInfoPromise(level, audioTracksByGroup, mediaCapabilities, cache = {}) {
|
22447
22448
|
const videoCodecs = level.videoCodec;
|
22448
|
-
|
22449
|
-
if (!videoCodecs && !audioCodecs || !mediaCapabilities) {
|
22449
|
+
if (!videoCodecs && !level.audioCodec || !mediaCapabilities) {
|
22450
22450
|
return Promise.resolve(SUPPORTED_INFO_DEFAULT);
|
22451
22451
|
}
|
22452
22452
|
const configurations = [];
|
22453
|
-
|
22454
|
-
|
22455
|
-
|
22456
|
-
|
22457
|
-
|
22458
|
-
|
22459
|
-
|
22453
|
+
const videoDecodeList = makeVideoConfigurations(level);
|
22454
|
+
const videoCount = videoDecodeList.length;
|
22455
|
+
const audioDecodeList = makeAudioConfigurations(level, audioTracksByGroup, videoCount > 0);
|
22456
|
+
const audioCount = audioDecodeList.length;
|
22457
|
+
for (let i = videoCount || 1 * audioCount || 1; i--;) {
|
22458
|
+
const configuration = {
|
22459
|
+
type: 'media-source'
|
22460
22460
|
};
|
22461
|
-
|
22462
|
-
|
22463
|
-
|
22461
|
+
if (videoCount) {
|
22462
|
+
configuration.video = videoDecodeList[i % videoCount];
|
22463
|
+
}
|
22464
|
+
if (audioCount) {
|
22465
|
+
configuration.audio = audioDecodeList[i % audioCount];
|
22466
|
+
const audioBitrate = configuration.audio.bitrate;
|
22467
|
+
if (configuration.video && audioBitrate) {
|
22468
|
+
configuration.video.bitrate -= audioBitrate;
|
22469
|
+
}
|
22464
22470
|
}
|
22465
|
-
|
22471
|
+
configurations.push(configuration);
|
22472
|
+
}
|
22473
|
+
if (videoCodecs) {
|
22466
22474
|
// Override Windows Firefox HEVC MediaCapabilities result (https://github.com/video-dev/hls.js/issues/7046)
|
22467
22475
|
const ua = navigator.userAgent;
|
22468
|
-
if (
|
22469
|
-
return Promise.resolve(getUnsupportedResult(new Error(`Overriding Windows Firefox HEVC MediaCapabilities result based on user-agent
|
22476
|
+
if (videoCodecs.split(',').some(videoCodec => isHEVC(videoCodec)) && userAgentHevcSupportIsInaccurate()) {
|
22477
|
+
return Promise.resolve(getUnsupportedResult(new Error(`Overriding Windows Firefox HEVC MediaCapabilities result based on user-agent string: (${ua})`), configurations));
|
22470
22478
|
}
|
22471
|
-
configurations.push.apply(configurations, videoCodecsArray.map(videoCodec => ({
|
22472
|
-
type: 'media-source',
|
22473
|
-
video: _objectSpread2(_objectSpread2({}, baseVideoConfiguration), {}, {
|
22474
|
-
contentType: mimeTypeForCodec(fillInMissingAV01Params(videoCodec), 'video')
|
22475
|
-
})
|
22476
|
-
})));
|
22477
|
-
}
|
22478
|
-
if (audioCodecs && level.audioGroups) {
|
22479
|
-
level.audioGroups.forEach(audioGroupId => {
|
22480
|
-
var _audioTracksByGroup$g;
|
22481
|
-
if (!audioGroupId) {
|
22482
|
-
return;
|
22483
|
-
}
|
22484
|
-
(_audioTracksByGroup$g = audioTracksByGroup.groups[audioGroupId]) == null ? void 0 : _audioTracksByGroup$g.tracks.forEach(audioTrack => {
|
22485
|
-
if (audioTrack.groupId === audioGroupId) {
|
22486
|
-
const channels = audioTrack.channels || '';
|
22487
|
-
const channelsNumber = parseFloat(channels);
|
22488
|
-
if (isFiniteNumber(channelsNumber) && channelsNumber > 2) {
|
22489
|
-
configurations.push.apply(configurations, audioCodecs.split(',').map(audioCodec => ({
|
22490
|
-
type: 'media-source',
|
22491
|
-
audio: {
|
22492
|
-
contentType: mimeTypeForCodec(audioCodec, 'audio'),
|
22493
|
-
channels: '' + channelsNumber
|
22494
|
-
// spatialRendering:
|
22495
|
-
// audioCodec === 'ec-3' && channels.indexOf('JOC'),
|
22496
|
-
}
|
22497
|
-
})));
|
22498
|
-
}
|
22499
|
-
}
|
22500
|
-
});
|
22501
|
-
});
|
22502
22479
|
}
|
22503
22480
|
return Promise.all(configurations.map(configuration => {
|
22504
22481
|
// Cache MediaCapabilities promises
|
22505
22482
|
const decodingInfoKey = getMediaDecodingInfoKey(configuration);
|
22506
|
-
return
|
22483
|
+
return cache[decodingInfoKey] || (cache[decodingInfoKey] = mediaCapabilities.decodingInfo(configuration));
|
22507
22484
|
})).then(decodingInfoResults => ({
|
22508
22485
|
supported: !decodingInfoResults.some(info => !info.supported),
|
22509
22486
|
configurations,
|
@@ -22515,22 +22492,90 @@ function getMediaDecodingInfoPromise(level, audioTracksByGroup, mediaCapabilitie
|
|
22515
22492
|
error
|
22516
22493
|
}));
|
22517
22494
|
}
|
22495
|
+
function makeVideoConfigurations(level) {
|
22496
|
+
var _level$videoCodec;
|
22497
|
+
const videoCodecs = (_level$videoCodec = level.videoCodec) == null ? void 0 : _level$videoCodec.split(',');
|
22498
|
+
const bitrate = getVariantDecodingBitrate(level);
|
22499
|
+
const width = level.width || 640;
|
22500
|
+
const height = level.height || 480;
|
22501
|
+
// Assume a framerate of 30fps since MediaCapabilities will not accept Level default of 0.
|
22502
|
+
const framerate = level.frameRate || 30;
|
22503
|
+
const videoRange = level.videoRange.toLowerCase();
|
22504
|
+
return videoCodecs ? videoCodecs.map(videoCodec => {
|
22505
|
+
const videoConfiguration = {
|
22506
|
+
contentType: mimeTypeForCodec(fillInMissingAV01Params(videoCodec), 'video'),
|
22507
|
+
width,
|
22508
|
+
height,
|
22509
|
+
bitrate,
|
22510
|
+
framerate
|
22511
|
+
};
|
22512
|
+
if (videoRange !== 'sdr') {
|
22513
|
+
videoConfiguration.transferFunction = videoRange;
|
22514
|
+
}
|
22515
|
+
return videoConfiguration;
|
22516
|
+
}) : [];
|
22517
|
+
}
|
22518
|
+
function makeAudioConfigurations(level, audioTracksByGroup, hasVideo) {
|
22519
|
+
var _level$audioCodec;
|
22520
|
+
const audioCodecs = (_level$audioCodec = level.audioCodec) == null ? void 0 : _level$audioCodec.split(',');
|
22521
|
+
const combinedBitrate = getVariantDecodingBitrate(level);
|
22522
|
+
if (audioCodecs && level.audioGroups) {
|
22523
|
+
return level.audioGroups.reduce((configurations, audioGroupId) => {
|
22524
|
+
var _audioTracksByGroup$g;
|
22525
|
+
const tracks = audioGroupId ? (_audioTracksByGroup$g = audioTracksByGroup.groups[audioGroupId]) == null ? void 0 : _audioTracksByGroup$g.tracks : null;
|
22526
|
+
if (tracks) {
|
22527
|
+
return tracks.reduce((configs, audioTrack) => {
|
22528
|
+
if (audioTrack.groupId === audioGroupId) {
|
22529
|
+
const channelsNumber = parseFloat(audioTrack.channels || '');
|
22530
|
+
audioCodecs.forEach(audioCodec => {
|
22531
|
+
const audioConfiguration = {
|
22532
|
+
contentType: mimeTypeForCodec(audioCodec, 'audio'),
|
22533
|
+
bitrate: hasVideo ? estimatedAudioBitrate(audioCodec, combinedBitrate) : combinedBitrate
|
22534
|
+
};
|
22535
|
+
if (channelsNumber) {
|
22536
|
+
audioConfiguration.channels = '' + channelsNumber;
|
22537
|
+
}
|
22538
|
+
configs.push(audioConfiguration);
|
22539
|
+
});
|
22540
|
+
}
|
22541
|
+
return configs;
|
22542
|
+
}, configurations);
|
22543
|
+
}
|
22544
|
+
return configurations;
|
22545
|
+
}, []);
|
22546
|
+
}
|
22547
|
+
return [];
|
22548
|
+
}
|
22549
|
+
function estimatedAudioBitrate(audioCodec, levelBitrate) {
|
22550
|
+
if (levelBitrate <= 1) {
|
22551
|
+
return 1;
|
22552
|
+
}
|
22553
|
+
let audioBitrate = 128000;
|
22554
|
+
if (audioCodec === 'ec-3') {
|
22555
|
+
audioBitrate = 768000;
|
22556
|
+
} else if (audioCodec === 'ac-3') {
|
22557
|
+
audioBitrate = 640000;
|
22558
|
+
}
|
22559
|
+
return Math.min(levelBitrate / 2, audioBitrate); // Don't exceed some % of level bitrate
|
22560
|
+
}
|
22561
|
+
function getVariantDecodingBitrate(level) {
|
22562
|
+
return Math.ceil(Math.max(level.bitrate * 0.9, level.averageBitrate) / 1000) * 1000 || 1;
|
22563
|
+
}
|
22518
22564
|
function getMediaDecodingInfoKey(config) {
|
22565
|
+
let key = '';
|
22519
22566
|
const {
|
22520
22567
|
audio,
|
22521
22568
|
video
|
22522
22569
|
} = config;
|
22523
|
-
|
22524
|
-
|
22525
|
-
|
22526
|
-
|
22527
|
-
|
22528
|
-
|
22529
|
-
|
22530
|
-
return `c${audio.channels}${audio.spatialRendering ? 's' : 'n'}_${codec}`;
|
22531
|
-
}
|
22570
|
+
if (video) {
|
22571
|
+
const codec = getCodecsForMimeType(video.contentType);
|
22572
|
+
key += `${codec}_r${video.height}x${video.width}f${Math.ceil(video.framerate)}${video.transferFunction || 'sd'}_${Math.ceil(video.bitrate / 1e5)}`;
|
22573
|
+
}
|
22574
|
+
if (audio) {
|
22575
|
+
const codec = getCodecsForMimeType(audio.contentType);
|
22576
|
+
key += `${video ? '_' : ''}${codec}_c${audio.channels}`;
|
22532
22577
|
}
|
22533
|
-
return
|
22578
|
+
return key;
|
22534
22579
|
}
|
22535
22580
|
|
22536
22581
|
/**
|