stormcloud-video-player 0.3.61 → 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,5 +1,5 @@
1
1
  import { Component } from 'react';
2
- import { S as StormcloudVideoPlayerConfig } from '../types-XKUJJhlG.cjs';
2
+ import { S as StormcloudVideoPlayerConfig } from '../types-CjI14dPN.cjs';
3
3
 
4
4
  interface HlsPlayerProps extends StormcloudVideoPlayerConfig {
5
5
  onMount?: (player: any) => void;
@@ -3425,7 +3425,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3425
3425
  key: "load",
3426
3426
  value: function load() {
3427
3427
  return _async_to_generator(function() {
3428
- var _this, error, _this_config_lowLatencyMode, _this_video_play;
3428
+ var _this, error, _this_config_isLiveStream, _this_config_lowLatencyMode, _this_video_play;
3429
3429
  return _ts_generator(this, function(_state) {
3430
3430
  switch(_state.label){
3431
3431
  case 0:
@@ -3469,7 +3469,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3469
3469
  this.nativeHlsMode = true;
3470
3470
  this.videoSrcProtection = this.config.src;
3471
3471
  this.video.src = this.config.src;
3472
- this.isLiveStream = (_this_config_lowLatencyMode = this.config.lowLatencyMode) !== null && _this_config_lowLatencyMode !== void 0 ? _this_config_lowLatencyMode : false;
3472
+ this.isLiveStream = (_this_config_isLiveStream = this.config.isLiveStream) !== null && _this_config_isLiveStream !== void 0 ? _this_config_isLiveStream : (_this_config_lowLatencyMode = this.config.lowLatencyMode) !== null && _this_config_lowLatencyMode !== void 0 ? _this_config_lowLatencyMode : false;
3473
3473
  if (this.config.debugAdTiming) {
3474
3474
  console.log("[StormcloudVideoPlayer] Using native HLS playback - VOD mode:", {
3475
3475
  isLive: this.isLiveStream,
@@ -3520,19 +3520,28 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3520
3520
  });
3521
3521
  this.hls.on(import_hls2.default.Events.MANIFEST_PARSED, function(_, data) {
3522
3522
  return _async_to_generator(function() {
3523
- var _this_config_minSegmentsBeforePlay, _ref, _this_hls_levels, _this_hls, adBehavior, minSegments, _this_video_play;
3523
+ var _this_config_isLiveStream, _ref, _this_config_minSegmentsBeforePlay, _this_hls_levels, _this_hls, prerollKey, adBehavior, minSegments, _this_video_play;
3524
3524
  return _ts_generator(this, function(_state) {
3525
3525
  switch(_state.label){
3526
3526
  case 0:
3527
- if (this.config.allowNativeHls === false) {
3528
- this.isLiveStream = true;
3529
- } else {
3530
- ;
3531
- ;
3532
- this.isLiveStream = (_ref = (_this_hls = this.hls) === null || _this_hls === void 0 ? void 0 : (_this_hls_levels = _this_hls.levels) === null || _this_hls_levels === void 0 ? void 0 : _this_hls_levels.some(function(level) {
3533
- var _level_details, _level_details1;
3534
- 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";
3535
- })) !== null && _ref !== void 0 ? _ref : false;
3527
+ this.isLiveStream = (_this_config_isLiveStream = this.config.isLiveStream) !== null && _this_config_isLiveStream !== void 0 ? _this_config_isLiveStream : (_ref = (_this_hls = this.hls) === null || _this_hls === void 0 ? void 0 : (_this_hls_levels = _this_hls.levels) === null || _this_hls_levels === void 0 ? void 0 : _this_hls_levels.some(function(level) {
3528
+ var _level_details, _level_details1;
3529
+ 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";
3530
+ })) !== null && _ref !== void 0 ? _ref : false;
3531
+ if (!this.isVmapEnabled() && !this.isLiveStream && this.vmapBreaks.length === 0 && this.apiVastTagUrl) {
3532
+ prerollKey = "synthetic-vod-preroll";
3533
+ if (!this.consumedVmapBreakIds.has(prerollKey)) {
3534
+ this.vmapBreaks = [
3535
+ {
3536
+ id: prerollKey,
3537
+ startTimeMs: 0,
3538
+ vastTagUrl: this.apiVastTagUrl
3539
+ }
3540
+ ];
3541
+ if (this.config.debugAdTiming) {
3542
+ console.log("[StormcloudVideoPlayer] Injected synthetic VOD preroll from apiVastTagUrl");
3543
+ }
3544
+ }
3536
3545
  }
3537
3546
  if (this.config.debugAdTiming) {
3538
3547
  adBehavior = this.shouldContinueLiveStreamDuringAds() ? "live (main video continues muted during ads)" : "vod (main video pauses during ads)";
@@ -4102,6 +4111,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4102
4111
  _this.onTimeUpdate(_this.video.currentTime);
4103
4112
  };
4104
4113
  this.video.addEventListener("timeupdate", this.timeUpdateHandler);
4114
+ this.endedHandler = function() {
4115
+ _this.onVideoEnded();
4116
+ };
4117
+ this.video.addEventListener("ended", this.endedHandler);
4105
4118
  this.emptiedHandler = function() {
4106
4119
  if (_this.nativeHlsMode && _this.videoSrcProtection && !_this.ima.isAdPlaying()) {
4107
4120
  if (_this.config.debugAdTiming) {
@@ -5413,6 +5426,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5413
5426
  }
5414
5427
  }
5415
5428
  },
5429
+ {
5430
+ key: "isVmapEnabled",
5431
+ value: function isVmapEnabled() {
5432
+ var _this_config_vmapUrl;
5433
+ return !!(this.config.isVmap && ((_this_config_vmapUrl = this.config.vmapUrl) === null || _this_config_vmapUrl === void 0 ? void 0 : _this_config_vmapUrl.trim()));
5434
+ }
5435
+ },
5416
5436
  {
5417
5437
  key: "fetchAdConfiguration",
5418
5438
  value: function fetchAdConfiguration() {
@@ -5421,7 +5441,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5421
5441
  return _ts_generator(this, function(_state) {
5422
5442
  switch(_state.label){
5423
5443
  case 0:
5424
- if (!this.config.vmapUrl) return [
5444
+ if (!this.isVmapEnabled()) return [
5425
5445
  3,
5426
5446
  2
5427
5447
  ];
@@ -5431,7 +5451,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5431
5451
  ];
5432
5452
  case 1:
5433
5453
  _state.sent();
5434
- _state.label = 2;
5454
+ if (this.config.debugAdTiming) {
5455
+ console.log("[StormcloudVideoPlayer] VMAP mode enabled");
5456
+ }
5457
+ return [
5458
+ 2
5459
+ ];
5435
5460
  case 2:
5436
5461
  vastMode = this.config.vastMode || "default";
5437
5462
  if (this.config.debugAdTiming) {
@@ -5599,7 +5624,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5599
5624
  }
5600
5625
  return [];
5601
5626
  }
5602
- var adBreakNodes = Array.from(doc.querySelectorAll("AdBreak, vmap\\:AdBreak"));
5627
+ var VMAP_NS = "http://www.iab.net/videosuite/vmap";
5628
+ var adBreakNodes = Array.from(doc.getElementsByTagNameNS(VMAP_NS, "AdBreak"));
5629
+ if (adBreakNodes.length === 0) {
5630
+ adBreakNodes = Array.from(doc.querySelectorAll("AdBreak, vmap\\:AdBreak"));
5631
+ }
5632
+ if (adBreakNodes.length === 0) {
5633
+ adBreakNodes = Array.from(doc.getElementsByTagName("*")).filter(function(el) {
5634
+ return el.localName === "AdBreak";
5635
+ });
5636
+ }
5603
5637
  var parsed = [];
5604
5638
  adBreakNodes.forEach(function(node, index) {
5605
5639
  var timeOffsetRaw = (node.getAttribute("timeOffset") || "").trim();
@@ -5607,8 +5641,17 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5607
5641
  if (startTimeMs == null) {
5608
5642
  return;
5609
5643
  }
5610
- var adTagNode = node.querySelector("AdTagURI, vmap\\:AdTagURI");
5611
- var adTagUrl = ((adTagNode === null || adTagNode === void 0 ? void 0 : adTagNode.textContent) || "").trim();
5644
+ var adTagNode = node.getElementsByTagNameNS(VMAP_NS, "AdTagURI")[0];
5645
+ if (!adTagNode) {
5646
+ var _node_querySelector;
5647
+ adTagNode = (_node_querySelector = node.querySelector("AdTagURI, vmap\\:AdTagURI")) !== null && _node_querySelector !== void 0 ? _node_querySelector : void 0;
5648
+ }
5649
+ if (!adTagNode) {
5650
+ adTagNode = Array.from(node.getElementsByTagName("*")).find(function(el) {
5651
+ return el.localName === "AdTagURI";
5652
+ });
5653
+ }
5654
+ var adTagUrl = _this.resolveVmapAdTagUrl(((adTagNode === null || adTagNode === void 0 ? void 0 : adTagNode.textContent) || "").trim());
5612
5655
  if (!adTagUrl) {
5613
5656
  return;
5614
5657
  }
@@ -5627,6 +5670,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5627
5670
  return parsed;
5628
5671
  }
5629
5672
  },
5673
+ {
5674
+ key: "resolveVmapAdTagUrl",
5675
+ value: function resolveVmapAdTagUrl(url) {
5676
+ if (!url) {
5677
+ return "";
5678
+ }
5679
+ return url.replace(/\[timestamp\]/gi, String(Date.now())).replace(/\$\{GDPR\}/gi, "0").trim();
5680
+ }
5681
+ },
5630
5682
  {
5631
5683
  key: "parseVmapTimeOffsetToMs",
5632
5684
  value: function parseVmapTimeOffsetToMs(timeOffset) {
@@ -5649,6 +5701,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5649
5701
  var millis = Number(ms.padEnd(3, "0").slice(0, 3));
5650
5702
  return (hours * 3600 + minutes * 60 + seconds) * 1e3 + millis;
5651
5703
  }
5704
+ var msOnly = timeOffset.match(/^(\d{1,2}):(\d{2})(?:\.(\d{1,3}))?$/);
5705
+ if (msOnly) {
5706
+ var _msOnly = _sliced_to_array(msOnly, 4), mm1 = _msOnly[1], ss1 = _msOnly[2], tmp1 = _msOnly[3], ms1 = tmp1 === void 0 ? "0" : tmp1;
5707
+ var minutes1 = Number(mm1);
5708
+ var seconds1 = Number(ss1);
5709
+ var millis1 = Number(ms1.padEnd(3, "0").slice(0, 3));
5710
+ return (minutes1 * 60 + seconds1) * 1e3 + millis1;
5711
+ }
5652
5712
  var percent = timeOffset.match(/^(\d+(?:\.\d+)?)%$/);
5653
5713
  if (percent) {
5654
5714
  var ratio = Number(percent[1]) / 100;
@@ -7164,23 +7224,49 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7164
7224
  key: "onTimeUpdate",
7165
7225
  value: function onTimeUpdate(currentTimeSec) {
7166
7226
  var _this = this;
7227
+ if (!this.isVmapEnabled() || this.vmapBreaks.length === 0) {
7228
+ return;
7229
+ }
7167
7230
  if (this.ima.isAdPlaying() || this.inAdBreak) return;
7168
7231
  var nowMs = currentTimeSec * 1e3;
7169
7232
  var breakToPlay = this.findBreakForTime(nowMs);
7170
7233
  if (breakToPlay) {
7171
- void this.handleMidAdJoin(breakToPlay, nowMs).catch(function(error) {
7234
+ void this.handleVmapAdBreak(breakToPlay, nowMs).catch(function(error) {
7172
7235
  if (_this.config.debugAdTiming) {
7173
- console.warn("[StormcloudVideoPlayer] Mid-roll VMAP join failed gracefully:", error);
7236
+ console.warn("[StormcloudVideoPlayer] VMAP ad break failed gracefully:", error);
7174
7237
  }
7175
7238
  });
7176
7239
  }
7177
7240
  }
7178
7241
  },
7179
7242
  {
7180
- key: "handleMidAdJoin",
7181
- value: function handleMidAdJoin(adBreak, nowMs) {
7243
+ key: "onVideoEnded",
7244
+ value: function onVideoEnded() {
7245
+ var _this = this;
7246
+ if (!this.isVmapEnabled() || this.vmapBreaks.length === 0) {
7247
+ return;
7248
+ }
7249
+ if (this.ima.isAdPlaying() || this.inAdBreak) {
7250
+ return;
7251
+ }
7252
+ var durationMs = Number.isFinite(this.video.duration) ? Math.floor(this.video.duration * 1e3) : 0;
7253
+ var postroll = this.vmapBreaks.find(function(b) {
7254
+ return b.startTimeMs === -1 && !_this.consumedVmapBreakIds.has(_this.getAdBreakKey(b));
7255
+ });
7256
+ if (postroll) {
7257
+ void this.handleVmapAdBreak(postroll, durationMs).catch(function(error) {
7258
+ if (_this.config.debugAdTiming) {
7259
+ console.warn("[StormcloudVideoPlayer] VMAP post-roll failed gracefully:", error);
7260
+ }
7261
+ });
7262
+ }
7263
+ }
7264
+ },
7265
+ {
7266
+ key: "handleVmapAdBreak",
7267
+ value: function handleVmapAdBreak(adBreak, nowMs) {
7182
7268
  return _async_to_generator(function() {
7183
- var _adBreak_durationMs, _this_config_driftToleranceMs, key, breakStartMs, durationMs, endMs, tol, inWindow, remainingMs, tags, first, rest, error;
7269
+ var _adBreak_durationMs, key, breakStartMs, durationMs, endMs, inWindow, tags, first, rest, error;
7184
7270
  return _ts_generator(this, function(_state) {
7185
7271
  switch(_state.label){
7186
7272
  case 0:
@@ -7198,25 +7284,28 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7198
7284
  }
7199
7285
  durationMs = (_adBreak_durationMs = adBreak.durationMs) !== null && _adBreak_durationMs !== void 0 ? _adBreak_durationMs : 0;
7200
7286
  endMs = breakStartMs + durationMs;
7201
- tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
7202
- inWindow = durationMs > 0 ? nowMs > breakStartMs && nowMs < endMs : nowMs + tol >= breakStartMs;
7287
+ inWindow = durationMs > 0 ? nowMs >= breakStartMs && nowMs < endMs : nowMs >= breakStartMs;
7203
7288
  if (!inWindow) return [
7204
7289
  3,
7205
7290
  4
7206
7291
  ];
7207
7292
  this.consumedVmapBreakIds.add(key);
7208
- remainingMs = durationMs > 0 ? Math.max(0, endMs - nowMs) : 0;
7209
- tags = this.selectVastTagsForBreak(adBreak) || (this.apiVastTagUrl ? [
7210
- this.apiVastTagUrl
7211
- ] : void 0);
7212
- if (!(tags && tags.length > 0)) return [
7213
- 3,
7214
- 4
7215
- ];
7293
+ tags = this.selectVastTagsForBreak(adBreak);
7294
+ if (!tags || tags.length === 0) {
7295
+ return [
7296
+ 2
7297
+ ];
7298
+ }
7216
7299
  first = tags[0];
7217
7300
  rest = tags.slice(1);
7218
7301
  this.adPodQueue = rest;
7219
7302
  this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
7303
+ this.showAds = true;
7304
+ this.inAdBreak = true;
7305
+ this.currentAdBreakStartWallClockMs = Date.now();
7306
+ if (!this.video.paused) {
7307
+ this.video.pause();
7308
+ }
7220
7309
  _state.label = 1;
7221
7310
  case 1:
7222
7311
  _state.trys.push([
@@ -7231,10 +7320,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7231
7320
  ];
7232
7321
  case 2:
7233
7322
  _state.sent();
7234
- this.inAdBreak = true;
7235
- this.expectedAdBreakDurationMs = remainingMs;
7236
- this.currentAdBreakStartWallClockMs = Date.now();
7237
- this.scheduleAdStopCountdown(remainingMs);
7238
7323
  return [
7239
7324
  3,
7240
7325
  4
@@ -7242,8 +7327,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7242
7327
  case 3:
7243
7328
  error = _state.sent();
7244
7329
  this.adPodQueue = [];
7330
+ this.inAdBreak = false;
7331
+ this.showAds = false;
7245
7332
  if (this.config.debugAdTiming) {
7246
- console.warn("[StormcloudVideoPlayer] Mid-roll VMAP ad request failed:", error);
7333
+ console.warn("[StormcloudVideoPlayer] VMAP ad request failed:", error);
7247
7334
  }
7248
7335
  return [
7249
7336
  3,
@@ -7914,16 +8001,18 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7914
8001
  {
7915
8002
  key: "selectVastTagsForBreak",
7916
8003
  value: function selectVastTagsForBreak(b) {
8004
+ var _this = this;
7917
8005
  if (!b || !b.vastTagUrl) return void 0;
7918
- if (b.vastTagUrl.includes(",")) {
7919
- return b.vastTagUrl.split(",").map(function(s) {
7920
- return s.trim();
8006
+ var resolvedUrl = this.resolveVmapAdTagUrl(b.vastTagUrl);
8007
+ if (resolvedUrl.includes(",")) {
8008
+ return resolvedUrl.split(",").map(function(s) {
8009
+ return _this.resolveVmapAdTagUrl(s.trim());
7921
8010
  }).filter(function(s) {
7922
8011
  return s.length > 0;
7923
8012
  });
7924
8013
  }
7925
8014
  return [
7926
- b.vastTagUrl
8015
+ resolvedUrl
7927
8016
  ];
7928
8017
  }
7929
8018
  },
@@ -7955,9 +8044,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7955
8044
  {
7956
8045
  key: "findBreakForTime",
7957
8046
  value: function findBreakForTime(nowMs) {
7958
- var _this_config_driftToleranceMs;
7959
8047
  var schedule = this.vmapBreaks;
7960
- var tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
7961
8048
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
7962
8049
  try {
7963
8050
  for(var _iterator = schedule[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
@@ -7969,8 +8056,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7969
8056
  if (breakStartMs == null) {
7970
8057
  continue;
7971
8058
  }
7972
- var end = breakStartMs + (b.durationMs || 0);
7973
- if (nowMs >= breakStartMs && (b.durationMs ? nowMs < end : nowMs <= breakStartMs + tol)) {
8059
+ if (b.durationMs) {
8060
+ var end = breakStartMs + b.durationMs;
8061
+ if (nowMs >= breakStartMs && nowMs < end) {
8062
+ return b;
8063
+ }
8064
+ continue;
8065
+ }
8066
+ if (nowMs >= breakStartMs) {
7974
8067
  return b;
7975
8068
  }
7976
8069
  }
@@ -8178,6 +8271,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8178
8271
  this.video.removeEventListener("timeupdate", this.timeUpdateHandler);
8179
8272
  delete this.timeUpdateHandler;
8180
8273
  }
8274
+ if (this.endedHandler) {
8275
+ this.video.removeEventListener("ended", this.endedHandler);
8276
+ delete this.endedHandler;
8277
+ }
8181
8278
  if (this.emptiedHandler) {
8182
8279
  this.video.removeEventListener("emptied", this.emptiedHandler);
8183
8280
  delete this.emptiedHandler;