stormcloud-video-player 0.2.1 → 0.2.4

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.cjs CHANGED
@@ -64,7 +64,7 @@ var import_react = __toESM(require("react"), 1);
64
64
  var import_hls = __toESM(require("hls.js"), 1);
65
65
 
66
66
  // src/sdk/ima.ts
67
- function createImaController(video) {
67
+ function createImaController(video, options) {
68
68
  let adPlaying = false;
69
69
  let originalMutedState = false;
70
70
  const listeners = /* @__PURE__ */ new Map();
@@ -257,8 +257,10 @@ function createImaController(video) {
257
257
  "[IMA] Max retries reached, emitting ad_error"
258
258
  );
259
259
  emit("ad_error");
260
- video.play().catch(() => {
261
- });
260
+ if (!options?.continueLiveStreamDuringAds) {
261
+ video.play().catch(() => {
262
+ });
263
+ }
262
264
  }
263
265
  }
264
266
  );
@@ -268,7 +270,14 @@ function createImaController(video) {
268
270
  console.log("[IMA] Content pause requested");
269
271
  originalMutedState = video.muted;
270
272
  video.muted = true;
271
- video.pause();
273
+ if (!options?.continueLiveStreamDuringAds) {
274
+ video.pause();
275
+ console.log("[IMA] Video paused (VOD mode)");
276
+ } else {
277
+ console.log(
278
+ "[IMA] Video continues playing but muted (Live mode)"
279
+ );
280
+ }
272
281
  adPlaying = true;
273
282
  if (adContainerEl)
274
283
  adContainerEl.style.pointerEvents = "auto";
@@ -283,8 +292,15 @@ function createImaController(video) {
283
292
  video.muted = originalMutedState;
284
293
  if (adContainerEl)
285
294
  adContainerEl.style.pointerEvents = "none";
286
- video.play().catch(() => {
287
- });
295
+ if (!options?.continueLiveStreamDuringAds) {
296
+ video.play().catch(() => {
297
+ });
298
+ console.log("[IMA] Video resumed (VOD mode)");
299
+ } else {
300
+ console.log(
301
+ "[IMA] Video unmuted (Live mode - was never paused)"
302
+ );
303
+ }
288
304
  emit("content_resume");
289
305
  }
290
306
  );
@@ -293,8 +309,17 @@ function createImaController(video) {
293
309
  adPlaying = false;
294
310
  video.muted = originalMutedState;
295
311
  if (adContainerEl) adContainerEl.style.pointerEvents = "none";
296
- video.play().catch(() => {
297
- });
312
+ if (!options?.continueLiveStreamDuringAds) {
313
+ video.play().catch(() => {
314
+ });
315
+ console.log(
316
+ "[IMA] Video resumed after all ads completed (VOD mode)"
317
+ );
318
+ } else {
319
+ console.log(
320
+ "[IMA] Video unmuted after all ads completed (Live mode)"
321
+ );
322
+ }
298
323
  emit("all_ads_completed");
299
324
  });
300
325
  console.log("[IMA] Ads manager event listeners attached");
@@ -308,8 +333,10 @@ function createImaController(video) {
308
333
  adPlaying = false;
309
334
  video.muted = originalMutedState;
310
335
  if (adContainerEl) adContainerEl.style.pointerEvents = "none";
311
- video.play().catch(() => {
312
- });
336
+ if (!options?.continueLiveStreamDuringAds) {
337
+ video.play().catch(() => {
338
+ });
339
+ }
313
340
  if (adsLoadedReject) {
314
341
  adsLoadedReject(new Error("Failed to setup ads manager"));
315
342
  adsLoadedReject = void 0;
@@ -363,8 +390,14 @@ function createImaController(video) {
363
390
  const height = video.clientHeight || 360;
364
391
  console.log(`[IMA] Initializing ads manager (${width}x${height})`);
365
392
  adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);
366
- console.log("[IMA] Pausing video for ad playback");
367
- video.pause();
393
+ if (!options?.continueLiveStreamDuringAds) {
394
+ console.log("[IMA] Pausing video for ad playback (VOD mode)");
395
+ video.pause();
396
+ } else {
397
+ console.log(
398
+ "[IMA] Keeping video playing but muted for ad playback (Live mode)"
399
+ );
400
+ }
368
401
  adPlaying = true;
369
402
  console.log("[IMA] Starting ad playback");
370
403
  adsManager.start();
@@ -372,8 +405,10 @@ function createImaController(video) {
372
405
  } catch (error) {
373
406
  console.error("[IMA] Error starting ad playback:", error);
374
407
  adPlaying = false;
375
- video.play().catch(() => {
376
- });
408
+ if (!options?.continueLiveStreamDuringAds) {
409
+ video.play().catch(() => {
410
+ });
411
+ }
377
412
  return Promise.reject(error);
378
413
  }
379
414
  },
@@ -384,8 +419,13 @@ function createImaController(video) {
384
419
  adsManager?.stop?.();
385
420
  } catch {
386
421
  }
387
- video.play().catch(() => {
388
- });
422
+ if (!options?.continueLiveStreamDuringAds) {
423
+ video.play().catch(() => {
424
+ });
425
+ console.log("[IMA] Video resumed after stop (VOD mode)");
426
+ } else {
427
+ console.log("[IMA] Video unmuted after stop (Live mode)");
428
+ }
389
429
  },
390
430
  destroy() {
391
431
  try {
@@ -682,9 +722,12 @@ var StormcloudVideoPlayer = class {
682
722
  this.currentAdIndex = 0;
683
723
  this.totalAdsInBreak = 0;
684
724
  this.showAds = false;
725
+ this.isLiveStream = false;
685
726
  this.config = config;
686
727
  this.video = config.videoElement;
687
- this.ima = createImaController(this.video);
728
+ this.ima = createImaController(this.video, {
729
+ continueLiveStreamDuringAds: false
730
+ });
688
731
  }
689
732
  async load() {
690
733
  if (!this.attached) {
@@ -703,6 +746,22 @@ var StormcloudVideoPlayer = class {
703
746
  this.initializeTracking();
704
747
  if (this.shouldUseNativeHls()) {
705
748
  this.video.src = this.config.src;
749
+ this.isLiveStream = this.config.lowLatencyMode ?? false;
750
+ if (this.config.debugAdTiming) {
751
+ console.log(
752
+ "[StormcloudVideoPlayer] allowNativeHls: true - VOD mode detected:",
753
+ {
754
+ isLive: this.isLiveStream,
755
+ allowNativeHls: this.config.allowNativeHls,
756
+ adBehavior: "vod (main video pauses during ads)"
757
+ }
758
+ );
759
+ }
760
+ this.ima.destroy();
761
+ this.ima = createImaController(this.video, {
762
+ continueLiveStreamDuringAds: false
763
+ });
764
+ this.ima.initialize();
706
765
  if (this.config.autoplay) {
707
766
  await this.video.play().catch(() => {
708
767
  });
@@ -720,7 +779,23 @@ var StormcloudVideoPlayer = class {
720
779
  this.hls.on(import_hls.default.Events.MEDIA_ATTACHED, () => {
721
780
  this.hls?.loadSource(this.config.src);
722
781
  });
723
- this.hls.on(import_hls.default.Events.MANIFEST_PARSED, async () => {
782
+ this.hls.on(import_hls.default.Events.MANIFEST_PARSED, async (_, data) => {
783
+ this.isLiveStream = this.hls?.levels?.some(
784
+ (level) => level?.details?.live === true || level?.details?.type === "LIVE"
785
+ ) ?? false;
786
+ if (this.config.debugAdTiming) {
787
+ const adBehavior = this.shouldContinueLiveStreamDuringAds() ? "live (main video continues muted during ads)" : "vod (main video pauses during ads)";
788
+ console.log("[StormcloudVideoPlayer] Stream type detected:", {
789
+ isLive: this.isLiveStream,
790
+ allowNativeHls: this.config.allowNativeHls,
791
+ adBehavior
792
+ });
793
+ }
794
+ this.ima.destroy();
795
+ this.ima = createImaController(this.video, {
796
+ continueLiveStreamDuringAds: this.shouldContinueLiveStreamDuringAds()
797
+ });
798
+ this.ima.initialize();
724
799
  if (this.config.autoplay) {
725
800
  await this.video.play().catch(() => {
726
801
  });
@@ -1346,6 +1421,15 @@ var StormcloudVideoPlayer = class {
1346
1421
  }
1347
1422
  return !!(this.config.allowNativeHls && !(this.config.showCustomControls ?? false));
1348
1423
  }
1424
+ shouldContinueLiveStreamDuringAds() {
1425
+ if (this.config.allowNativeHls) {
1426
+ return false;
1427
+ }
1428
+ if (!this.isLiveStream) {
1429
+ return false;
1430
+ }
1431
+ return true;
1432
+ }
1349
1433
  async loadDefaultVastFromAdstorm(adstormApiUrl, params) {
1350
1434
  const usp = new URLSearchParams(params || {});
1351
1435
  const url = `${adstormApiUrl}?${usp.toString()}`;
@@ -1660,6 +1744,9 @@ var StormcloudVideoPlayer = class {
1660
1744
  isFullscreen() {
1661
1745
  return !!document.fullscreenElement;
1662
1746
  }
1747
+ isLive() {
1748
+ return this.isLiveStream;
1749
+ }
1663
1750
  get videoElement() {
1664
1751
  return this.video;
1665
1752
  }