hls.js 1.5.5-0.canary.9985 → 1.5.5-0.canary.9986
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.js +63 -6
- package/dist/hls.js.d.ts +2 -0
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +63 -6
- 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 +63 -6
- 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 +63 -6
- package/dist/hls.mjs.map +1 -1
- package/dist/hls.worker.js +1 -1
- package/package.json +1 -1
- package/src/controller/base-stream-controller.ts +93 -4
@@ -101,6 +101,7 @@ export default class BaseStreamController
|
|
101
101
|
protected decrypter: Decrypter;
|
102
102
|
protected initPTS: RationalTimestamp[] = [];
|
103
103
|
protected buffering: boolean = true;
|
104
|
+
private loadingParts: boolean = false;
|
104
105
|
|
105
106
|
constructor(
|
106
107
|
hls: Hls,
|
@@ -304,6 +305,21 @@ export default class BaseStreamController
|
|
304
305
|
);
|
305
306
|
|
306
307
|
this.lastCurrentTime = currentTime;
|
308
|
+
if (!this.loadingParts) {
|
309
|
+
const bufferEnd = Math.max(bufferInfo.end, currentTime);
|
310
|
+
const shouldLoadParts = this.shouldLoadParts(
|
311
|
+
this.getLevelDetails(),
|
312
|
+
bufferEnd,
|
313
|
+
);
|
314
|
+
if (shouldLoadParts) {
|
315
|
+
this.log(
|
316
|
+
`LL-Part loading ON after seeking to ${currentTime.toFixed(
|
317
|
+
2,
|
318
|
+
)} with buffer @${bufferEnd.toFixed(2)}`,
|
319
|
+
);
|
320
|
+
this.loadingParts = shouldLoadParts;
|
321
|
+
}
|
322
|
+
}
|
307
323
|
}
|
308
324
|
|
309
325
|
// in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
|
@@ -700,8 +716,23 @@ export default class BaseStreamController
|
|
700
716
|
this.keyLoader.loadClear(frag, details.encryptedFragments);
|
701
717
|
}
|
702
718
|
|
719
|
+
const fragPrevious = this.fragPrevious;
|
720
|
+
if (
|
721
|
+
frag.sn !== 'initSegment' &&
|
722
|
+
(!fragPrevious || frag.sn !== fragPrevious.sn)
|
723
|
+
) {
|
724
|
+
const shouldLoadParts = this.shouldLoadParts(level.details, frag.end);
|
725
|
+
if (shouldLoadParts !== this.loadingParts) {
|
726
|
+
this.log(
|
727
|
+
`LL-Part loading ${
|
728
|
+
shouldLoadParts ? 'ON' : 'OFF'
|
729
|
+
} loading sn ${fragPrevious?.sn}->${frag.sn}`,
|
730
|
+
);
|
731
|
+
this.loadingParts = shouldLoadParts;
|
732
|
+
}
|
733
|
+
}
|
703
734
|
targetBufferTime = Math.max(frag.start, targetBufferTime || 0);
|
704
|
-
if (this.
|
735
|
+
if (this.loadingParts && frag.sn !== 'initSegment') {
|
705
736
|
const partList = details.partList;
|
706
737
|
if (partList && progressCallback) {
|
707
738
|
if (targetBufferTime > frag.end && details.fragmentHint) {
|
@@ -772,6 +803,18 @@ export default class BaseStreamController
|
|
772
803
|
}
|
773
804
|
}
|
774
805
|
|
806
|
+
if (frag.sn !== 'initSegment' && this.loadingParts) {
|
807
|
+
this.log(
|
808
|
+
`LL-Part loading OFF after next part miss @${targetBufferTime.toFixed(
|
809
|
+
2,
|
810
|
+
)}`,
|
811
|
+
);
|
812
|
+
this.loadingParts = false;
|
813
|
+
} else if (!frag.url) {
|
814
|
+
// Selected fragment hint for part but not loading parts
|
815
|
+
return Promise.resolve(null);
|
816
|
+
}
|
817
|
+
|
775
818
|
this.log(
|
776
819
|
`Loading fragment ${frag.sn} cc: ${frag.cc} ${
|
777
820
|
details ? 'of [' + details.startSN + '-' + details.endSN + '] ' : ''
|
@@ -899,9 +942,50 @@ export default class BaseStreamController
|
|
899
942
|
if (part) {
|
900
943
|
part.stats.parsing.end = now;
|
901
944
|
}
|
945
|
+
// See if part loading should be disabled/enabled based on buffer and playback position.
|
946
|
+
if (frag.sn !== 'initSegment') {
|
947
|
+
const levelDetails = this.getLevelDetails();
|
948
|
+
const loadingPartsAtEdge = levelDetails && frag.sn > levelDetails.endSN;
|
949
|
+
const shouldLoadParts =
|
950
|
+
loadingPartsAtEdge || this.shouldLoadParts(levelDetails, frag.end);
|
951
|
+
if (shouldLoadParts !== this.loadingParts) {
|
952
|
+
this.log(
|
953
|
+
`LL-Part loading ${
|
954
|
+
shouldLoadParts ? 'ON' : 'OFF'
|
955
|
+
} after parsing segment ending @${frag.end.toFixed(2)}`,
|
956
|
+
);
|
957
|
+
this.loadingParts = shouldLoadParts;
|
958
|
+
}
|
959
|
+
}
|
960
|
+
|
902
961
|
this.updateLevelTiming(frag, part, level, chunkMeta.partial);
|
903
962
|
}
|
904
963
|
|
964
|
+
private shouldLoadParts(
|
965
|
+
details: LevelDetails | undefined,
|
966
|
+
bufferEnd: number,
|
967
|
+
): boolean {
|
968
|
+
if (this.config.lowLatencyMode) {
|
969
|
+
if (!details) {
|
970
|
+
return this.loadingParts;
|
971
|
+
}
|
972
|
+
if (details?.partList) {
|
973
|
+
// Buffer must be ahead of first part + duration of parts after last segment
|
974
|
+
// and playback must be at or past segment adjacent to part list
|
975
|
+
const firstPart = details.partList[0];
|
976
|
+
const safePartStart =
|
977
|
+
firstPart.end + (details.fragmentHint?.duration || 0);
|
978
|
+
if (
|
979
|
+
bufferEnd >= safePartStart &&
|
980
|
+
this.lastCurrentTime > firstPart.start - firstPart.fragment.duration
|
981
|
+
) {
|
982
|
+
return true;
|
983
|
+
}
|
984
|
+
}
|
985
|
+
}
|
986
|
+
return false;
|
987
|
+
}
|
988
|
+
|
905
989
|
protected getCurrentContext(
|
906
990
|
chunkMeta: ChunkMetadata,
|
907
991
|
): { frag: Fragment; part: Part | null; level: Level } | null {
|
@@ -1083,7 +1167,8 @@ export default class BaseStreamController
|
|
1083
1167
|
// find fragment index, contiguous with end of buffer position
|
1084
1168
|
const { config } = this;
|
1085
1169
|
const start = fragments[0].start;
|
1086
|
-
|
1170
|
+
const canLoadParts = config.lowLatencyMode && !!levelDetails.partList;
|
1171
|
+
let frag: Fragment | null = null;
|
1087
1172
|
|
1088
1173
|
if (levelDetails.live) {
|
1089
1174
|
const initialLiveManifestSize = config.initialLiveManifestSize;
|
@@ -1103,6 +1188,10 @@ export default class BaseStreamController
|
|
1103
1188
|
this.startPosition === -1) ||
|
1104
1189
|
pos < start
|
1105
1190
|
) {
|
1191
|
+
if (canLoadParts && !this.loadingParts) {
|
1192
|
+
this.log(`LL-Part loading ON for initial live fragment`);
|
1193
|
+
this.loadingParts = true;
|
1194
|
+
}
|
1106
1195
|
frag = this.getInitialLiveFragment(levelDetails, fragments);
|
1107
1196
|
this.startPosition = this.nextLoadPosition = frag
|
1108
1197
|
? this.hls.liveSyncPosition || frag.start
|
@@ -1115,7 +1204,7 @@ export default class BaseStreamController
|
|
1115
1204
|
|
1116
1205
|
// If we haven't run into any special cases already, just load the fragment most closely matching the requested position
|
1117
1206
|
if (!frag) {
|
1118
|
-
const end =
|
1207
|
+
const end = this.loadingParts
|
1119
1208
|
? levelDetails.partEnd
|
1120
1209
|
: levelDetails.fragmentEnd;
|
1121
1210
|
frag = this.getFragmentAtPosition(pos, end, levelDetails);
|
@@ -1298,7 +1387,7 @@ export default class BaseStreamController
|
|
1298
1387
|
const partList = levelDetails.partList;
|
1299
1388
|
|
1300
1389
|
const loadingParts = !!(
|
1301
|
-
|
1390
|
+
this.loadingParts &&
|
1302
1391
|
partList?.length &&
|
1303
1392
|
fragmentHint
|
1304
1393
|
);
|