hls.js 1.6.0-beta.3.0.canary.10980 → 1.6.0-beta.3.0.canary.10982

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/package.json CHANGED
@@ -134,5 +134,5 @@
134
134
  "url-toolkit": "2.2.5",
135
135
  "wrangler": "3.109.2"
136
136
  },
137
- "version": "1.6.0-beta.3.0.canary.10980"
137
+ "version": "1.6.0-beta.3.0.canary.10982"
138
138
  }
package/src/config.ts CHANGED
@@ -308,7 +308,7 @@ export type HlsConfig = {
308
308
  interstitialsController?: typeof InterstitialsController;
309
309
  // Option to disable internal playback handling of Interstitials (set to false to disable Interstitials playback without disabling parsing and schedule events)
310
310
  enableInterstitialPlayback: boolean;
311
- // Option to disable appending Interstitals inline on same timeline and MediaSource as Primary media
311
+ // Option to disable appending Interstitials inline on same timeline and MediaSource as Primary media
312
312
  interstitialAppendInPlace: boolean;
313
313
  // How many seconds past the end of a live playlist to preload Interstitial assets
314
314
  interstitialLiveLookAhead: number;
@@ -440,7 +440,7 @@ export const hlsDefaultConfig: HlsConfig = {
440
440
  enableEmsgMetadataCues: true,
441
441
  enableEmsgKLVMetadata: false,
442
442
  enableID3MetadataCues: true,
443
- enableInterstitialPlayback: __USE_INTERSTITALS__,
443
+ enableInterstitialPlayback: __USE_INTERSTITIALS__,
444
444
  interstitialAppendInPlace: true,
445
445
  interstitialLiveLookAhead: 10,
446
446
  useMediaCapabilities: __USE_MEDIA_CAPABILITIES__,
@@ -533,7 +533,7 @@ export const hlsDefaultConfig: HlsConfig = {
533
533
  : defaultLoadPolicy,
534
534
  },
535
535
  interstitialAssetListLoadPolicy: {
536
- default: __USE_INTERSTITALS__
536
+ default: __USE_INTERSTITIALS__
537
537
  ? {
538
538
  maxTimeToFirstByteMs: 10000,
539
539
  maxLoadTimeMs: 30000,
@@ -582,7 +582,7 @@ export const hlsDefaultConfig: HlsConfig = {
582
582
  contentSteeringController: __USE_CONTENT_STEERING__
583
583
  ? ContentSteeringController
584
584
  : undefined,
585
- interstitialsController: __USE_INTERSTITALS__
585
+ interstitialsController: __USE_INTERSTITIALS__
586
586
  ? InterstitialsController
587
587
  : undefined,
588
588
  };
@@ -8,6 +8,7 @@ import {
8
8
  requiresMediaCapabilitiesDecodingInfo,
9
9
  SUPPORTED_INFO_DEFAULT,
10
10
  } from '../utils/mediacapabilities-helper';
11
+ import { isHEVC } from '../utils/mp4-tools';
11
12
  import {
12
13
  type AudioTracksByGroup,
13
14
  type CodecSetTier,
@@ -804,7 +805,7 @@ class AbrController extends Logger implements AbrComponentAPI {
804
805
  currentBw,
805
806
  audioPreference,
806
807
  ) ||
807
- levelInfo.videoCodec?.substring(0, 4) === 'hvc1') // Force media capabilities check for HEVC to avoid failure on Windows
808
+ isHEVC(levelInfo.videoCodec)) // Force media capabilities check for HEVC to avoid failure on Windows
808
809
  ) {
809
810
  levelInfo.supportedPromise = getMediaDecodingInfoPromise(
810
811
  levelInfo,
@@ -797,13 +797,15 @@ class AudioStreamController
797
797
  this.state = State.IDLE;
798
798
  }
799
799
  break;
800
+ case ErrorDetails.BUFFER_ADD_CODEC_ERROR:
800
801
  case ErrorDetails.BUFFER_APPEND_ERROR:
801
- case ErrorDetails.BUFFER_FULL_ERROR:
802
- if (!data.parent || data.parent !== 'audio') {
802
+ if (data.parent !== 'audio') {
803
803
  return;
804
804
  }
805
- if (data.details === ErrorDetails.BUFFER_APPEND_ERROR) {
806
- this.resetLoadingState();
805
+ this.resetLoadingState();
806
+ break;
807
+ case ErrorDetails.BUFFER_FULL_ERROR:
808
+ if (data.parent !== 'audio') {
807
809
  return;
808
810
  }
809
811
  if (this.reduceLengthAndFlushBuffer(data)) {
@@ -954,7 +956,7 @@ class AudioStreamController
954
956
  }
955
957
  const track = tracks.audio;
956
958
 
957
- track.id = 'audio';
959
+ track.id = PlaylistLevelType.AUDIO;
958
960
 
959
961
  const variantAudioCodecs = currentLevel.audioCodec;
960
962
  this.log(
@@ -454,7 +454,7 @@ export default class BaseStreamController
454
454
  ) {
455
455
  const config = this.hls.config;
456
456
  if (
457
- __USE_INTERSTITALS__ &&
457
+ __USE_INTERSTITIALS__ &&
458
458
  config.interstitialsController &&
459
459
  config.enableInterstitialPlayback !== false &&
460
460
  frag.type !== PlaylistLevelType.SUBTITLE
@@ -488,7 +488,7 @@ export default class BaseStreamController
488
488
  }
489
489
  }
490
490
  }
491
- // Skip loading of fragments that overlap completely with appendInPlace interstitals
491
+ // Skip loading of fragments that overlap completely with appendInPlace interstitials
492
492
  const playerQueue = interstitials?.playerQueue;
493
493
  if (playerQueue) {
494
494
  for (let i = playerQueue.length; i--; ) {
@@ -1336,7 +1336,6 @@ transfer tracks: ${stringify(transferredTracks, (key, value) => (key === 'initSe
1336
1336
  } else {
1337
1337
  // ok, let's create them now !
1338
1338
  this.createSourceBuffers();
1339
- this.bufferCreated();
1340
1339
  }
1341
1340
  }
1342
1341
  }
@@ -1409,6 +1408,10 @@ transfer tracks: ${stringify(transferredTracks, (key, value) => (key === 'initSe
1409
1408
  this.error(
1410
1409
  `error while trying to add sourceBuffer: ${error.message}`,
1411
1410
  );
1411
+ // remove init segment from queue and delete track info
1412
+ this.shiftAndExecuteNext(type);
1413
+ this.operationQueue?.removeBlockers();
1414
+ delete this.tracks[type];
1412
1415
  this.hls.trigger(Events.ERROR, {
1413
1416
  type: ErrorTypes.MEDIA_ERROR,
1414
1417
  details: ErrorDetails.BUFFER_ADD_CODEC_ERROR,
@@ -1416,12 +1419,14 @@ transfer tracks: ${stringify(transferredTracks, (key, value) => (key === 'initSe
1416
1419
  error,
1417
1420
  sourceBufferName: type,
1418
1421
  mimeType: mimeType,
1422
+ parent: track.id as PlaylistLevelType,
1419
1423
  });
1420
- break;
1424
+ return;
1421
1425
  }
1422
1426
  this.trackSourceBuffer(type, track);
1423
1427
  }
1424
1428
  }
1429
+ this.bufferCreated();
1425
1430
  }
1426
1431
 
1427
1432
  private getTrackCodec(track: BaseTrack, trackName: SourceBufferName): string {
@@ -1450,7 +1455,7 @@ transfer tracks: ${stringify(transferredTracks, (key, value) => (key === 'initSe
1450
1455
  id: track.id,
1451
1456
  listeners: [],
1452
1457
  };
1453
-
1458
+ this.removeBufferListeners(type);
1454
1459
  this.addBufferListener(type, 'updatestart', this.onSBUpdateStart);
1455
1460
  this.addBufferListener(type, 'updateend', this.onSBUpdateEnd);
1456
1461
  this.addBufferListener(type, 'error', this.onSBUpdateError);
@@ -3,6 +3,7 @@ import { ErrorDetails, ErrorTypes } from '../errors';
3
3
  import { Events } from '../events';
4
4
  import { HdcpLevels } from '../types/level';
5
5
  import { PlaylistContextType, PlaylistLevelType } from '../types/loader';
6
+ import { getCodecsForMimeType } from '../utils/codecs';
6
7
  import {
7
8
  getRetryConfig,
8
9
  isTimeoutError,
@@ -506,6 +507,19 @@ export default class ErrorController
506
507
  data.errorAction.resolved = true;
507
508
  // Stream controller is responsible for this but won't switch on false start
508
509
  this.hls.nextLoadLevel = this.hls.nextAutoLevel;
510
+ if (
511
+ data.details === ErrorDetails.BUFFER_ADD_CODEC_ERROR &&
512
+ data.mimeType &&
513
+ data.sourceBufferName !== 'audiovideo'
514
+ ) {
515
+ const codec = getCodecsForMimeType(data.mimeType);
516
+ const levels = this.hls.levels;
517
+ for (let i = levels.length; i--; ) {
518
+ if (levels[i][`${data.sourceBufferName}Codec`] === codec) {
519
+ this.hls.removeLevel(i);
520
+ }
521
+ }
522
+ }
509
523
  }
510
524
  }
511
525
  }
@@ -461,7 +461,7 @@ class ID3TrackController implements ComponentAPI {
461
461
  this.id3Track.addCue(cue);
462
462
  cues[key] = cue;
463
463
  if (
464
- __USE_INTERSTITALS__ &&
464
+ __USE_INTERSTITIALS__ &&
465
465
  this.hls.config.interstitialsController
466
466
  ) {
467
467
  if (key === 'X-ASSET-LIST' || key === 'X-ASSET-URL') {
@@ -9,9 +9,17 @@ import {
9
9
  } from '../loader/interstitial-event';
10
10
  import { BufferHelper } from '../utils/buffer-helper';
11
11
  import type { HlsConfig } from '../config';
12
+ import type { InterstitialScheduleEventItem } from '../controller/interstitials-schedule';
12
13
  import type Hls from '../hls';
13
14
  import type { BufferCodecsData, MediaAttachingData } from '../types/events';
14
15
 
16
+ export interface InterstitialPlayer {
17
+ currentTime: number;
18
+ duration: number;
19
+ assetPlayers: (HlsAssetPlayer | null)[];
20
+ playingIndex: number;
21
+ scheduleItem: InterstitialScheduleEventItem | null;
22
+ }
15
23
  export class HlsAssetPlayer {
16
24
  public readonly hls: Hls;
17
25
  public readonly interstitial: InterstitialEvent;
@@ -19,7 +27,6 @@ export class HlsAssetPlayer {
19
27
  public tracks: Partial<BufferCodecsData> | null = null;
20
28
  private hasDetails: boolean = false;
21
29
  private mediaAttached: HTMLMediaElement | null = null;
22
- private playoutOffset: number = 0;
23
30
 
24
31
  constructor(
25
32
  HlsPlayerClass: typeof Hls,
@@ -49,8 +56,6 @@ export class HlsAssetPlayer {
49
56
  this.mediaAttached = media;
50
57
  const event = this.interstitial;
51
58
  if (event.playoutLimit) {
52
- this.playoutOffset =
53
- event.assetList[event.assetList.indexOf(assetItem)]?.startOffset || 0;
54
59
  media.addEventListener('timeupdate', this.checkPlayout);
55
60
  }
56
61
  });
@@ -59,7 +64,8 @@ export class HlsAssetPlayer {
59
64
  private checkPlayout = () => {
60
65
  const interstitial = this.interstitial;
61
66
  const playoutLimit = interstitial.playoutLimit;
62
- if (this.playoutOffset + this.currentTime >= playoutLimit) {
67
+ const currentTime = this.currentTime;
68
+ if (this.startOffset + currentTime >= playoutLimit) {
63
69
  this.hls.trigger(Events.PLAYOUT_LIMIT_REACHED, {});
64
70
  }
65
71
  };
@@ -98,7 +104,7 @@ export class HlsAssetPlayer {
98
104
  }
99
105
 
100
106
  get duration(): number {
101
- const duration = this.assetItem?.duration;
107
+ const duration = this.assetItem.duration;
102
108
  if (!duration) {
103
109
  return 0;
104
110
  }
@@ -113,6 +119,10 @@ export class HlsAssetPlayer {
113
119
  return Math.max(0, duration - this.currentTime);
114
120
  }
115
121
 
122
+ get startOffset(): number {
123
+ return this.assetItem.startOffset;
124
+ }
125
+
116
126
  get timelineOffset(): number {
117
127
  return this.hls?.config.timelineOffset || 0;
118
128
  }