stormcloud-video-player 0.6.13 → 0.6.14

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/lib/index.d.cts CHANGED
@@ -127,6 +127,7 @@ declare class StormcloudVideoPlayer {
127
127
  private inAdBreak;
128
128
  private currentAdBreakStartWallClockMs;
129
129
  private expectedAdBreakDurationMs;
130
+ private scteAdBreakEndWallClockMs;
130
131
  private adStopTimerId;
131
132
  private adStartTimerId;
132
133
  private adFailsafeTimerId;
@@ -190,6 +191,9 @@ declare class StormcloudVideoPlayer {
190
191
  private parseScte35FromId3;
191
192
  private decodeId3ValueToText;
192
193
  private onScte35Marker;
194
+ private resolveScteBreakStartWallClockMs;
195
+ private setAdBreakDurationBoundary;
196
+ private scheduleAdStopAtBreakBoundary;
193
197
  private parseCueOutDuration;
194
198
  private parseCueOutCont;
195
199
  private parseAttributeList;
@@ -232,6 +236,7 @@ declare class StormcloudVideoPlayer {
232
236
  private clearAdFailsafeTimer;
233
237
  private logAdState;
234
238
  private getRemainingAdMs;
239
+ private getAdBreakEndWallClockMs;
235
240
  toggleMute(): void;
236
241
  toggleFullscreen(): Promise<void>;
237
242
  isMuted(): boolean;
package/lib/index.d.ts CHANGED
@@ -127,6 +127,7 @@ declare class StormcloudVideoPlayer {
127
127
  private inAdBreak;
128
128
  private currentAdBreakStartWallClockMs;
129
129
  private expectedAdBreakDurationMs;
130
+ private scteAdBreakEndWallClockMs;
130
131
  private adStopTimerId;
131
132
  private adStartTimerId;
132
133
  private adFailsafeTimerId;
@@ -190,6 +191,9 @@ declare class StormcloudVideoPlayer {
190
191
  private parseScte35FromId3;
191
192
  private decodeId3ValueToText;
192
193
  private onScte35Marker;
194
+ private resolveScteBreakStartWallClockMs;
195
+ private setAdBreakDurationBoundary;
196
+ private scheduleAdStopAtBreakBoundary;
193
197
  private parseCueOutDuration;
194
198
  private parseCueOutCont;
195
199
  private parseAttributeList;
@@ -232,6 +236,7 @@ declare class StormcloudVideoPlayer {
232
236
  private clearAdFailsafeTimer;
233
237
  private logAdState;
234
238
  private getRemainingAdMs;
239
+ private getAdBreakEndWallClockMs;
235
240
  toggleMute(): void;
236
241
  toggleFullscreen(): Promise<void>;
237
242
  isMuted(): boolean;
package/lib/index.js CHANGED
@@ -3796,7 +3796,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3796
3796
  _this.adLayer.showPlaceholder();
3797
3797
  }
3798
3798
  if (_this.inAdBreak && _this.expectedAdBreakDurationMs != null && _this.adStopTimerId == null) {
3799
- _this.scheduleAdStopCountdown(_this.getRemainingAdMs());
3799
+ _this.scheduleAdStopAtBreakBoundary();
3800
3800
  if (_this.config.debugAdTiming) {
3801
3801
  console.log("[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)");
3802
3802
  }
@@ -4230,12 +4230,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4230
4230
  if (marker.durationSeconds != null) {
4231
4231
  var newDurationMs = marker.durationSeconds * 1e3;
4232
4232
  if (this.expectedAdBreakDurationMs == null || newDurationMs > this.expectedAdBreakDurationMs) {
4233
- this.expectedAdBreakDurationMs = newDurationMs;
4234
- var elapsedMs = this.currentAdBreakStartWallClockMs != null ? Date.now() - this.currentAdBreakStartWallClockMs : 0;
4235
- var remainingMs = Math.max(0, newDurationMs - elapsedMs);
4236
- this.scheduleAdStopCountdown(remainingMs);
4233
+ this.setAdBreakDurationBoundary(newDurationMs);
4234
+ this.scheduleAdStopAtBreakBoundary();
4237
4235
  if (this.config.debugAdTiming) {
4238
- console.log("[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ".concat(newDurationMs, "ms, remaining: ").concat(remainingMs, "ms"));
4236
+ console.log("[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ".concat(newDurationMs, "ms, remaining: ").concat(this.getRemainingAdMs(), "ms"));
4239
4237
  }
4240
4238
  }
4241
4239
  }
@@ -4243,8 +4241,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4243
4241
  }
4244
4242
  this.inAdBreak = true;
4245
4243
  var durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : ((_this_pendingAdBreak = this.pendingAdBreak) === null || _this_pendingAdBreak === void 0 ? void 0 : _this_pendingAdBreak.marker.durationSeconds) != null ? this.pendingAdBreak.marker.durationSeconds * 1e3 : void 0;
4246
- this.expectedAdBreakDurationMs = durationMs;
4247
- this.currentAdBreakStartWallClockMs = Date.now();
4244
+ this.currentAdBreakStartWallClockMs = this.resolveScteBreakStartWallClockMs(marker);
4245
+ this.setAdBreakDurationBoundary(durationMs);
4248
4246
  if (this.config.licenseKey) {
4249
4247
  var _this_pendingAdBreak1;
4250
4248
  var adDetectInfo = _object_spread({
@@ -4308,20 +4306,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4308
4306
  this.clearAdStartTimer();
4309
4307
  this.handleAdStart(marker);
4310
4308
  }
4311
- if (this.expectedAdBreakDurationMs != null) {
4312
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
4313
- }
4309
+ this.scheduleAdStopAtBreakBoundary();
4314
4310
  return;
4315
4311
  }
4316
4312
  if (marker.type === "progress" && this.inAdBreak) {
4317
4313
  if (marker.durationSeconds != null) {
4318
- this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;
4319
- }
4320
- if (this.expectedAdBreakDurationMs != null && this.currentAdBreakStartWallClockMs != null) {
4321
- var elapsedMs1 = Date.now() - this.currentAdBreakStartWallClockMs;
4322
- var remainingMs1 = Math.max(0, this.expectedAdBreakDurationMs - elapsedMs1);
4323
- this.scheduleAdStopCountdown(remainingMs1);
4314
+ this.setAdBreakDurationBoundary(marker.durationSeconds * 1e3);
4324
4315
  }
4316
+ this.scheduleAdStopAtBreakBoundary();
4325
4317
  if (!this.adLayer.isAdPlaying() && this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0) {
4326
4318
  var bids = this.pendingNextAdBids;
4327
4319
  this.pendingNextAdBids = null;
@@ -4352,15 +4344,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4352
4344
  }
4353
4345
  return;
4354
4346
  }
4355
- if (adPlaying || remaining > 500) {
4356
- if (this.config.debugAdTiming) {
4357
- console.log("[StormcloudVideoPlayer] Ignoring premature SCTE-35 end marker - ads still active or time remaining");
4358
- }
4359
- return;
4360
- }
4361
- this.inAdBreak = false;
4362
- this.expectedAdBreakDurationMs = void 0;
4363
- this.currentAdBreakStartWallClockMs = void 0;
4347
+ this.scteAdBreakEndWallClockMs = Date.now();
4364
4348
  this.clearAdStartTimer();
4365
4349
  this.clearAdStopTimer();
4366
4350
  if (adPlaying) {
@@ -4371,6 +4355,42 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4371
4355
  }
4372
4356
  }
4373
4357
  },
4358
+ {
4359
+ key: "resolveScteBreakStartWallClockMs",
4360
+ value: function resolveScteBreakStartWallClockMs(marker) {
4361
+ var nowWallClockMs = Date.now();
4362
+ if (typeof marker.ptsSeconds !== "number") {
4363
+ return nowWallClockMs;
4364
+ }
4365
+ var nowMs = this.video.currentTime * 1e3;
4366
+ var estimatedCurrentPtsMs = nowMs - this.ptsDriftEmaMs;
4367
+ var deltaMs = marker.ptsSeconds * 1e3 - estimatedCurrentPtsMs;
4368
+ if (!Number.isFinite(deltaMs)) {
4369
+ return nowWallClockMs;
4370
+ }
4371
+ return nowWallClockMs + Math.floor(deltaMs);
4372
+ }
4373
+ },
4374
+ {
4375
+ key: "setAdBreakDurationBoundary",
4376
+ value: function setAdBreakDurationBoundary(durationMs) {
4377
+ this.expectedAdBreakDurationMs = durationMs;
4378
+ if (durationMs != null && this.currentAdBreakStartWallClockMs != null) {
4379
+ this.scteAdBreakEndWallClockMs = this.currentAdBreakStartWallClockMs + durationMs;
4380
+ } else {
4381
+ this.scteAdBreakEndWallClockMs = void 0;
4382
+ }
4383
+ }
4384
+ },
4385
+ {
4386
+ key: "scheduleAdStopAtBreakBoundary",
4387
+ value: function scheduleAdStopAtBreakBoundary() {
4388
+ if (this.expectedAdBreakDurationMs == null) {
4389
+ return;
4390
+ }
4391
+ this.scheduleAdStopCountdown(this.getRemainingAdMs());
4392
+ }
4393
+ },
4374
4394
  {
4375
4395
  key: "parseCueOutDuration",
4376
4396
  value: function parseCueOutDuration(value) {
@@ -5006,7 +5026,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5006
5026
  case 9:
5007
5027
  _state.sent();
5008
5028
  if (_this.expectedAdBreakDurationMs != null && _this.adStopTimerId == null) {
5009
- _this.scheduleAdStopCountdown(_this.getRemainingAdMs());
5029
+ _this.scheduleAdStopAtBreakBoundary();
5010
5030
  }
5011
5031
  _this.adLayer.setAdVolume(_this.adLayer.getOriginalMutedState() ? 1 : _this.adLayer.getOriginalVolume());
5012
5032
  return [
@@ -5111,7 +5131,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5111
5131
  case 19:
5112
5132
  _state.sent();
5113
5133
  if (_this.expectedAdBreakDurationMs != null && _this.adStopTimerId == null) {
5114
- _this.scheduleAdStopCountdown(_this.getRemainingAdMs());
5134
+ _this.scheduleAdStopAtBreakBoundary();
5115
5135
  }
5116
5136
  _this.adLayer.setAdVolume(_this.adLayer.getOriginalMutedState() ? 1 : _this.adLayer.getOriginalVolume());
5117
5137
  _state.label = 20;
@@ -5194,7 +5214,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5194
5214
  key: "handleAdStart",
5195
5215
  value: function handleAdStart(_marker) {
5196
5216
  return _async_to_generator(function() {
5197
- var _this_savedMutedStateBeforeScte, adBreakDurationMs, mode, state, adBreakToken, adVolume, token, remaining, err;
5217
+ var _this_savedMutedStateBeforeScte, adBreakDurationMs, mode, state, fillerRemainingMs, adBreakToken, adVolume, token, remaining, err;
5198
5218
  return _ts_generator(this, function(_state) {
5199
5219
  switch(_state.label){
5200
5220
  case 0:
@@ -5228,20 +5248,21 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5228
5248
  }
5229
5249
  }
5230
5250
  this.inAdBreak = true;
5231
- this.currentAdBreakStartWallClockMs = Date.now();
5232
5251
  this.currentAdIndex = 0;
5233
5252
  this.totalAdsInBreak = Math.max(1, this.preloadedTokens.length);
5234
5253
  this.adPodQueue = [];
5235
5254
  if (!this.config.disableFiller) this.showAds = true;
5236
- if (adBreakDurationMs != null) {
5237
- this.startFillerBreakTimer(adBreakDurationMs);
5255
+ if (this.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {
5256
+ this.currentAdBreakStartWallClockMs = Date.now();
5257
+ this.setAdBreakDurationBoundary(adBreakDurationMs);
5258
+ }
5259
+ fillerRemainingMs = this.getRemainingAdMs();
5260
+ if (this.expectedAdBreakDurationMs != null && fillerRemainingMs > 0) {
5261
+ this.startFillerBreakTimer(fillerRemainingMs);
5238
5262
  } else if (!this.config.disableFiller && this.preloadedTokens.length === 0) {
5239
5263
  this.showPlaceholderLayer();
5240
5264
  }
5241
5265
  if (!this.config.disableFiller) this.adLayer.showPlaceholder();
5242
- if (this.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {
5243
- this.expectedAdBreakDurationMs = adBreakDurationMs;
5244
- }
5245
5266
  this.clearPendingAdBreak();
5246
5267
  adBreakToken = Date.now();
5247
5268
  this.activeAdRequestToken = adBreakToken;
@@ -5278,7 +5299,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5278
5299
  case 2:
5279
5300
  _state.sent();
5280
5301
  if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
5281
- this.scheduleAdStopCountdown(this.getRemainingAdMs());
5302
+ this.scheduleAdStopAtBreakBoundary();
5282
5303
  }
5283
5304
  this.adLayer.setAdVolume(adVolume);
5284
5305
  return [
@@ -5464,7 +5485,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5464
5485
  case 4:
5465
5486
  _state.sent();
5466
5487
  if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
5467
- this.scheduleAdStopCountdown(this.getRemainingAdMs());
5488
+ this.scheduleAdStopAtBreakBoundary();
5468
5489
  }
5469
5490
  this.adLayer.setAdVolume(this.adLayer.getOriginalMutedState() ? 1 : this.adLayer.getOriginalVolume());
5470
5491
  _state.label = 5;
@@ -5706,21 +5727,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5706
5727
  {
5707
5728
  key: "ensureAdStoppedByTimer",
5708
5729
  value: function ensureAdStoppedByTimer() {
5709
- var _this_config_adBreakCheckIntervalMs, _this_expectedAdBreakDurationMs;
5730
+ var _this_config_adBreakCheckIntervalMs, _this_getAdBreakEndWallClockMs;
5710
5731
  if (!this.inAdBreak) return;
5711
5732
  this.adStopTimerId = void 0;
5712
5733
  var adPlaying = this.adLayer.isAdPlaying();
5713
- var pendingAds = this.adPodQueue.length > 0;
5714
5734
  var checkIntervalMs = Math.max(250, Math.floor((_this_config_adBreakCheckIntervalMs = this.config.adBreakCheckIntervalMs) !== null && _this_config_adBreakCheckIntervalMs !== void 0 ? _this_config_adBreakCheckIntervalMs : 1e3));
5715
5735
  var maxExtensionMsConfig = this.config.maxAdBreakExtensionMs;
5716
- var maxExtensionMs = typeof maxExtensionMsConfig === "number" && maxExtensionMsConfig > 0 ? maxExtensionMsConfig : 6e4;
5717
- var elapsedSinceStartMs = 0;
5718
- if (this.currentAdBreakStartWallClockMs != null) {
5719
- elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;
5720
- }
5721
- var expectedDurationMs = (_this_expectedAdBreakDurationMs = this.expectedAdBreakDurationMs) !== null && _this_expectedAdBreakDurationMs !== void 0 ? _this_expectedAdBreakDurationMs : 0;
5722
- var overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);
5723
- var shouldExtendAdBreak = (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;
5736
+ var maxExtensionMs = typeof maxExtensionMsConfig === "number" && maxExtensionMsConfig > 0 ? maxExtensionMsConfig : 0;
5737
+ var endWallClockMs = (_this_getAdBreakEndWallClockMs = this.getAdBreakEndWallClockMs()) !== null && _this_getAdBreakEndWallClockMs !== void 0 ? _this_getAdBreakEndWallClockMs : Date.now();
5738
+ var overrunMs = Math.max(0, Date.now() - endWallClockMs);
5739
+ var shouldExtendAdBreak = adPlaying && overrunMs < maxExtensionMs;
5724
5740
  if (shouldExtendAdBreak) {
5725
5741
  this.scheduleAdStopCountdown(checkIntervalMs);
5726
5742
  return;
@@ -5794,6 +5810,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5794
5810
  this.inAdBreak = false;
5795
5811
  this.expectedAdBreakDurationMs = void 0;
5796
5812
  this.currentAdBreakStartWallClockMs = void 0;
5813
+ this.scteAdBreakEndWallClockMs = void 0;
5797
5814
  this.clearAdStartTimer();
5798
5815
  this.clearAdStopTimer();
5799
5816
  this.adPodQueue = [];
@@ -6055,10 +6072,25 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6055
6072
  {
6056
6073
  key: "getRemainingAdMs",
6057
6074
  value: function getRemainingAdMs() {
6075
+ var endWallClockMs = this.getAdBreakEndWallClockMs();
6076
+ if (endWallClockMs != null) {
6077
+ return Math.max(0, endWallClockMs - Date.now());
6078
+ }
6058
6079
  if (this.currentAdBreakStartWallClockMs == null) return 0;
6059
6080
  if (this.expectedAdBreakDurationMs == null) return Number.MAX_SAFE_INTEGER;
6060
- var elapsed = Date.now() - this.currentAdBreakStartWallClockMs;
6061
- return Math.max(0, this.expectedAdBreakDurationMs - elapsed);
6081
+ return 0;
6082
+ }
6083
+ },
6084
+ {
6085
+ key: "getAdBreakEndWallClockMs",
6086
+ value: function getAdBreakEndWallClockMs() {
6087
+ if (this.scteAdBreakEndWallClockMs != null) {
6088
+ return this.scteAdBreakEndWallClockMs;
6089
+ }
6090
+ if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null) {
6091
+ return void 0;
6092
+ }
6093
+ return this.currentAdBreakStartWallClockMs + this.expectedAdBreakDurationMs;
6062
6094
  }
6063
6095
  },
6064
6096
  {