hls.js 1.5.14-0.canary.10668 → 1.5.14-0.canary.10669
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 +8 -4
- package/dist/hls.d.ts +8 -4
- package/dist/hls.js +134 -57
- package/dist/hls.js.d.ts +8 -4
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +212 -36
- 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 +191 -28
- 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 +120 -48
- package/dist/hls.mjs.map +1 -1
- package/dist/hls.worker.js +1 -1
- package/dist/hls.worker.js.map +1 -1
- package/package.json +1 -1
- package/src/controller/buffer-controller.ts +2 -2
- package/src/controller/level-controller.ts +44 -21
- package/src/controller/stream-controller.ts +30 -3
- package/src/hls.ts +24 -4
- package/src/remux/passthrough-remuxer.ts +7 -15
- package/src/utils/codecs.ts +36 -6
- package/src/utils/mediacapabilities-helper.ts +30 -23
- package/src/utils/mediakeys-helper.ts +2 -2
package/dist/hls.mjs
CHANGED
@@ -440,7 +440,7 @@ function enableLogs(debugConfig, context, id) {
|
|
440
440
|
// Some browsers don't allow to use bind on console object anyway
|
441
441
|
// fallback to default if needed
|
442
442
|
try {
|
443
|
-
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.5.14-0.canary.
|
443
|
+
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.5.14-0.canary.10669"}`);
|
444
444
|
} catch (e) {
|
445
445
|
/* log fn threw an exception. All logger methods are no-ops. */
|
446
446
|
return createLogger();
|
@@ -1391,12 +1391,12 @@ function createMediaKeySystemConfigurations(initDataTypes, audioCodecs, videoCod
|
|
1391
1391
|
distinctiveIdentifier: drmSystemOptions.distinctiveIdentifier || 'optional',
|
1392
1392
|
sessionTypes: drmSystemOptions.sessionTypes || [drmSystemOptions.sessionType || 'temporary'],
|
1393
1393
|
audioCapabilities: audioCodecs.map(codec => ({
|
1394
|
-
contentType: `audio/mp4; codecs
|
1394
|
+
contentType: `audio/mp4; codecs=${codec}`,
|
1395
1395
|
robustness: drmSystemOptions.audioRobustness || '',
|
1396
1396
|
encryptionScheme: drmSystemOptions.audioEncryptionScheme || null
|
1397
1397
|
})),
|
1398
1398
|
videoCapabilities: videoCodecs.map(codec => ({
|
1399
|
-
contentType: `video/mp4; codecs
|
1399
|
+
contentType: `video/mp4; codecs=${codec}`,
|
1400
1400
|
robustness: drmSystemOptions.videoRobustness || '',
|
1401
1401
|
encryptionScheme: drmSystemOptions.videoEncryptionScheme || null
|
1402
1402
|
}))
|
@@ -2926,7 +2926,7 @@ function isCodecMediaSourceSupported(codec, type, preferManagedMediaSource = tru
|
|
2926
2926
|
return (_MediaSource$isTypeSu = MediaSource == null ? void 0 : MediaSource.isTypeSupported(mimeTypeForCodec(codec, type))) != null ? _MediaSource$isTypeSu : false;
|
2927
2927
|
}
|
2928
2928
|
function mimeTypeForCodec(codec, type) {
|
2929
|
-
return `${type}/mp4;codecs
|
2929
|
+
return `${type}/mp4;codecs=${codec}`;
|
2930
2930
|
}
|
2931
2931
|
function videoCodecPreferenceValue(videoCodec) {
|
2932
2932
|
if (videoCodec) {
|
@@ -2977,15 +2977,28 @@ function getCodecCompatibleName(codec, preferManagedMediaSource = true) {
|
|
2977
2977
|
function pickMostCompleteCodecName(parsedCodec, levelCodec) {
|
2978
2978
|
// Parsing of mp4a codecs strings in mp4-tools from media is incomplete as of d8c6c7a
|
2979
2979
|
// so use level codec is parsed codec is unavailable or incomplete
|
2980
|
-
if (parsedCodec && parsedCodec
|
2980
|
+
if (parsedCodec && (parsedCodec.length > 4 || ['ac-3', 'ec-3', 'alac', 'fLaC', 'Opus'].indexOf(parsedCodec) !== -1)) {
|
2981
2981
|
return parsedCodec;
|
2982
2982
|
}
|
2983
|
-
|
2983
|
+
if (levelCodec) {
|
2984
|
+
const levelCodecs = levelCodec.split(',');
|
2985
|
+
if (levelCodecs.length > 1) {
|
2986
|
+
if (parsedCodec) {
|
2987
|
+
for (let i = levelCodecs.length; i--;) {
|
2988
|
+
if (levelCodecs[i].substring(0, 4) === parsedCodec.substring(0, 4)) {
|
2989
|
+
return levelCodecs[i];
|
2990
|
+
}
|
2991
|
+
}
|
2992
|
+
}
|
2993
|
+
return levelCodecs[0];
|
2994
|
+
}
|
2995
|
+
}
|
2996
|
+
return levelCodec || parsedCodec;
|
2984
2997
|
}
|
2985
|
-
function convertAVC1ToAVCOTI(
|
2998
|
+
function convertAVC1ToAVCOTI(videoCodecs) {
|
2986
2999
|
// Convert avc1 codec string from RFC-4281 to RFC-6381 for MediaSource.isTypeSupported
|
2987
3000
|
// Examples: avc1.66.30 to avc1.42001e and avc1.77.30,avc1.66.30 to avc1.4d001e,avc1.42001e.
|
2988
|
-
const codecs =
|
3001
|
+
const codecs = videoCodecs.split(',');
|
2989
3002
|
for (let i = 0; i < codecs.length; i++) {
|
2990
3003
|
const avcdata = codecs[i].split('.');
|
2991
3004
|
if (avcdata.length > 2) {
|
@@ -2997,6 +3010,18 @@ function convertAVC1ToAVCOTI(codec) {
|
|
2997
3010
|
}
|
2998
3011
|
return codecs.join(',');
|
2999
3012
|
}
|
3013
|
+
function fillInMissingAV01Params(videoCodec) {
|
3014
|
+
// Used to fill in incomplete AV1 playlist CODECS strings for mediaCapabilities.decodingInfo queries
|
3015
|
+
if (videoCodec.startsWith('av01.')) {
|
3016
|
+
const av1params = videoCodec.split('.');
|
3017
|
+
const placeholders = ['0', '111', '01', '01', '01', '0'];
|
3018
|
+
for (let i = av1params.length; i > 4 && i < 10; i++) {
|
3019
|
+
av1params[i] = placeholders[i - 4];
|
3020
|
+
}
|
3021
|
+
return av1params.join('.');
|
3022
|
+
}
|
3023
|
+
return videoCodec;
|
3024
|
+
}
|
3000
3025
|
function getM2TSSupportedAudioTypes(preferManagedMediaSource) {
|
3001
3026
|
const MediaSource = getMediaSource(preferManagedMediaSource) || {
|
3002
3027
|
isTypeSupported: () => false
|
@@ -6965,10 +6990,27 @@ class LevelController extends BasePlaylistController {
|
|
6965
6990
|
height,
|
6966
6991
|
unknownCodecs
|
6967
6992
|
} = levelParsed;
|
6993
|
+
let unknownUnsupportedCodecCount = unknownCodecs ? unknownCodecs.length : 0;
|
6994
|
+
if (unknownCodecs) {
|
6995
|
+
// Treat unknown codec as audio or video codec based on passing `isTypeSupported` check
|
6996
|
+
// (allows for playback of any supported codec even if not indexed in utils/codecs)
|
6997
|
+
for (let i = unknownUnsupportedCodecCount; i--;) {
|
6998
|
+
const unknownCodec = unknownCodecs[i];
|
6999
|
+
if (this.isAudioSupported(unknownCodec)) {
|
7000
|
+
levelParsed.audioCodec = audioCodec = audioCodec ? `${audioCodec},${unknownCodec}` : unknownCodec;
|
7001
|
+
unknownUnsupportedCodecCount--;
|
7002
|
+
sampleEntryCodesISO.audio[audioCodec.substring(0, 4)] = 2;
|
7003
|
+
} else if (this.isVideoSupported(unknownCodec)) {
|
7004
|
+
levelParsed.videoCodec = videoCodec = videoCodec ? `${videoCodec},${unknownCodec}` : unknownCodec;
|
7005
|
+
unknownUnsupportedCodecCount--;
|
7006
|
+
sampleEntryCodesISO.video[videoCodec.substring(0, 4)] = 2;
|
7007
|
+
}
|
7008
|
+
}
|
7009
|
+
}
|
6968
7010
|
resolutionFound || (resolutionFound = !!(width && height));
|
6969
7011
|
videoCodecFound || (videoCodecFound = !!videoCodec);
|
6970
7012
|
audioCodecFound || (audioCodecFound = !!audioCodec);
|
6971
|
-
if (
|
7013
|
+
if (unknownUnsupportedCodecCount || audioCodec && !this.isAudioSupported(audioCodec) || videoCodec && !this.isVideoSupported(videoCodec)) {
|
6972
7014
|
return;
|
6973
7015
|
}
|
6974
7016
|
const {
|
@@ -7001,6 +7043,12 @@ class LevelController extends BasePlaylistController {
|
|
7001
7043
|
});
|
7002
7044
|
this.filterAndSortMediaOptions(levels, data, resolutionFound, videoCodecFound, audioCodecFound);
|
7003
7045
|
}
|
7046
|
+
isAudioSupported(codec) {
|
7047
|
+
return areCodecsMediaSourceSupported(codec, 'audio', this.hls.config.preferManagedMediaSource);
|
7048
|
+
}
|
7049
|
+
isVideoSupported(codec) {
|
7050
|
+
return areCodecsMediaSourceSupported(codec, 'video', this.hls.config.preferManagedMediaSource);
|
7051
|
+
}
|
7004
7052
|
filterAndSortMediaOptions(filteredLevels, data, resolutionFound, videoCodecFound, audioCodecFound) {
|
7005
7053
|
let audioTracks = [];
|
7006
7054
|
let subtitleTracks = [];
|
@@ -7036,10 +7084,7 @@ class LevelController extends BasePlaylistController {
|
|
7036
7084
|
return;
|
7037
7085
|
}
|
7038
7086
|
if (data.audioTracks) {
|
7039
|
-
|
7040
|
-
preferManagedMediaSource
|
7041
|
-
} = this.hls.config;
|
7042
|
-
audioTracks = data.audioTracks.filter(track => !track.audioCodec || areCodecsMediaSourceSupported(track.audioCodec, 'audio', preferManagedMediaSource));
|
7087
|
+
audioTracks = data.audioTracks.filter(track => !track.audioCodec || this.isAudioSupported(track.audioCodec));
|
7043
7088
|
// Assign ids after filtering as array indices by group-id
|
7044
7089
|
assignTrackIdsByGroup(audioTracks);
|
7045
7090
|
}
|
@@ -10768,7 +10813,7 @@ function changeTypeSupported() {
|
|
10768
10813
|
return typeof (sourceBuffer == null ? void 0 : (_sourceBuffer$prototy = sourceBuffer.prototype) == null ? void 0 : _sourceBuffer$prototy.changeType) === 'function';
|
10769
10814
|
}
|
10770
10815
|
|
10771
|
-
const version = "1.5.14-0.canary.
|
10816
|
+
const version = "1.5.14-0.canary.10669";
|
10772
10817
|
|
10773
10818
|
// ensure the worker ends up in the bundle
|
10774
10819
|
// If the worker should not be included this gets aliased to empty.js
|
@@ -15610,7 +15655,7 @@ class PassThroughRemuxer {
|
|
15610
15655
|
}
|
15611
15656
|
const initData = this.initData = parseInitSegment(initSegment);
|
15612
15657
|
|
15613
|
-
// Get codec from initSegment
|
15658
|
+
// Get codec from initSegment
|
15614
15659
|
if (initData.audio) {
|
15615
15660
|
audioCodec = getParsedTrackCodec(initData.audio, ElementaryStreamTypes.AUDIO);
|
15616
15661
|
}
|
@@ -15765,20 +15810,13 @@ function getParsedTrackCodec(track, type) {
|
|
15765
15810
|
const preferManagedMediaSource = false;
|
15766
15811
|
return getCodecCompatibleName(parsedCodec, preferManagedMediaSource);
|
15767
15812
|
}
|
15768
|
-
|
15769
|
-
|
15770
|
-
return result;
|
15813
|
+
logger.warn(`Unhandled audio codec "${parsedCodec}" in mp4 MAP`);
|
15814
|
+
return parsedCodec || 'mp4a';
|
15771
15815
|
}
|
15772
15816
|
// Provide defaults based on codec type
|
15773
15817
|
// This allows for some playback of some fmp4 playlists without CODECS defined in manifest
|
15774
|
-
|
15775
|
-
|
15776
|
-
return 'hvc1.1.6.L120.90';
|
15777
|
-
}
|
15778
|
-
if (parsedCodec === 'av01') {
|
15779
|
-
return 'av01.0.04M.08';
|
15780
|
-
}
|
15781
|
-
return 'avc1.42e01e';
|
15818
|
+
logger.warn(`Unhandled video codec "${parsedCodec}" in mp4 MAP`);
|
15819
|
+
return parsedCodec || 'avc1';
|
15782
15820
|
}
|
15783
15821
|
|
15784
15822
|
let now;
|
@@ -18244,7 +18282,13 @@ class StreamController extends BaseStreamController {
|
|
18244
18282
|
audiovideo
|
18245
18283
|
} = tracks;
|
18246
18284
|
if (audio) {
|
18247
|
-
let audioCodec = currentLevel.audioCodec;
|
18285
|
+
let audioCodec = pickMostCompleteCodecName(audio.codec, currentLevel.audioCodec);
|
18286
|
+
// Add level and profile to make up for passthrough-remuxer not being able to parse full codec
|
18287
|
+
// (logger warning "Unhandled audio codec...")
|
18288
|
+
if (audioCodec === 'mp4a') {
|
18289
|
+
audioCodec = 'mp4a.40.5';
|
18290
|
+
}
|
18291
|
+
// Handle `audioCodecSwitch`
|
18248
18292
|
const ua = navigator.userAgent.toLowerCase();
|
18249
18293
|
if (this.audioCodecSwitch) {
|
18250
18294
|
if (audioCodec) {
|
@@ -18279,7 +18323,24 @@ class StreamController extends BaseStreamController {
|
|
18279
18323
|
if (video) {
|
18280
18324
|
video.levelCodec = currentLevel.videoCodec;
|
18281
18325
|
video.id = 'main';
|
18282
|
-
|
18326
|
+
const parsedVideoCodec = video.codec;
|
18327
|
+
if ((parsedVideoCodec == null ? void 0 : parsedVideoCodec.length) === 4) {
|
18328
|
+
// Make up for passthrough-remuxer not being able to parse full codec
|
18329
|
+
// (logger warning "Unhandled video codec...")
|
18330
|
+
switch (parsedVideoCodec) {
|
18331
|
+
case 'hvc1':
|
18332
|
+
case 'hev1':
|
18333
|
+
video.codec = 'hvc1.1.6.L120.90';
|
18334
|
+
break;
|
18335
|
+
case 'av01':
|
18336
|
+
video.codec = 'av01.0.04M.08';
|
18337
|
+
break;
|
18338
|
+
case 'avc1':
|
18339
|
+
video.codec = 'avc1.42e01e';
|
18340
|
+
break;
|
18341
|
+
}
|
18342
|
+
}
|
18343
|
+
this.log(`Init video buffer, container:${video.container}, codecs[level/parsed]=[${currentLevel.videoCodec || ''}/${parsedVideoCodec}${video.codec !== parsedVideoCodec ? ' parsed-corrected=' + video.codec : ''}}]`);
|
18283
18344
|
delete tracks.audiovideo;
|
18284
18345
|
}
|
18285
18346
|
if (audiovideo) {
|
@@ -18601,26 +18662,29 @@ function requiresMediaCapabilitiesDecodingInfo(level, audioTracksByGroup, curren
|
|
18601
18662
|
function getMediaDecodingInfoPromise(level, audioTracksByGroup, mediaCapabilities) {
|
18602
18663
|
const videoCodecs = level.videoCodec;
|
18603
18664
|
const audioCodecs = level.audioCodec;
|
18604
|
-
if (!videoCodecs
|
18665
|
+
if (!videoCodecs && !audioCodecs || !mediaCapabilities) {
|
18605
18666
|
return Promise.resolve(SUPPORTED_INFO_DEFAULT);
|
18606
18667
|
}
|
18607
|
-
const
|
18608
|
-
|
18609
|
-
|
18610
|
-
|
18611
|
-
|
18612
|
-
|
18613
|
-
|
18614
|
-
|
18615
|
-
|
18616
|
-
|
18617
|
-
|
18618
|
-
|
18619
|
-
|
18620
|
-
|
18621
|
-
|
18622
|
-
|
18623
|
-
|
18668
|
+
const configurations = [];
|
18669
|
+
if (videoCodecs) {
|
18670
|
+
const baseVideoConfiguration = {
|
18671
|
+
width: level.width,
|
18672
|
+
height: level.height,
|
18673
|
+
bitrate: Math.ceil(Math.max(level.bitrate * 0.9, level.averageBitrate)),
|
18674
|
+
// Assume a framerate of 30fps since MediaCapabilities will not accept Level default of 0.
|
18675
|
+
framerate: level.frameRate || 30
|
18676
|
+
};
|
18677
|
+
const videoRange = level.videoRange;
|
18678
|
+
if (videoRange !== 'SDR') {
|
18679
|
+
baseVideoConfiguration.transferFunction = videoRange.toLowerCase();
|
18680
|
+
}
|
18681
|
+
configurations.push.apply(configurations, videoCodecs.split(',').map(videoCodec => ({
|
18682
|
+
type: 'media-source',
|
18683
|
+
video: _objectSpread2(_objectSpread2({}, baseVideoConfiguration), {}, {
|
18684
|
+
contentType: mimeTypeForCodec(fillInMissingAV01Params(videoCodec), 'video')
|
18685
|
+
})
|
18686
|
+
})));
|
18687
|
+
}
|
18624
18688
|
if (audioCodecs && level.audioGroups) {
|
18625
18689
|
level.audioGroups.forEach(audioGroupId => {
|
18626
18690
|
var _audioTracksByGroup$g;
|
@@ -22362,7 +22426,7 @@ transfer tracks: ${JSON.stringify(transferredTracks, (key, value) => key === 'in
|
|
22362
22426
|
if (trackName.slice(0, 5) === 'audio') {
|
22363
22427
|
trackCodec = getCodecCompatibleName(trackCodec, this.appendSource);
|
22364
22428
|
}
|
22365
|
-
this.log(`switching codec ${sbCodec} to ${
|
22429
|
+
this.log(`switching codec ${sbCodec} to ${trackCodec}`);
|
22366
22430
|
if (trackCodec !== (track.pendingCodec || track.codec)) {
|
22367
22431
|
track.pendingCodec = trackCodec;
|
22368
22432
|
}
|
@@ -23045,7 +23109,7 @@ transfer tracks: ${JSON.stringify(transferredTracks, (key, value) => key === 'in
|
|
23045
23109
|
}
|
23046
23110
|
}
|
23047
23111
|
getTrackCodec(track, trackName) {
|
23048
|
-
const codec = track.codec
|
23112
|
+
const codec = pickMostCompleteCodecName(track.codec, track.levelCodec);
|
23049
23113
|
if (codec) {
|
23050
23114
|
if (trackName.slice(0, 5) === 'audio') {
|
23051
23115
|
return getCodecCompatibleName(codec, this.appendSource);
|
@@ -33700,6 +33764,14 @@ class Hls {
|
|
33700
33764
|
var _this$interstitialsCo;
|
33701
33765
|
return ((_this$interstitialsCo = this.interstitialsController) == null ? void 0 : _this$interstitialsCo.interstitialsManager) || null;
|
33702
33766
|
}
|
33767
|
+
|
33768
|
+
/**
|
33769
|
+
* returns mediaCapabilities.decodingInfo for a variant/rendition
|
33770
|
+
*/
|
33771
|
+
getMediaDecodingInfo(level, audioTracks = this.allAudioTracks) {
|
33772
|
+
const audioTracksByGroup = getAudioTracksByGroup(audioTracks);
|
33773
|
+
return getMediaDecodingInfoPromise(level, audioTracksByGroup, navigator.mediaCapabilities);
|
33774
|
+
}
|
33703
33775
|
}
|
33704
33776
|
Hls.defaultConfig = void 0;
|
33705
33777
|
|