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.
@@ -12,6 +12,7 @@ declare class StormcloudVideoPlayer {
12
12
  private inAdBreak;
13
13
  private currentAdBreakStartWallClockMs;
14
14
  private expectedAdBreakDurationMs;
15
+ private scteAdBreakEndWallClockMs;
15
16
  private adStopTimerId;
16
17
  private adStartTimerId;
17
18
  private adFailsafeTimerId;
@@ -75,6 +76,9 @@ declare class StormcloudVideoPlayer {
75
76
  private parseScte35FromId3;
76
77
  private decodeId3ValueToText;
77
78
  private onScte35Marker;
79
+ private resolveScteBreakStartWallClockMs;
80
+ private setAdBreakDurationBoundary;
81
+ private scheduleAdStopAtBreakBoundary;
78
82
  private parseCueOutDuration;
79
83
  private parseCueOutCont;
80
84
  private parseAttributeList;
@@ -117,6 +121,7 @@ declare class StormcloudVideoPlayer {
117
121
  private clearAdFailsafeTimer;
118
122
  private logAdState;
119
123
  private getRemainingAdMs;
124
+ private getAdBreakEndWallClockMs;
120
125
  toggleMute(): void;
121
126
  toggleFullscreen(): Promise<void>;
122
127
  isMuted(): boolean;
@@ -3782,7 +3782,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3782
3782
  _this.adLayer.showPlaceholder();
3783
3783
  }
3784
3784
  if (_this.inAdBreak && _this.expectedAdBreakDurationMs != null && _this.adStopTimerId == null) {
3785
- _this.scheduleAdStopCountdown(_this.getRemainingAdMs());
3785
+ _this.scheduleAdStopAtBreakBoundary();
3786
3786
  if (_this.config.debugAdTiming) {
3787
3787
  console.log("[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)");
3788
3788
  }
@@ -4216,12 +4216,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4216
4216
  if (marker.durationSeconds != null) {
4217
4217
  var newDurationMs = marker.durationSeconds * 1e3;
4218
4218
  if (this.expectedAdBreakDurationMs == null || newDurationMs > this.expectedAdBreakDurationMs) {
4219
- this.expectedAdBreakDurationMs = newDurationMs;
4220
- var elapsedMs = this.currentAdBreakStartWallClockMs != null ? Date.now() - this.currentAdBreakStartWallClockMs : 0;
4221
- var remainingMs = Math.max(0, newDurationMs - elapsedMs);
4222
- this.scheduleAdStopCountdown(remainingMs);
4219
+ this.setAdBreakDurationBoundary(newDurationMs);
4220
+ this.scheduleAdStopAtBreakBoundary();
4223
4221
  if (this.config.debugAdTiming) {
4224
- console.log("[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ".concat(newDurationMs, "ms, remaining: ").concat(remainingMs, "ms"));
4222
+ console.log("[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ".concat(newDurationMs, "ms, remaining: ").concat(this.getRemainingAdMs(), "ms"));
4225
4223
  }
4226
4224
  }
4227
4225
  }
@@ -4229,8 +4227,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4229
4227
  }
4230
4228
  this.inAdBreak = true;
4231
4229
  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;
4232
- this.expectedAdBreakDurationMs = durationMs;
4233
- this.currentAdBreakStartWallClockMs = Date.now();
4230
+ this.currentAdBreakStartWallClockMs = this.resolveScteBreakStartWallClockMs(marker);
4231
+ this.setAdBreakDurationBoundary(durationMs);
4234
4232
  if (this.config.licenseKey) {
4235
4233
  var _this_pendingAdBreak1;
4236
4234
  var adDetectInfo = _object_spread({
@@ -4294,20 +4292,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4294
4292
  this.clearAdStartTimer();
4295
4293
  this.handleAdStart(marker);
4296
4294
  }
4297
- if (this.expectedAdBreakDurationMs != null) {
4298
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
4299
- }
4295
+ this.scheduleAdStopAtBreakBoundary();
4300
4296
  return;
4301
4297
  }
4302
4298
  if (marker.type === "progress" && this.inAdBreak) {
4303
4299
  if (marker.durationSeconds != null) {
4304
- this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;
4305
- }
4306
- if (this.expectedAdBreakDurationMs != null && this.currentAdBreakStartWallClockMs != null) {
4307
- var elapsedMs1 = Date.now() - this.currentAdBreakStartWallClockMs;
4308
- var remainingMs1 = Math.max(0, this.expectedAdBreakDurationMs - elapsedMs1);
4309
- this.scheduleAdStopCountdown(remainingMs1);
4300
+ this.setAdBreakDurationBoundary(marker.durationSeconds * 1e3);
4310
4301
  }
4302
+ this.scheduleAdStopAtBreakBoundary();
4311
4303
  if (!this.adLayer.isAdPlaying() && this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0) {
4312
4304
  var bids = this.pendingNextAdBids;
4313
4305
  this.pendingNextAdBids = null;
@@ -4338,15 +4330,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4338
4330
  }
4339
4331
  return;
4340
4332
  }
4341
- if (adPlaying || remaining > 500) {
4342
- if (this.config.debugAdTiming) {
4343
- console.log("[StormcloudVideoPlayer] Ignoring premature SCTE-35 end marker - ads still active or time remaining");
4344
- }
4345
- return;
4346
- }
4347
- this.inAdBreak = false;
4348
- this.expectedAdBreakDurationMs = void 0;
4349
- this.currentAdBreakStartWallClockMs = void 0;
4333
+ this.scteAdBreakEndWallClockMs = Date.now();
4350
4334
  this.clearAdStartTimer();
4351
4335
  this.clearAdStopTimer();
4352
4336
  if (adPlaying) {
@@ -4357,6 +4341,42 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4357
4341
  }
4358
4342
  }
4359
4343
  },
4344
+ {
4345
+ key: "resolveScteBreakStartWallClockMs",
4346
+ value: function resolveScteBreakStartWallClockMs(marker) {
4347
+ var nowWallClockMs = Date.now();
4348
+ if (typeof marker.ptsSeconds !== "number") {
4349
+ return nowWallClockMs;
4350
+ }
4351
+ var nowMs = this.video.currentTime * 1e3;
4352
+ var estimatedCurrentPtsMs = nowMs - this.ptsDriftEmaMs;
4353
+ var deltaMs = marker.ptsSeconds * 1e3 - estimatedCurrentPtsMs;
4354
+ if (!Number.isFinite(deltaMs)) {
4355
+ return nowWallClockMs;
4356
+ }
4357
+ return nowWallClockMs + Math.floor(deltaMs);
4358
+ }
4359
+ },
4360
+ {
4361
+ key: "setAdBreakDurationBoundary",
4362
+ value: function setAdBreakDurationBoundary(durationMs) {
4363
+ this.expectedAdBreakDurationMs = durationMs;
4364
+ if (durationMs != null && this.currentAdBreakStartWallClockMs != null) {
4365
+ this.scteAdBreakEndWallClockMs = this.currentAdBreakStartWallClockMs + durationMs;
4366
+ } else {
4367
+ this.scteAdBreakEndWallClockMs = void 0;
4368
+ }
4369
+ }
4370
+ },
4371
+ {
4372
+ key: "scheduleAdStopAtBreakBoundary",
4373
+ value: function scheduleAdStopAtBreakBoundary() {
4374
+ if (this.expectedAdBreakDurationMs == null) {
4375
+ return;
4376
+ }
4377
+ this.scheduleAdStopCountdown(this.getRemainingAdMs());
4378
+ }
4379
+ },
4360
4380
  {
4361
4381
  key: "parseCueOutDuration",
4362
4382
  value: function parseCueOutDuration(value) {
@@ -4992,7 +5012,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4992
5012
  case 9:
4993
5013
  _state.sent();
4994
5014
  if (_this.expectedAdBreakDurationMs != null && _this.adStopTimerId == null) {
4995
- _this.scheduleAdStopCountdown(_this.getRemainingAdMs());
5015
+ _this.scheduleAdStopAtBreakBoundary();
4996
5016
  }
4997
5017
  _this.adLayer.setAdVolume(_this.adLayer.getOriginalMutedState() ? 1 : _this.adLayer.getOriginalVolume());
4998
5018
  return [
@@ -5097,7 +5117,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5097
5117
  case 19:
5098
5118
  _state.sent();
5099
5119
  if (_this.expectedAdBreakDurationMs != null && _this.adStopTimerId == null) {
5100
- _this.scheduleAdStopCountdown(_this.getRemainingAdMs());
5120
+ _this.scheduleAdStopAtBreakBoundary();
5101
5121
  }
5102
5122
  _this.adLayer.setAdVolume(_this.adLayer.getOriginalMutedState() ? 1 : _this.adLayer.getOriginalVolume());
5103
5123
  _state.label = 20;
@@ -5180,7 +5200,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5180
5200
  key: "handleAdStart",
5181
5201
  value: function handleAdStart(_marker) {
5182
5202
  return _async_to_generator(function() {
5183
- var _this_savedMutedStateBeforeScte, adBreakDurationMs, mode, state, adBreakToken, adVolume, token, remaining, err;
5203
+ var _this_savedMutedStateBeforeScte, adBreakDurationMs, mode, state, fillerRemainingMs, adBreakToken, adVolume, token, remaining, err;
5184
5204
  return _ts_generator(this, function(_state) {
5185
5205
  switch(_state.label){
5186
5206
  case 0:
@@ -5214,20 +5234,21 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5214
5234
  }
5215
5235
  }
5216
5236
  this.inAdBreak = true;
5217
- this.currentAdBreakStartWallClockMs = Date.now();
5218
5237
  this.currentAdIndex = 0;
5219
5238
  this.totalAdsInBreak = Math.max(1, this.preloadedTokens.length);
5220
5239
  this.adPodQueue = [];
5221
5240
  if (!this.config.disableFiller) this.showAds = true;
5222
- if (adBreakDurationMs != null) {
5223
- this.startFillerBreakTimer(adBreakDurationMs);
5241
+ if (this.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {
5242
+ this.currentAdBreakStartWallClockMs = Date.now();
5243
+ this.setAdBreakDurationBoundary(adBreakDurationMs);
5244
+ }
5245
+ fillerRemainingMs = this.getRemainingAdMs();
5246
+ if (this.expectedAdBreakDurationMs != null && fillerRemainingMs > 0) {
5247
+ this.startFillerBreakTimer(fillerRemainingMs);
5224
5248
  } else if (!this.config.disableFiller && this.preloadedTokens.length === 0) {
5225
5249
  this.showPlaceholderLayer();
5226
5250
  }
5227
5251
  if (!this.config.disableFiller) this.adLayer.showPlaceholder();
5228
- if (this.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {
5229
- this.expectedAdBreakDurationMs = adBreakDurationMs;
5230
- }
5231
5252
  this.clearPendingAdBreak();
5232
5253
  adBreakToken = Date.now();
5233
5254
  this.activeAdRequestToken = adBreakToken;
@@ -5264,7 +5285,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5264
5285
  case 2:
5265
5286
  _state.sent();
5266
5287
  if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
5267
- this.scheduleAdStopCountdown(this.getRemainingAdMs());
5288
+ this.scheduleAdStopAtBreakBoundary();
5268
5289
  }
5269
5290
  this.adLayer.setAdVolume(adVolume);
5270
5291
  return [
@@ -5450,7 +5471,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5450
5471
  case 4:
5451
5472
  _state.sent();
5452
5473
  if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
5453
- this.scheduleAdStopCountdown(this.getRemainingAdMs());
5474
+ this.scheduleAdStopAtBreakBoundary();
5454
5475
  }
5455
5476
  this.adLayer.setAdVolume(this.adLayer.getOriginalMutedState() ? 1 : this.adLayer.getOriginalVolume());
5456
5477
  _state.label = 5;
@@ -5692,21 +5713,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5692
5713
  {
5693
5714
  key: "ensureAdStoppedByTimer",
5694
5715
  value: function ensureAdStoppedByTimer() {
5695
- var _this_config_adBreakCheckIntervalMs, _this_expectedAdBreakDurationMs;
5716
+ var _this_config_adBreakCheckIntervalMs, _this_getAdBreakEndWallClockMs;
5696
5717
  if (!this.inAdBreak) return;
5697
5718
  this.adStopTimerId = void 0;
5698
5719
  var adPlaying = this.adLayer.isAdPlaying();
5699
- var pendingAds = this.adPodQueue.length > 0;
5700
5720
  var checkIntervalMs = Math.max(250, Math.floor((_this_config_adBreakCheckIntervalMs = this.config.adBreakCheckIntervalMs) !== null && _this_config_adBreakCheckIntervalMs !== void 0 ? _this_config_adBreakCheckIntervalMs : 1e3));
5701
5721
  var maxExtensionMsConfig = this.config.maxAdBreakExtensionMs;
5702
- var maxExtensionMs = typeof maxExtensionMsConfig === "number" && maxExtensionMsConfig > 0 ? maxExtensionMsConfig : 6e4;
5703
- var elapsedSinceStartMs = 0;
5704
- if (this.currentAdBreakStartWallClockMs != null) {
5705
- elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;
5706
- }
5707
- var expectedDurationMs = (_this_expectedAdBreakDurationMs = this.expectedAdBreakDurationMs) !== null && _this_expectedAdBreakDurationMs !== void 0 ? _this_expectedAdBreakDurationMs : 0;
5708
- var overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);
5709
- var shouldExtendAdBreak = (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;
5722
+ var maxExtensionMs = typeof maxExtensionMsConfig === "number" && maxExtensionMsConfig > 0 ? maxExtensionMsConfig : 0;
5723
+ var endWallClockMs = (_this_getAdBreakEndWallClockMs = this.getAdBreakEndWallClockMs()) !== null && _this_getAdBreakEndWallClockMs !== void 0 ? _this_getAdBreakEndWallClockMs : Date.now();
5724
+ var overrunMs = Math.max(0, Date.now() - endWallClockMs);
5725
+ var shouldExtendAdBreak = adPlaying && overrunMs < maxExtensionMs;
5710
5726
  if (shouldExtendAdBreak) {
5711
5727
  this.scheduleAdStopCountdown(checkIntervalMs);
5712
5728
  return;
@@ -5780,6 +5796,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5780
5796
  this.inAdBreak = false;
5781
5797
  this.expectedAdBreakDurationMs = void 0;
5782
5798
  this.currentAdBreakStartWallClockMs = void 0;
5799
+ this.scteAdBreakEndWallClockMs = void 0;
5783
5800
  this.clearAdStartTimer();
5784
5801
  this.clearAdStopTimer();
5785
5802
  this.adPodQueue = [];
@@ -6041,10 +6058,25 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6041
6058
  {
6042
6059
  key: "getRemainingAdMs",
6043
6060
  value: function getRemainingAdMs() {
6061
+ var endWallClockMs = this.getAdBreakEndWallClockMs();
6062
+ if (endWallClockMs != null) {
6063
+ return Math.max(0, endWallClockMs - Date.now());
6064
+ }
6044
6065
  if (this.currentAdBreakStartWallClockMs == null) return 0;
6045
6066
  if (this.expectedAdBreakDurationMs == null) return Number.MAX_SAFE_INTEGER;
6046
- var elapsed = Date.now() - this.currentAdBreakStartWallClockMs;
6047
- return Math.max(0, this.expectedAdBreakDurationMs - elapsed);
6067
+ return 0;
6068
+ }
6069
+ },
6070
+ {
6071
+ key: "getAdBreakEndWallClockMs",
6072
+ value: function getAdBreakEndWallClockMs() {
6073
+ if (this.scteAdBreakEndWallClockMs != null) {
6074
+ return this.scteAdBreakEndWallClockMs;
6075
+ }
6076
+ if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null) {
6077
+ return void 0;
6078
+ }
6079
+ return this.currentAdBreakStartWallClockMs + this.expectedAdBreakDurationMs;
6048
6080
  }
6049
6081
  },
6050
6082
  {