stormcloud-video-player 0.3.62 → 0.3.63

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.
@@ -1,4 +1,4 @@
1
- import { S as StormcloudVideoPlayerConfig } from '../types-BJPNhfLV.cjs';
1
+ import { S as StormcloudVideoPlayerConfig } from '../types-CjI14dPN.cjs';
2
2
 
3
3
  declare class StormcloudVideoPlayer {
4
4
  private readonly video;
@@ -42,6 +42,7 @@ declare class StormcloudVideoPlayer {
42
42
  private maxPlaceholderDurationMs;
43
43
  private isShowingPlaceholder;
44
44
  private timeUpdateHandler?;
45
+ private endedHandler?;
45
46
  private emptiedHandler?;
46
47
  private readonly tsScte35Pids;
47
48
  private readonly pmtPids;
@@ -128,9 +129,11 @@ declare class StormcloudVideoPlayer {
128
129
  private markerTypeFromSegmentationTypeId;
129
130
  private initializeTracking;
130
131
  private sendHeartbeatIfNeeded;
132
+ private isVmapEnabled;
131
133
  private fetchAdConfiguration;
132
134
  private fetchAndParseVmap;
133
135
  private parseVmapToBreaks;
136
+ private resolveVmapAdTagUrl;
134
137
  private parseVmapTimeOffsetToMs;
135
138
  private getAdBreakKey;
136
139
  private resolveBreakStartMs;
@@ -160,7 +163,8 @@ declare class StormcloudVideoPlayer {
160
163
  private showPlaceholderAndWaitForAds;
161
164
  private findCurrentOrNextBreak;
162
165
  private onTimeUpdate;
163
- private handleMidAdJoin;
166
+ private onVideoEnded;
167
+ private handleVmapAdBreak;
164
168
  private scheduleAdStopCountdown;
165
169
  private clearAdStopTimer;
166
170
  private ensureAdStoppedByTimer;
@@ -3492,7 +3492,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3492
3492
  var _level_details, _level_details1;
3493
3493
  return (level === null || level === void 0 ? void 0 : (_level_details = level.details) === null || _level_details === void 0 ? void 0 : _level_details.live) === true || (level === null || level === void 0 ? void 0 : (_level_details1 = level.details) === null || _level_details1 === void 0 ? void 0 : _level_details1.type) === "LIVE";
3494
3494
  })) !== null && _ref !== void 0 ? _ref : false;
3495
- if (!this.isLiveStream && this.vmapBreaks.length === 0 && this.apiVastTagUrl) {
3495
+ if (!this.isVmapEnabled() && !this.isLiveStream && this.vmapBreaks.length === 0 && this.apiVastTagUrl) {
3496
3496
  prerollKey = "synthetic-vod-preroll";
3497
3497
  if (!this.consumedVmapBreakIds.has(prerollKey)) {
3498
3498
  this.vmapBreaks = [
@@ -4075,6 +4075,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4075
4075
  _this.onTimeUpdate(_this.video.currentTime);
4076
4076
  };
4077
4077
  this.video.addEventListener("timeupdate", this.timeUpdateHandler);
4078
+ this.endedHandler = function() {
4079
+ _this.onVideoEnded();
4080
+ };
4081
+ this.video.addEventListener("ended", this.endedHandler);
4078
4082
  this.emptiedHandler = function() {
4079
4083
  if (_this.nativeHlsMode && _this.videoSrcProtection && !_this.ima.isAdPlaying()) {
4080
4084
  if (_this.config.debugAdTiming) {
@@ -5386,6 +5390,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5386
5390
  }
5387
5391
  }
5388
5392
  },
5393
+ {
5394
+ key: "isVmapEnabled",
5395
+ value: function isVmapEnabled() {
5396
+ var _this_config_vmapUrl;
5397
+ return !!(this.config.isVmap && ((_this_config_vmapUrl = this.config.vmapUrl) === null || _this_config_vmapUrl === void 0 ? void 0 : _this_config_vmapUrl.trim()));
5398
+ }
5399
+ },
5389
5400
  {
5390
5401
  key: "fetchAdConfiguration",
5391
5402
  value: function fetchAdConfiguration() {
@@ -5394,7 +5405,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5394
5405
  return _ts_generator(this, function(_state) {
5395
5406
  switch(_state.label){
5396
5407
  case 0:
5397
- if (!this.config.vmapUrl) return [
5408
+ if (!this.isVmapEnabled()) return [
5398
5409
  3,
5399
5410
  2
5400
5411
  ];
@@ -5404,7 +5415,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5404
5415
  ];
5405
5416
  case 1:
5406
5417
  _state.sent();
5407
- _state.label = 2;
5418
+ if (this.config.debugAdTiming) {
5419
+ console.log("[StormcloudVideoPlayer] VMAP mode enabled");
5420
+ }
5421
+ return [
5422
+ 2
5423
+ ];
5408
5424
  case 2:
5409
5425
  vastMode = this.config.vastMode || "default";
5410
5426
  if (this.config.debugAdTiming) {
@@ -5572,7 +5588,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5572
5588
  }
5573
5589
  return [];
5574
5590
  }
5575
- var adBreakNodes = Array.from(doc.querySelectorAll("AdBreak, vmap\\:AdBreak"));
5591
+ var VMAP_NS = "http://www.iab.net/videosuite/vmap";
5592
+ var adBreakNodes = Array.from(doc.getElementsByTagNameNS(VMAP_NS, "AdBreak"));
5593
+ if (adBreakNodes.length === 0) {
5594
+ adBreakNodes = Array.from(doc.querySelectorAll("AdBreak, vmap\\:AdBreak"));
5595
+ }
5596
+ if (adBreakNodes.length === 0) {
5597
+ adBreakNodes = Array.from(doc.getElementsByTagName("*")).filter(function(el) {
5598
+ return el.localName === "AdBreak";
5599
+ });
5600
+ }
5576
5601
  var parsed = [];
5577
5602
  adBreakNodes.forEach(function(node, index) {
5578
5603
  var timeOffsetRaw = (node.getAttribute("timeOffset") || "").trim();
@@ -5580,8 +5605,17 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5580
5605
  if (startTimeMs == null) {
5581
5606
  return;
5582
5607
  }
5583
- var adTagNode = node.querySelector("AdTagURI, vmap\\:AdTagURI");
5584
- var adTagUrl = ((adTagNode === null || adTagNode === void 0 ? void 0 : adTagNode.textContent) || "").trim();
5608
+ var adTagNode = node.getElementsByTagNameNS(VMAP_NS, "AdTagURI")[0];
5609
+ if (!adTagNode) {
5610
+ var _node_querySelector;
5611
+ adTagNode = (_node_querySelector = node.querySelector("AdTagURI, vmap\\:AdTagURI")) !== null && _node_querySelector !== void 0 ? _node_querySelector : void 0;
5612
+ }
5613
+ if (!adTagNode) {
5614
+ adTagNode = Array.from(node.getElementsByTagName("*")).find(function(el) {
5615
+ return el.localName === "AdTagURI";
5616
+ });
5617
+ }
5618
+ var adTagUrl = _this.resolveVmapAdTagUrl(((adTagNode === null || adTagNode === void 0 ? void 0 : adTagNode.textContent) || "").trim());
5585
5619
  if (!adTagUrl) {
5586
5620
  return;
5587
5621
  }
@@ -5600,6 +5634,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5600
5634
  return parsed;
5601
5635
  }
5602
5636
  },
5637
+ {
5638
+ key: "resolveVmapAdTagUrl",
5639
+ value: function resolveVmapAdTagUrl(url) {
5640
+ if (!url) {
5641
+ return "";
5642
+ }
5643
+ return url.replace(/\[timestamp\]/gi, String(Date.now())).replace(/\$\{GDPR\}/gi, "0").trim();
5644
+ }
5645
+ },
5603
5646
  {
5604
5647
  key: "parseVmapTimeOffsetToMs",
5605
5648
  value: function parseVmapTimeOffsetToMs(timeOffset) {
@@ -5622,6 +5665,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5622
5665
  var millis = Number(ms.padEnd(3, "0").slice(0, 3));
5623
5666
  return (hours * 3600 + minutes * 60 + seconds) * 1e3 + millis;
5624
5667
  }
5668
+ var msOnly = timeOffset.match(/^(\d{1,2}):(\d{2})(?:\.(\d{1,3}))?$/);
5669
+ if (msOnly) {
5670
+ var _msOnly = _sliced_to_array(msOnly, 4), mm1 = _msOnly[1], ss1 = _msOnly[2], tmp1 = _msOnly[3], ms1 = tmp1 === void 0 ? "0" : tmp1;
5671
+ var minutes1 = Number(mm1);
5672
+ var seconds1 = Number(ss1);
5673
+ var millis1 = Number(ms1.padEnd(3, "0").slice(0, 3));
5674
+ return (minutes1 * 60 + seconds1) * 1e3 + millis1;
5675
+ }
5625
5676
  var percent = timeOffset.match(/^(\d+(?:\.\d+)?)%$/);
5626
5677
  if (percent) {
5627
5678
  var ratio = Number(percent[1]) / 100;
@@ -7137,23 +7188,49 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7137
7188
  key: "onTimeUpdate",
7138
7189
  value: function onTimeUpdate(currentTimeSec) {
7139
7190
  var _this = this;
7191
+ if (!this.isVmapEnabled() || this.vmapBreaks.length === 0) {
7192
+ return;
7193
+ }
7140
7194
  if (this.ima.isAdPlaying() || this.inAdBreak) return;
7141
7195
  var nowMs = currentTimeSec * 1e3;
7142
7196
  var breakToPlay = this.findBreakForTime(nowMs);
7143
7197
  if (breakToPlay) {
7144
- void this.handleMidAdJoin(breakToPlay, nowMs).catch(function(error) {
7198
+ void this.handleVmapAdBreak(breakToPlay, nowMs).catch(function(error) {
7199
+ if (_this.config.debugAdTiming) {
7200
+ console.warn("[StormcloudVideoPlayer] VMAP ad break failed gracefully:", error);
7201
+ }
7202
+ });
7203
+ }
7204
+ }
7205
+ },
7206
+ {
7207
+ key: "onVideoEnded",
7208
+ value: function onVideoEnded() {
7209
+ var _this = this;
7210
+ if (!this.isVmapEnabled() || this.vmapBreaks.length === 0) {
7211
+ return;
7212
+ }
7213
+ if (this.ima.isAdPlaying() || this.inAdBreak) {
7214
+ return;
7215
+ }
7216
+ var durationMs = Number.isFinite(this.video.duration) ? Math.floor(this.video.duration * 1e3) : 0;
7217
+ var postroll = this.vmapBreaks.find(function(b) {
7218
+ return b.startTimeMs === -1 && !_this.consumedVmapBreakIds.has(_this.getAdBreakKey(b));
7219
+ });
7220
+ if (postroll) {
7221
+ void this.handleVmapAdBreak(postroll, durationMs).catch(function(error) {
7145
7222
  if (_this.config.debugAdTiming) {
7146
- console.warn("[StormcloudVideoPlayer] Mid-roll VMAP join failed gracefully:", error);
7223
+ console.warn("[StormcloudVideoPlayer] VMAP post-roll failed gracefully:", error);
7147
7224
  }
7148
7225
  });
7149
7226
  }
7150
7227
  }
7151
7228
  },
7152
7229
  {
7153
- key: "handleMidAdJoin",
7154
- value: function handleMidAdJoin(adBreak, nowMs) {
7230
+ key: "handleVmapAdBreak",
7231
+ value: function handleVmapAdBreak(adBreak, nowMs) {
7155
7232
  return _async_to_generator(function() {
7156
- var _adBreak_durationMs, _this_config_driftToleranceMs, key, breakStartMs, durationMs, endMs, tol, inWindow, remainingMs, tags, first, rest, error;
7233
+ var _adBreak_durationMs, key, breakStartMs, durationMs, endMs, inWindow, tags, first, rest, error;
7157
7234
  return _ts_generator(this, function(_state) {
7158
7235
  switch(_state.label){
7159
7236
  case 0:
@@ -7171,25 +7248,28 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7171
7248
  }
7172
7249
  durationMs = (_adBreak_durationMs = adBreak.durationMs) !== null && _adBreak_durationMs !== void 0 ? _adBreak_durationMs : 0;
7173
7250
  endMs = breakStartMs + durationMs;
7174
- tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
7175
- inWindow = durationMs > 0 ? nowMs > breakStartMs && nowMs < endMs : nowMs + tol >= breakStartMs;
7251
+ inWindow = durationMs > 0 ? nowMs >= breakStartMs && nowMs < endMs : nowMs >= breakStartMs;
7176
7252
  if (!inWindow) return [
7177
7253
  3,
7178
7254
  4
7179
7255
  ];
7180
7256
  this.consumedVmapBreakIds.add(key);
7181
- remainingMs = durationMs > 0 ? Math.max(0, endMs - nowMs) : 0;
7182
- tags = this.selectVastTagsForBreak(adBreak) || (this.apiVastTagUrl ? [
7183
- this.apiVastTagUrl
7184
- ] : void 0);
7185
- if (!(tags && tags.length > 0)) return [
7186
- 3,
7187
- 4
7188
- ];
7257
+ tags = this.selectVastTagsForBreak(adBreak);
7258
+ if (!tags || tags.length === 0) {
7259
+ return [
7260
+ 2
7261
+ ];
7262
+ }
7189
7263
  first = tags[0];
7190
7264
  rest = tags.slice(1);
7191
7265
  this.adPodQueue = rest;
7192
7266
  this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
7267
+ this.showAds = true;
7268
+ this.inAdBreak = true;
7269
+ this.currentAdBreakStartWallClockMs = Date.now();
7270
+ if (!this.video.paused) {
7271
+ this.video.pause();
7272
+ }
7193
7273
  _state.label = 1;
7194
7274
  case 1:
7195
7275
  _state.trys.push([
@@ -7204,10 +7284,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7204
7284
  ];
7205
7285
  case 2:
7206
7286
  _state.sent();
7207
- this.inAdBreak = true;
7208
- this.expectedAdBreakDurationMs = remainingMs;
7209
- this.currentAdBreakStartWallClockMs = Date.now();
7210
- this.scheduleAdStopCountdown(remainingMs);
7211
7287
  return [
7212
7288
  3,
7213
7289
  4
@@ -7215,8 +7291,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7215
7291
  case 3:
7216
7292
  error = _state.sent();
7217
7293
  this.adPodQueue = [];
7294
+ this.inAdBreak = false;
7295
+ this.showAds = false;
7218
7296
  if (this.config.debugAdTiming) {
7219
- console.warn("[StormcloudVideoPlayer] Mid-roll VMAP ad request failed:", error);
7297
+ console.warn("[StormcloudVideoPlayer] VMAP ad request failed:", error);
7220
7298
  }
7221
7299
  return [
7222
7300
  3,
@@ -7887,16 +7965,18 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7887
7965
  {
7888
7966
  key: "selectVastTagsForBreak",
7889
7967
  value: function selectVastTagsForBreak(b) {
7968
+ var _this = this;
7890
7969
  if (!b || !b.vastTagUrl) return void 0;
7891
- if (b.vastTagUrl.includes(",")) {
7892
- return b.vastTagUrl.split(",").map(function(s) {
7893
- return s.trim();
7970
+ var resolvedUrl = this.resolveVmapAdTagUrl(b.vastTagUrl);
7971
+ if (resolvedUrl.includes(",")) {
7972
+ return resolvedUrl.split(",").map(function(s) {
7973
+ return _this.resolveVmapAdTagUrl(s.trim());
7894
7974
  }).filter(function(s) {
7895
7975
  return s.length > 0;
7896
7976
  });
7897
7977
  }
7898
7978
  return [
7899
- b.vastTagUrl
7979
+ resolvedUrl
7900
7980
  ];
7901
7981
  }
7902
7982
  },
@@ -7928,9 +8008,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7928
8008
  {
7929
8009
  key: "findBreakForTime",
7930
8010
  value: function findBreakForTime(nowMs) {
7931
- var _this_config_driftToleranceMs;
7932
8011
  var schedule = this.vmapBreaks;
7933
- var tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
7934
8012
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
7935
8013
  try {
7936
8014
  for(var _iterator = schedule[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
@@ -7942,9 +8020,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7942
8020
  if (breakStartMs == null) {
7943
8021
  continue;
7944
8022
  }
7945
- var end = breakStartMs + (b.durationMs || 0);
7946
- var effectiveTol = breakStartMs === 0 ? Math.max(tol, 3e4) : tol;
7947
- if (nowMs >= breakStartMs && (b.durationMs ? nowMs < end : nowMs <= breakStartMs + effectiveTol)) {
8023
+ if (b.durationMs) {
8024
+ var end = breakStartMs + b.durationMs;
8025
+ if (nowMs >= breakStartMs && nowMs < end) {
8026
+ return b;
8027
+ }
8028
+ continue;
8029
+ }
8030
+ if (nowMs >= breakStartMs) {
7948
8031
  return b;
7949
8032
  }
7950
8033
  }
@@ -8152,6 +8235,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8152
8235
  this.video.removeEventListener("timeupdate", this.timeUpdateHandler);
8153
8236
  delete this.timeUpdateHandler;
8154
8237
  }
8238
+ if (this.endedHandler) {
8239
+ this.video.removeEventListener("ended", this.endedHandler);
8240
+ delete this.endedHandler;
8241
+ }
8155
8242
  if (this.emptiedHandler) {
8156
8243
  this.video.removeEventListener("emptied", this.emptiedHandler);
8157
8244
  delete this.emptiedHandler;