hls.js 1.6.0-beta.1.0.canary.10803 → 1.6.0-beta.1.0.canary.10804
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 +12 -4
- package/dist/hls.d.ts +12 -4
- package/dist/hls.js +141 -81
- package/dist/hls.js.d.ts +12 -4
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +127 -75
- 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 +120 -74
- 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 +134 -80
- 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 +2 -2
- package/src/controller/base-playlist-controller.ts +39 -44
- package/src/controller/base-stream-controller.ts +1 -1
- package/src/controller/interstitials-controller.ts +18 -5
- package/src/controller/level-controller.ts +13 -14
- package/src/controller/stream-controller.ts +3 -0
- package/src/hls.ts +26 -7
- package/src/loader/level-details.ts +16 -0
- package/src/loader/playlist-loader.ts +38 -4
- package/src/types/events.ts +1 -0
- package/src/utils/level-helper.ts +6 -3
@@ -24,8 +24,8 @@ export default class BasePlaylistController
|
|
24
24
|
implements NetworkComponentAPI
|
25
25
|
{
|
26
26
|
protected hls: Hls;
|
27
|
+
protected canLoad: boolean = false;
|
27
28
|
private timer: number = -1;
|
28
|
-
private canLoad: boolean = false;
|
29
29
|
|
30
30
|
constructor(hls: Hls, logPrefix: string) {
|
31
31
|
super(logPrefix, hls.logger);
|
@@ -170,6 +170,25 @@ export default class BasePlaylistController
|
|
170
170
|
if (details.live || previousDetails?.live) {
|
171
171
|
const levelOrTrack = 'levelInfo' in data ? data.levelInfo : data.track;
|
172
172
|
details.reloaded(previousDetails);
|
173
|
+
// Merge live playlists to adjust fragment starts and fill in delta playlist skipped segments
|
174
|
+
if (previousDetails && details.fragments.length > 0) {
|
175
|
+
mergeDetails(previousDetails, details);
|
176
|
+
}
|
177
|
+
if (details.requestScheduled === -1) {
|
178
|
+
details.requestScheduled = stats.loading.start;
|
179
|
+
}
|
180
|
+
const bufferInfo = this.hls.mainForwardBufferInfo;
|
181
|
+
const position = bufferInfo ? bufferInfo.end - bufferInfo.len : 0;
|
182
|
+
const distanceToLiveEdgeMs = (details.edge - position) * 1000;
|
183
|
+
const reloadInterval = computeReloadInterval(
|
184
|
+
details,
|
185
|
+
distanceToLiveEdgeMs,
|
186
|
+
);
|
187
|
+
if (details.requestScheduled + reloadInterval < now) {
|
188
|
+
details.requestScheduled = now;
|
189
|
+
} else {
|
190
|
+
details.requestScheduled += reloadInterval;
|
191
|
+
}
|
173
192
|
this.log(
|
174
193
|
`live playlist ${index} ${
|
175
194
|
details.advanced
|
@@ -179,10 +198,6 @@ export default class BasePlaylistController
|
|
179
198
|
: 'MISSED'
|
180
199
|
}`,
|
181
200
|
);
|
182
|
-
// Merge live playlists to adjust fragment starts and fill in delta playlist skipped segments
|
183
|
-
if (previousDetails && details.fragments.length > 0) {
|
184
|
-
mergeDetails(previousDetails, details);
|
185
|
-
}
|
186
201
|
if (!this.canLoad || !details.live) {
|
187
202
|
return;
|
188
203
|
}
|
@@ -196,12 +211,16 @@ export default class BasePlaylistController
|
|
196
211
|
const endSn = details.endSN;
|
197
212
|
const lastPartIndex = details.lastPartIndex;
|
198
213
|
const hasParts = lastPartIndex !== -1;
|
199
|
-
const
|
200
|
-
// When low latency mode is disabled, we'll skip part requests once the last part index is found
|
201
|
-
const nextSnStartIndex = lowLatencyMode ? 0 : lastPartIndex;
|
214
|
+
const atLastPartOfSegment = lastPartSn === endSn;
|
202
215
|
if (hasParts) {
|
203
|
-
|
204
|
-
|
216
|
+
// When low latency mode is disabled, request the last part of the next segment
|
217
|
+
if (atLastPartOfSegment) {
|
218
|
+
msn = endSn + 1;
|
219
|
+
part = lowLatencyMode ? 0 : lastPartIndex;
|
220
|
+
} else {
|
221
|
+
msn = lastPartSn;
|
222
|
+
part = lowLatencyMode ? lastPartIndex + 1 : details.maxPartIndex;
|
223
|
+
}
|
205
224
|
} else {
|
206
225
|
msn = endSn + 1;
|
207
226
|
}
|
@@ -258,7 +277,8 @@ export default class BasePlaylistController
|
|
258
277
|
msn,
|
259
278
|
part,
|
260
279
|
);
|
261
|
-
if (lowLatencyMode || !
|
280
|
+
if (lowLatencyMode || !atLastPartOfSegment) {
|
281
|
+
details.requestScheduled = now;
|
262
282
|
this.loadingPlaylist(levelOrTrack, deliveryDirectives);
|
263
283
|
return;
|
264
284
|
}
|
@@ -270,25 +290,12 @@ export default class BasePlaylistController
|
|
270
290
|
part,
|
271
291
|
);
|
272
292
|
}
|
273
|
-
if (details.requestScheduled === -1) {
|
274
|
-
details.requestScheduled = stats.loading.start;
|
275
|
-
}
|
276
293
|
if (deliveryDirectives && msn !== undefined && details.canBlockReload) {
|
277
|
-
details.requestScheduled
|
278
|
-
|
279
|
-
|
280
|
-
const position = bufferInfo ? bufferInfo.end - bufferInfo.len : 0;
|
281
|
-
const distanceToLiveEdgeMs = (details.edge - position) * 1000;
|
282
|
-
const reloadInterval = computeReloadInterval(
|
283
|
-
details,
|
284
|
-
distanceToLiveEdgeMs,
|
285
|
-
);
|
286
|
-
if (details.requestScheduled + reloadInterval < now) {
|
287
|
-
details.requestScheduled = now;
|
288
|
-
} else {
|
289
|
-
details.requestScheduled += reloadInterval;
|
294
|
+
details.requestScheduled =
|
295
|
+
stats.loading.first +
|
296
|
+
Math.max(reloadInterval - elapsed * 2, reloadInterval / 2);
|
290
297
|
}
|
291
|
-
this.scheduleLoading(levelOrTrack, deliveryDirectives);
|
298
|
+
this.scheduleLoading(levelOrTrack, deliveryDirectives, details);
|
292
299
|
} else {
|
293
300
|
this.clearTimer();
|
294
301
|
}
|
@@ -297,8 +304,9 @@ export default class BasePlaylistController
|
|
297
304
|
protected scheduleLoading(
|
298
305
|
levelOrTrack: Level | MediaPlaylist,
|
299
306
|
deliveryDirectives?: HlsUrlParameters,
|
307
|
+
updatedDetails?: LevelDetails,
|
300
308
|
) {
|
301
|
-
const details = levelOrTrack.details;
|
309
|
+
const details = updatedDetails || levelOrTrack.details;
|
302
310
|
if (!details) {
|
303
311
|
this.loadingPlaylist(levelOrTrack, deliveryDirectives);
|
304
312
|
return;
|
@@ -316,22 +324,8 @@ export default class BasePlaylistController
|
|
316
324
|
estimatedTimeUntilUpdate,
|
317
325
|
)} ms`,
|
318
326
|
);
|
319
|
-
// this.log(
|
320
|
-
// `live reload ${details.updated ? 'REFRESHED' : 'MISSED'}
|
321
|
-
// reload in ${estimatedTimeUntilUpdate / 1000}
|
322
|
-
// round trip ${(stats.loading.end - stats.loading.start) / 1000}
|
323
|
-
// diff ${
|
324
|
-
// (reloadInterval -
|
325
|
-
// (estimatedTimeUntilUpdate +
|
326
|
-
// stats.loading.end -
|
327
|
-
// stats.loading.start)) /
|
328
|
-
// 1000
|
329
|
-
// }
|
330
|
-
// reload interval ${reloadInterval / 1000}
|
331
|
-
// target duration ${details.targetduration}
|
332
|
-
// distance to edge ${distanceToLiveEdgeMs / 1000}`
|
333
|
-
// );
|
334
327
|
|
328
|
+
this.clearTimer();
|
335
329
|
this.timer = self.setTimeout(
|
336
330
|
() => this.loadingPlaylist(levelOrTrack, deliveryDirectives),
|
337
331
|
estimatedTimeUntilUpdate,
|
@@ -379,6 +373,7 @@ export default class BasePlaylistController
|
|
379
373
|
} else {
|
380
374
|
const delay = getRetryDelay(retryConfig, retryCount);
|
381
375
|
// Schedule level/track reload
|
376
|
+
this.clearTimer();
|
382
377
|
this.timer = self.setTimeout(() => this.loadPlaylist(), delay);
|
383
378
|
this.warn(
|
384
379
|
`Retrying playlist loading ${retryCount + 1}/${
|
@@ -1871,7 +1871,7 @@ export default class BaseStreamController
|
|
1871
1871
|
}
|
1872
1872
|
}
|
1873
1873
|
|
1874
|
-
protected resetWhenMissingContext(chunkMeta: ChunkMetadata) {
|
1874
|
+
protected resetWhenMissingContext(chunkMeta: ChunkMetadata | Fragment) {
|
1875
1875
|
this.warn(
|
1876
1876
|
`The loading context changed while buffering fragment ${chunkMeta.sn} of ${this.playlistLabel()} ${chunkMeta.level}. This chunk will not be buffered.`,
|
1877
1877
|
);
|
@@ -1114,7 +1114,7 @@ MediaSource ${JSON.stringify(attachMediaSourceData)} from ${logFromSource}`,
|
|
1114
1114
|
player.media?.play();
|
1115
1115
|
}
|
1116
1116
|
} else if (scheduledItem !== null) {
|
1117
|
-
this.resumePrimary(scheduledItem, index);
|
1117
|
+
this.resumePrimary(scheduledItem, index, currentItem);
|
1118
1118
|
if (this.shouldPlay) {
|
1119
1119
|
this.hls.media?.play();
|
1120
1120
|
}
|
@@ -1144,12 +1144,16 @@ MediaSource ${JSON.stringify(attachMediaSourceData)} from ${logFromSource}`,
|
|
1144
1144
|
private resumePrimary(
|
1145
1145
|
scheduledItem: InterstitialSchedulePrimaryItem,
|
1146
1146
|
index: number,
|
1147
|
+
fromItem: InterstitialScheduleItem | null,
|
1147
1148
|
) {
|
1148
1149
|
this.playingItem = scheduledItem;
|
1149
1150
|
this.playingAsset = null;
|
1150
1151
|
this.waitingItem = null;
|
1151
1152
|
|
1152
1153
|
this.bufferedToItem(scheduledItem);
|
1154
|
+
if (!fromItem) {
|
1155
|
+
return;
|
1156
|
+
}
|
1153
1157
|
|
1154
1158
|
this.log(`resuming ${segmentToString(scheduledItem)}`);
|
1155
1159
|
|
@@ -1231,13 +1235,22 @@ MediaSource ${JSON.stringify(attachMediaSourceData)} from ${logFromSource}`,
|
|
1231
1235
|
} else {
|
1232
1236
|
this.transferMediaTo(hls, media);
|
1233
1237
|
if (skipSeekToStartPosition) {
|
1234
|
-
|
1238
|
+
this.startLoadingPrimaryAt(timelinePos, skipSeekToStartPosition);
|
1235
1239
|
}
|
1236
1240
|
}
|
1237
1241
|
if (!skipSeekToStartPosition) {
|
1238
1242
|
// Set primary position to resume time
|
1239
1243
|
this.timelinePos = timelinePos;
|
1240
|
-
|
1244
|
+
this.startLoadingPrimaryAt(timelinePos, skipSeekToStartPosition);
|
1245
|
+
}
|
1246
|
+
}
|
1247
|
+
|
1248
|
+
private startLoadingPrimaryAt(
|
1249
|
+
timelinePos: number,
|
1250
|
+
skipSeekToStartPosition?: boolean,
|
1251
|
+
) {
|
1252
|
+
if (this.hls.loadingEnabled) {
|
1253
|
+
this.hls.startLoad(timelinePos, skipSeekToStartPosition);
|
1241
1254
|
}
|
1242
1255
|
}
|
1243
1256
|
|
@@ -1688,7 +1701,7 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))}`,
|
|
1688
1701
|
private preloadPrimary(item: InterstitialSchedulePrimaryItem) {
|
1689
1702
|
const index = this.findItemIndex(item);
|
1690
1703
|
const timelinePos = this.getPrimaryResumption(item, index);
|
1691
|
-
this.
|
1704
|
+
this.startLoadingPrimaryAt(timelinePos);
|
1692
1705
|
}
|
1693
1706
|
|
1694
1707
|
private bufferedToEvent(
|
@@ -1869,7 +1882,7 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))}`,
|
|
1869
1882
|
}
|
1870
1883
|
const playerConfig: Partial<HlsConfig> = {
|
1871
1884
|
...userConfig,
|
1872
|
-
|
1885
|
+
autoStartLoad: true,
|
1873
1886
|
startFragPrefetch: true,
|
1874
1887
|
primarySessionId: primary.sessionId,
|
1875
1888
|
assetPlayerId: assetItem.identifier,
|
@@ -380,18 +380,6 @@ export default class LevelController extends BasePlaylistController {
|
|
380
380
|
altAudio: !audioOnly && audioTracks.some((t) => !!t.url),
|
381
381
|
};
|
382
382
|
this.hls.trigger(Events.MANIFEST_PARSED, edata);
|
383
|
-
|
384
|
-
// Initiate loading after all controllers have received MANIFEST_PARSED
|
385
|
-
const {
|
386
|
-
config: { autoStartLoad, startPosition },
|
387
|
-
forceStartLoad,
|
388
|
-
} = this.hls;
|
389
|
-
if (autoStartLoad || forceStartLoad) {
|
390
|
-
this.log(
|
391
|
-
`${autoStartLoad ? 'auto' : 'force'} startLoad with configured startPosition ${startPosition}`,
|
392
|
-
);
|
393
|
-
this.hls.startLoad(startPosition);
|
394
|
-
}
|
395
383
|
}
|
396
384
|
|
397
385
|
get levels(): Level[] | null {
|
@@ -606,8 +594,8 @@ export default class LevelController extends BasePlaylistController {
|
|
606
594
|
return;
|
607
595
|
}
|
608
596
|
|
609
|
-
// only process level loaded events matching with expected level
|
610
|
-
if (curLevel === this.currentLevel) {
|
597
|
+
// only process level loaded events matching with expected level or prior to switch when media playlist is loaded directly
|
598
|
+
if (curLevel === this.currentLevel || data.withoutMultiVariant) {
|
611
599
|
// reset level load error counter on successful level loaded only if there is no issues with fragments
|
612
600
|
if (curLevel.fragmentError === 0) {
|
613
601
|
curLevel.loadError = 0;
|
@@ -676,6 +664,9 @@ export default class LevelController extends BasePlaylistController {
|
|
676
664
|
}
|
677
665
|
|
678
666
|
removeLevel(levelIndex: number) {
|
667
|
+
if (this._levels.length === 1) {
|
668
|
+
return;
|
669
|
+
}
|
679
670
|
const levels = this._levels.filter((level, index) => {
|
680
671
|
if (index !== levelIndex) {
|
681
672
|
return true;
|
@@ -697,6 +688,14 @@ export default class LevelController extends BasePlaylistController {
|
|
697
688
|
if (this.currentLevelIndex > -1 && this.currentLevel?.details) {
|
698
689
|
this.currentLevelIndex = this.currentLevel.details.fragments[0].level;
|
699
690
|
}
|
691
|
+
if (this.manualLevelIndex > -1) {
|
692
|
+
this.manualLevelIndex = this.currentLevelIndex;
|
693
|
+
}
|
694
|
+
const maxLevel = levels.length - 1;
|
695
|
+
this._firstLevel = Math.min(this._firstLevel, maxLevel);
|
696
|
+
if (this._startLevel) {
|
697
|
+
this._startLevel = Math.min(this._startLevel, maxLevel);
|
698
|
+
}
|
700
699
|
this.hls.trigger(Events.LEVELS_UPDATED, { levels });
|
701
700
|
}
|
702
701
|
|
@@ -1095,6 +1095,9 @@ export default class StreamController
|
|
1095
1095
|
) {
|
1096
1096
|
if (this.level > -1 && this.fragCurrent) {
|
1097
1097
|
this.level = this.fragCurrent.level;
|
1098
|
+
if (this.level === -1) {
|
1099
|
+
this.resetWhenMissingContext(this.fragCurrent);
|
1100
|
+
}
|
1098
1101
|
}
|
1099
1102
|
this.levels = data.levels;
|
1100
1103
|
}
|
package/src/hls.ts
CHANGED
@@ -98,8 +98,9 @@ export default class Hls implements HlsEventEmitter {
|
|
98
98
|
private cmcdController?: CMCDController;
|
99
99
|
private _media: HTMLMediaElement | null = null;
|
100
100
|
private _url: string | null = null;
|
101
|
-
private triggeringException?: boolean;
|
102
101
|
private _sessionId?: string;
|
102
|
+
private triggeringException?: boolean;
|
103
|
+
private started: boolean = false;
|
103
104
|
|
104
105
|
/**
|
105
106
|
* Get the video-dev/hls.js package version.
|
@@ -527,10 +528,17 @@ export default class Hls implements HlsEventEmitter {
|
|
527
528
|
(skipSeekToStartPosition ? ', <skip seek to start>' : '')
|
528
529
|
})`,
|
529
530
|
);
|
531
|
+
this.started = true;
|
530
532
|
this.resumeBuffering();
|
531
|
-
this.networkControllers.
|
532
|
-
|
533
|
-
|
533
|
+
for (let i = 0; i < this.networkControllers.length; i++) {
|
534
|
+
this.networkControllers[i].startLoad(
|
535
|
+
startPosition,
|
536
|
+
skipSeekToStartPosition,
|
537
|
+
);
|
538
|
+
if (!this.started || !this.networkControllers) {
|
539
|
+
break;
|
540
|
+
}
|
541
|
+
}
|
534
542
|
}
|
535
543
|
|
536
544
|
/**
|
@@ -538,9 +546,20 @@ export default class Hls implements HlsEventEmitter {
|
|
538
546
|
*/
|
539
547
|
stopLoad() {
|
540
548
|
this.logger.log('stopLoad');
|
541
|
-
this.
|
542
|
-
|
543
|
-
|
549
|
+
this.started = false;
|
550
|
+
for (let i = 0; i < this.networkControllers.length; i++) {
|
551
|
+
this.networkControllers[i].stopLoad();
|
552
|
+
if (this.started || !this.networkControllers) {
|
553
|
+
break;
|
554
|
+
}
|
555
|
+
}
|
556
|
+
}
|
557
|
+
|
558
|
+
/**
|
559
|
+
* Returns whether loading, toggled with `startLoad()` and `stopLoad()`, is active or not`.
|
560
|
+
*/
|
561
|
+
get loadingEnabled(): boolean {
|
562
|
+
return this.started;
|
544
563
|
}
|
545
564
|
|
546
565
|
/**
|
@@ -155,6 +155,22 @@ export class LevelDetails {
|
|
155
155
|
return -1;
|
156
156
|
}
|
157
157
|
|
158
|
+
get maxPartIndex(): number {
|
159
|
+
const partList = this.partList;
|
160
|
+
if (partList) {
|
161
|
+
const lastIndex = this.lastPartIndex;
|
162
|
+
if (lastIndex !== -1) {
|
163
|
+
for (let i = partList.length; i--; ) {
|
164
|
+
if (partList[i].index > lastIndex) {
|
165
|
+
return partList[i].index;
|
166
|
+
}
|
167
|
+
}
|
168
|
+
return lastIndex;
|
169
|
+
}
|
170
|
+
}
|
171
|
+
return 0;
|
172
|
+
}
|
173
|
+
|
158
174
|
get lastPartSn(): number {
|
159
175
|
if (this.partList?.length) {
|
160
176
|
return this.partList[this.partList.length - 1].fragment.sn;
|
@@ -250,7 +250,9 @@ class PlaylistLoader implements NetworkComponentAPI {
|
|
250
250
|
) {
|
251
251
|
// same URL can't overlap, or wait for blocking request
|
252
252
|
if (loaderContext.url === context.url) {
|
253
|
-
logger.log(
|
253
|
+
logger.log(
|
254
|
+
`[playlist-loader]: ignore ${context.url} ongoing request`,
|
255
|
+
);
|
254
256
|
} else {
|
255
257
|
logger.log(
|
256
258
|
`[playlist-loader]: ignore ${context.url} in favor of ${loaderContext.url}`,
|
@@ -349,7 +351,10 @@ class PlaylistLoader implements NetworkComponentAPI {
|
|
349
351
|
}
|
350
352
|
|
351
353
|
stats.parsing.start = performance.now();
|
352
|
-
if (
|
354
|
+
if (
|
355
|
+
M3U8Parser.isMediaPlaylist(string) ||
|
356
|
+
context.type !== PlaylistContextType.MANIFEST
|
357
|
+
) {
|
353
358
|
this.handleTrackOrLevelPlaylist(
|
354
359
|
response,
|
355
360
|
stats,
|
@@ -386,6 +391,22 @@ class PlaylistLoader implements NetworkComponentAPI {
|
|
386
391
|
loader.load(context, loaderConfig, loaderCallbacks);
|
387
392
|
}
|
388
393
|
|
394
|
+
private checkAutostartLoad() {
|
395
|
+
if (!this.hls) {
|
396
|
+
return;
|
397
|
+
}
|
398
|
+
const {
|
399
|
+
config: { autoStartLoad, startPosition },
|
400
|
+
forceStartLoad,
|
401
|
+
} = this.hls;
|
402
|
+
if (autoStartLoad || forceStartLoad) {
|
403
|
+
this.hls.logger.log(
|
404
|
+
`${autoStartLoad ? 'auto' : 'force'} startLoad with configured startPosition ${startPosition}`,
|
405
|
+
);
|
406
|
+
this.hls.startLoad(startPosition);
|
407
|
+
}
|
408
|
+
}
|
409
|
+
|
389
410
|
private handleMasterPlaylist(
|
390
411
|
response: LoaderResponse,
|
391
412
|
stats: LoaderStats,
|
@@ -474,6 +495,8 @@ class PlaylistLoader implements NetworkComponentAPI {
|
|
474
495
|
startTimeOffset,
|
475
496
|
variableList,
|
476
497
|
});
|
498
|
+
|
499
|
+
this.checkAutostartLoad();
|
477
500
|
}
|
478
501
|
|
479
502
|
private handleTrackOrLevelPlaylist(
|
@@ -493,7 +516,7 @@ class PlaylistLoader implements NetworkComponentAPI {
|
|
493
516
|
? (id as number)
|
494
517
|
: 0;
|
495
518
|
const levelType = mapContextToLevelType(context);
|
496
|
-
const levelDetails
|
519
|
+
const levelDetails = M3U8Parser.parseLevelPlaylist(
|
497
520
|
response.data as string,
|
498
521
|
url,
|
499
522
|
levelId,
|
@@ -543,6 +566,14 @@ class PlaylistLoader implements NetworkComponentAPI {
|
|
543
566
|
networkDetails,
|
544
567
|
loader,
|
545
568
|
);
|
569
|
+
|
570
|
+
if (
|
571
|
+
type === PlaylistContextType.MANIFEST &&
|
572
|
+
(!levelDetails.playlistParsingError ||
|
573
|
+
(!levelDetails.fragments.length && levelDetails.live))
|
574
|
+
) {
|
575
|
+
this.checkAutostartLoad();
|
576
|
+
}
|
546
577
|
}
|
547
578
|
|
548
579
|
private handleManifestParsingError(
|
@@ -662,7 +693,9 @@ class PlaylistLoader implements NetworkComponentAPI {
|
|
662
693
|
? (level as number)
|
663
694
|
: undefined;
|
664
695
|
if (!levelDetails.fragments.length) {
|
665
|
-
const error = new Error(
|
696
|
+
const error = (levelDetails.playlistParsingError = new Error(
|
697
|
+
'No Segments found in Playlist',
|
698
|
+
));
|
666
699
|
hls.trigger(Events.ERROR, {
|
667
700
|
type: ErrorTypes.NETWORK_ERROR,
|
668
701
|
details: ErrorDetails.LEVEL_EMPTY_ERROR,
|
@@ -721,6 +754,7 @@ class PlaylistLoader implements NetworkComponentAPI {
|
|
721
754
|
stats,
|
722
755
|
networkDetails,
|
723
756
|
deliveryDirectives,
|
757
|
+
withoutMultiVariant: type === PlaylistContextType.MANIFEST,
|
724
758
|
});
|
725
759
|
break;
|
726
760
|
case PlaylistContextType.AUDIO_TRACK:
|
package/src/types/events.ts
CHANGED
@@ -538,10 +538,13 @@ export function findPart(
|
|
538
538
|
|
539
539
|
export function reassignFragmentLevelIndexes(levels: Level[]) {
|
540
540
|
levels.forEach((level, index) => {
|
541
|
-
const
|
542
|
-
if (
|
543
|
-
|
541
|
+
const fragments = level.details?.fragments;
|
542
|
+
if (fragments) {
|
543
|
+
fragments.forEach((fragment) => {
|
544
544
|
fragment.level = index;
|
545
|
+
if (fragment.initSegment) {
|
546
|
+
fragment.initSegment.level = index;
|
547
|
+
}
|
545
548
|
});
|
546
549
|
}
|
547
550
|
});
|