hls.js 1.6.0-beta.1.0.canary.10750 → 1.6.0-beta.1.0.canary.10752
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/README.md +6 -11
- package/dist/hls.d.mts +5 -1
- package/dist/hls.d.ts +5 -1
- package/dist/hls.js +74 -24
- package/dist/hls.js.d.ts +5 -1
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +74 -24
- 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 +69 -23
- 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 +69 -23
- 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/abr-controller.ts +6 -5
- package/src/controller/base-stream-controller.ts +29 -21
- package/src/controller/stream-controller.ts +5 -4
- package/src/demux/transmuxer-interface.ts +4 -2
- package/src/demux/transmuxer.ts +1 -1
- package/src/loader/fragment-loader.ts +1 -1
- package/src/loader/fragment.ts +33 -0
- package/src/loader/m3u8-parser.ts +10 -0
package/dist/hls.light.mjs
CHANGED
@@ -400,7 +400,7 @@ function enableLogs(debugConfig, context, id) {
|
|
400
400
|
// Some browsers don't allow to use bind on console object anyway
|
401
401
|
// fallback to default if needed
|
402
402
|
try {
|
403
|
-
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.0-beta.1.0.canary.
|
403
|
+
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.0-beta.1.0.canary.10752"}`);
|
404
404
|
} catch (e) {
|
405
405
|
/* log fn threw an exception. All logger methods are no-ops. */
|
406
406
|
return createLogger();
|
@@ -1129,7 +1129,7 @@ class AbrController extends Logger {
|
|
1129
1129
|
const bwEstimate = this.getBwEstimate();
|
1130
1130
|
const levels = hls.levels;
|
1131
1131
|
const level = levels[frag.level];
|
1132
|
-
const expectedLen =
|
1132
|
+
const expectedLen = Math.max(stats.loaded, Math.round(duration * (frag.bitrate || level.averageBitrate) / 8));
|
1133
1133
|
let timeStreaming = loadedFirstByte ? timeLoading - ttfb : timeLoading;
|
1134
1134
|
if (timeStreaming < 1 && loadedFirstByte) {
|
1135
1135
|
timeStreaming = Math.min(timeLoading, stats.loaded * 8 / bwEstimate);
|
@@ -1662,7 +1662,7 @@ class AbrController extends Logger {
|
|
1662
1662
|
}
|
1663
1663
|
|
1664
1664
|
// Use average bitrate when starvation delay (buffer length) is gt or eq two segment durations and rebuffering is not expected (maxStarvationDelay > 0)
|
1665
|
-
const bitrate = currentFragDuration && bufferStarvationDelay >= currentFragDuration * 2 && maxStarvationDelay === 0 ?
|
1665
|
+
const bitrate = currentFragDuration && bufferStarvationDelay >= currentFragDuration * 2 && maxStarvationDelay === 0 ? levelInfo.averageBitrate : levelInfo.maxBitrate;
|
1666
1666
|
const fetchDuration = this.getTimeToLoadFrag(ttfbEstimateSec, adjustedbw, bitrate * avgDuration, levelDetails === undefined);
|
1667
1667
|
const canSwitchWithinTolerance =
|
1668
1668
|
// if adjusted bw is greater than level bitrate AND
|
@@ -2869,6 +2869,8 @@ class Fragment extends BaseSegment {
|
|
2869
2869
|
this._decryptdata = null;
|
2870
2870
|
this._programDateTime = null;
|
2871
2871
|
this._ref = null;
|
2872
|
+
// Approximate bit rate of the fragment expressed in bits per second (bps) as indicated by the last EXT-X-BITRATE (kbps) tag
|
2873
|
+
this._bitrate = void 0;
|
2872
2874
|
this.rawProgramDateTime = null;
|
2873
2875
|
this.tagList = [];
|
2874
2876
|
// EXTINF has to be present for a m3u8 to be considered valid
|
@@ -2923,6 +2925,34 @@ class Fragment extends BaseSegment {
|
|
2923
2925
|
this.urlId = 0;
|
2924
2926
|
this.type = type;
|
2925
2927
|
}
|
2928
|
+
get byteLength() {
|
2929
|
+
if (this.hasStats) {
|
2930
|
+
const total = this.stats.total;
|
2931
|
+
if (total) {
|
2932
|
+
return total;
|
2933
|
+
}
|
2934
|
+
}
|
2935
|
+
if (this.byteRange) {
|
2936
|
+
const start = this.byteRange[0];
|
2937
|
+
const end = this.byteRange[1];
|
2938
|
+
if (isFiniteNumber(start) && isFiniteNumber(end)) {
|
2939
|
+
return end - start;
|
2940
|
+
}
|
2941
|
+
}
|
2942
|
+
return null;
|
2943
|
+
}
|
2944
|
+
get bitrate() {
|
2945
|
+
if (this.byteLength) {
|
2946
|
+
return this.byteLength * 8 / this.duration;
|
2947
|
+
}
|
2948
|
+
if (this._bitrate) {
|
2949
|
+
return this._bitrate;
|
2950
|
+
}
|
2951
|
+
return null;
|
2952
|
+
}
|
2953
|
+
set bitrate(value) {
|
2954
|
+
this._bitrate = value;
|
2955
|
+
}
|
2926
2956
|
get decryptdata() {
|
2927
2957
|
const {
|
2928
2958
|
levelkeys
|
@@ -4670,6 +4700,7 @@ class M3U8Parser {
|
|
4670
4700
|
let currentPart = 0;
|
4671
4701
|
let totalduration = 0;
|
4672
4702
|
let discontinuityCounter = 0;
|
4703
|
+
let currentBitrate = 0;
|
4673
4704
|
let prevFrag = null;
|
4674
4705
|
let frag = new Fragment(type, base);
|
4675
4706
|
let result;
|
@@ -4690,6 +4721,9 @@ class M3U8Parser {
|
|
4690
4721
|
frag.start = totalduration;
|
4691
4722
|
frag.sn = currentSN;
|
4692
4723
|
frag.cc = discontinuityCounter;
|
4724
|
+
if (currentBitrate) {
|
4725
|
+
frag.bitrate = currentBitrate;
|
4726
|
+
}
|
4693
4727
|
frag.level = id;
|
4694
4728
|
if (currentInitSegment) {
|
4695
4729
|
frag.initSegment = currentInitSegment;
|
@@ -4819,6 +4853,12 @@ class M3U8Parser {
|
|
4819
4853
|
break;
|
4820
4854
|
case 'BITRATE':
|
4821
4855
|
frag.tagList.push([tag, value1]);
|
4856
|
+
currentBitrate = parseInt(value1) * 1000;
|
4857
|
+
if (isFiniteNumber(currentBitrate)) {
|
4858
|
+
frag.bitrate = currentBitrate;
|
4859
|
+
} else {
|
4860
|
+
currentBitrate = 0;
|
4861
|
+
}
|
4822
4862
|
break;
|
4823
4863
|
case 'DATERANGE':
|
4824
4864
|
{
|
@@ -7710,22 +7750,24 @@ class BaseStreamController extends TaskLoop {
|
|
7710
7750
|
this.startFragRequested = true;
|
7711
7751
|
this._loadFragForPlayback(frag, level, targetBufferTime);
|
7712
7752
|
}
|
7713
|
-
_loadFragForPlayback(
|
7753
|
+
_loadFragForPlayback(fragment, level, targetBufferTime) {
|
7714
7754
|
const progressCallback = data => {
|
7755
|
+
const frag = data.frag;
|
7715
7756
|
if (this.fragContextChanged(frag)) {
|
7716
|
-
this.warn(
|
7757
|
+
this.warn(`${frag.type} sn: ${frag.sn}${data.part ? ' part: ' + data.part.index : ''} of ${this.fragInfo(frag, false, data.part)}) was dropped during download.`);
|
7717
7758
|
this.fragmentTracker.removeFragment(frag);
|
7718
7759
|
return;
|
7719
7760
|
}
|
7720
7761
|
frag.stats.chunkCount++;
|
7721
7762
|
this._handleFragmentLoadProgress(data);
|
7722
7763
|
};
|
7723
|
-
this._doFragLoad(
|
7764
|
+
this._doFragLoad(fragment, level, targetBufferTime, progressCallback).then(data => {
|
7724
7765
|
if (!data) {
|
7725
7766
|
// if we're here we probably needed to backtrack or are waiting for more parts
|
7726
7767
|
return;
|
7727
7768
|
}
|
7728
7769
|
const state = this.state;
|
7770
|
+
const frag = data.frag;
|
7729
7771
|
if (this.fragContextChanged(frag)) {
|
7730
7772
|
if (state === State.FRAG_LOADING || !this.fragCurrent && state === State.PARSING) {
|
7731
7773
|
this.fragmentTracker.removeFragment(frag);
|
@@ -7745,7 +7787,7 @@ class BaseStreamController extends TaskLoop {
|
|
7745
7787
|
return;
|
7746
7788
|
}
|
7747
7789
|
this.warn(`Frag error: ${(reason == null ? void 0 : reason.message) || reason}`);
|
7748
|
-
this.resetFragmentLoading(
|
7790
|
+
this.resetFragmentLoading(fragment);
|
7749
7791
|
});
|
7750
7792
|
}
|
7751
7793
|
clearTrackerIfNeeded(frag) {
|
@@ -7809,9 +7851,10 @@ class BaseStreamController extends TaskLoop {
|
|
7809
7851
|
};
|
7810
7852
|
this.hls.trigger(Events.BUFFER_FLUSHING, flushScope);
|
7811
7853
|
}
|
7812
|
-
_loadInitSegment(
|
7813
|
-
this._doFragLoad(
|
7814
|
-
|
7854
|
+
_loadInitSegment(fragment, level) {
|
7855
|
+
this._doFragLoad(fragment, level).then(data => {
|
7856
|
+
const frag = data == null ? void 0 : data.frag;
|
7857
|
+
if (!frag || this.fragContextChanged(frag) || !this.levels) {
|
7815
7858
|
throw new Error('init load aborted');
|
7816
7859
|
}
|
7817
7860
|
return data;
|
@@ -7820,6 +7863,7 @@ class BaseStreamController extends TaskLoop {
|
|
7820
7863
|
hls
|
7821
7864
|
} = this;
|
7822
7865
|
const {
|
7866
|
+
frag,
|
7823
7867
|
payload
|
7824
7868
|
} = data;
|
7825
7869
|
const decryptData = frag.decryptdata;
|
@@ -7858,7 +7902,7 @@ class BaseStreamController extends TaskLoop {
|
|
7858
7902
|
return;
|
7859
7903
|
}
|
7860
7904
|
this.warn(reason);
|
7861
|
-
this.resetFragmentLoading(
|
7905
|
+
this.resetFragmentLoading(fragment);
|
7862
7906
|
});
|
7863
7907
|
}
|
7864
7908
|
completeInitSegmentLoad(data) {
|
@@ -7885,7 +7929,7 @@ class BaseStreamController extends TaskLoop {
|
|
7885
7929
|
}
|
7886
7930
|
fragBufferedComplete(frag, part) {
|
7887
7931
|
const media = this.mediaBuffer ? this.mediaBuffer : this.media;
|
7888
|
-
this.log(`Buffered ${frag.type} sn: ${frag.sn}${part ? ' part: ' + part.index : ''} of ${this.fragInfo(frag)} > buffer:${media ? TimeRanges.toString(BufferHelper.getBuffered(media)) : '(detached)'})`);
|
7932
|
+
this.log(`Buffered ${frag.type} sn: ${frag.sn}${part ? ' part: ' + part.index : ''} of ${this.fragInfo(frag, false, part)} > buffer:${media ? TimeRanges.toString(BufferHelper.getBuffered(media)) : '(detached)'})`);
|
7889
7933
|
if (frag.sn !== 'initSegment') {
|
7890
7934
|
var _this$levels;
|
7891
7935
|
if (frag.type !== PlaylistLevelType.SUBTITLE) {
|
@@ -7972,7 +8016,8 @@ class BaseStreamController extends TaskLoop {
|
|
7972
8016
|
const partIndex = this.getNextPart(partList, frag, targetBufferTime);
|
7973
8017
|
if (partIndex > -1) {
|
7974
8018
|
const part = partList[partIndex];
|
7975
|
-
|
8019
|
+
frag = this.fragCurrent = part.fragment;
|
8020
|
+
this.log(`Loading ${frag.type} sn: ${frag.sn} part: ${part.index} (${partIndex}/${partList.length - 1}) of ${this.fragInfo(frag, false, part)}) cc: ${frag.cc} [${details.startSN}-${details.endSN}], target: ${parseFloat(targetBufferTime.toFixed(3))}`);
|
7976
8021
|
this.nextLoadPosition = part.start + part.duration;
|
7977
8022
|
this.state = State.FRAG_LOADING;
|
7978
8023
|
let _result;
|
@@ -8769,7 +8814,7 @@ class BaseStreamController extends TaskLoop {
|
|
8769
8814
|
// For this error fallthrough. Marking parsed will allow advancing to next fragment.
|
8770
8815
|
}
|
8771
8816
|
this.state = State.PARSED;
|
8772
|
-
this.log(`Parsed ${frag.type} sn: ${frag.sn}${part ? ' part: ' + part.index : ''} of ${this.fragInfo(frag)})`);
|
8817
|
+
this.log(`Parsed ${frag.type} sn: ${frag.sn}${part ? ' part: ' + part.index : ''} of ${this.fragInfo(frag, false, part)})`);
|
8773
8818
|
this.hls.trigger(Events.FRAG_PARSED, {
|
8774
8819
|
frag,
|
8775
8820
|
part
|
@@ -8778,9 +8823,9 @@ class BaseStreamController extends TaskLoop {
|
|
8778
8823
|
playlistLabel() {
|
8779
8824
|
return this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track';
|
8780
8825
|
}
|
8781
|
-
fragInfo(frag, pts = true) {
|
8826
|
+
fragInfo(frag, pts = true, part) {
|
8782
8827
|
var _ref, _ref2;
|
8783
|
-
return `${this.playlistLabel()} ${frag.level} (frag:[${((_ref = pts ? frag.startPTS : frag.start) != null ? _ref : NaN).toFixed(3)}-${((_ref2 = pts ? frag.endPTS : frag.end) != null ? _ref2 : NaN).toFixed(3)}]`;
|
8828
|
+
return `${this.playlistLabel()} ${frag.level} (${part ? 'part' : 'frag'}:[${((_ref = pts && !part ? frag.startPTS : (part || frag).start) != null ? _ref : NaN).toFixed(3)}-${((_ref2 = pts && !part ? frag.endPTS : (part || frag).end) != null ? _ref2 : NaN).toFixed(3)}]${part && frag.type === 'main' ? 'INDEPENDENT=' + (part.independent ? 'YES' : 'NO') : ''}`;
|
8784
8829
|
}
|
8785
8830
|
resetTransmuxer() {
|
8786
8831
|
var _this$transmuxer2;
|
@@ -16408,7 +16453,7 @@ class Transmuxer {
|
|
16408
16453
|
accurateTimeOffset,
|
16409
16454
|
timeOffset
|
16410
16455
|
} = this.currentTransmuxState;
|
16411
|
-
this.logger.log(`[transmuxer.ts]: Flushed ${this.id} sn: ${chunkMeta.sn}${chunkMeta.part > -1 ? '
|
16456
|
+
this.logger.log(`[transmuxer.ts]: Flushed ${this.id} sn: ${chunkMeta.sn}${chunkMeta.part > -1 ? ' part: ' + chunkMeta.part : ''} of ${this.id === PlaylistLevelType.MAIN ? 'level' : 'track'} ${chunkMeta.level}`);
|
16412
16457
|
const remuxResult = this.remuxer.remux(audioTrack, videoTrack, id3Track, textTrack, timeOffset, accurateTimeOffset, true, this.id);
|
16413
16458
|
transmuxResults.push({
|
16414
16459
|
remuxResult,
|
@@ -19038,7 +19083,7 @@ class GapController extends Logger {
|
|
19038
19083
|
}
|
19039
19084
|
}
|
19040
19085
|
|
19041
|
-
const version = "1.6.0-beta.1.0.canary.
|
19086
|
+
const version = "1.6.0-beta.1.0.canary.10752";
|
19042
19087
|
|
19043
19088
|
// ensure the worker ends up in the bundle
|
19044
19089
|
// If the worker should not be included this gets aliased to empty.js
|
@@ -19314,7 +19359,7 @@ class TransmuxerInterface {
|
|
19314
19359
|
const initSegmentChange = !(lastFrag && ((_frag$initSegment = frag.initSegment) == null ? void 0 : _frag$initSegment.url) === ((_lastFrag$initSegment = lastFrag.initSegment) == null ? void 0 : _lastFrag$initSegment.url));
|
19315
19360
|
const state = new TransmuxState(discontinuity, contiguous, accurateTimeOffset, trackSwitch, timeOffset, initSegmentChange);
|
19316
19361
|
if (!contiguous || discontinuity || initSegmentChange) {
|
19317
|
-
this.hls.logger.log(`[transmuxer-interface
|
19362
|
+
this.hls.logger.log(`[transmuxer-interface]: Starting new transmux session for ${frag.type} sn: ${chunkMeta.sn}${chunkMeta.part > -1 ? ' part: ' + chunkMeta.part : ''} ${this.id === PlaylistLevelType.MAIN ? 'level' : 'track'}: ${chunkMeta.level} id: ${chunkMeta.id}
|
19318
19363
|
discontinuity: ${discontinuity}
|
19319
19364
|
trackSwitch: ${trackSwitch}
|
19320
19365
|
contiguous: ${contiguous}
|
@@ -20322,13 +20367,14 @@ class StreamController extends BaseStreamController {
|
|
20322
20367
|
}
|
20323
20368
|
return audioCodec;
|
20324
20369
|
}
|
20325
|
-
_loadBitrateTestFrag(
|
20326
|
-
|
20327
|
-
this._doFragLoad(
|
20370
|
+
_loadBitrateTestFrag(fragment, level) {
|
20371
|
+
fragment.bitrateTest = true;
|
20372
|
+
this._doFragLoad(fragment, level).then(data => {
|
20328
20373
|
const {
|
20329
20374
|
hls
|
20330
20375
|
} = this;
|
20331
|
-
|
20376
|
+
const frag = data == null ? void 0 : data.frag;
|
20377
|
+
if (!frag || this.fragContextChanged(frag)) {
|
20332
20378
|
return;
|
20333
20379
|
}
|
20334
20380
|
level.fragmentError = 0;
|