stormcloud-video-player 0.2.3 → 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.
@@ -36,7 +36,7 @@ module.exports = __toCommonJS(StormcloudVideoPlayer_exports);
36
36
  var import_hls = __toESM(require("hls.js"), 1);
37
37
 
38
38
  // src/sdk/ima.ts
39
- function createImaController(video) {
39
+ function createImaController(video, options) {
40
40
  let adPlaying = false;
41
41
  let originalMutedState = false;
42
42
  const listeners = /* @__PURE__ */ new Map();
@@ -229,8 +229,10 @@ function createImaController(video) {
229
229
  "[IMA] Max retries reached, emitting ad_error"
230
230
  );
231
231
  emit("ad_error");
232
- video.play().catch(() => {
233
- });
232
+ if (!options?.continueLiveStreamDuringAds) {
233
+ video.play().catch(() => {
234
+ });
235
+ }
234
236
  }
235
237
  }
236
238
  );
@@ -240,7 +242,14 @@ function createImaController(video) {
240
242
  console.log("[IMA] Content pause requested");
241
243
  originalMutedState = video.muted;
242
244
  video.muted = true;
243
- video.pause();
245
+ if (!options?.continueLiveStreamDuringAds) {
246
+ video.pause();
247
+ console.log("[IMA] Video paused (VOD mode)");
248
+ } else {
249
+ console.log(
250
+ "[IMA] Video continues playing but muted (Live mode)"
251
+ );
252
+ }
244
253
  adPlaying = true;
245
254
  if (adContainerEl)
246
255
  adContainerEl.style.pointerEvents = "auto";
@@ -255,8 +264,15 @@ function createImaController(video) {
255
264
  video.muted = originalMutedState;
256
265
  if (adContainerEl)
257
266
  adContainerEl.style.pointerEvents = "none";
258
- video.play().catch(() => {
259
- });
267
+ if (!options?.continueLiveStreamDuringAds) {
268
+ video.play().catch(() => {
269
+ });
270
+ console.log("[IMA] Video resumed (VOD mode)");
271
+ } else {
272
+ console.log(
273
+ "[IMA] Video unmuted (Live mode - was never paused)"
274
+ );
275
+ }
260
276
  emit("content_resume");
261
277
  }
262
278
  );
@@ -265,8 +281,17 @@ function createImaController(video) {
265
281
  adPlaying = false;
266
282
  video.muted = originalMutedState;
267
283
  if (adContainerEl) adContainerEl.style.pointerEvents = "none";
268
- video.play().catch(() => {
269
- });
284
+ if (!options?.continueLiveStreamDuringAds) {
285
+ video.play().catch(() => {
286
+ });
287
+ console.log(
288
+ "[IMA] Video resumed after all ads completed (VOD mode)"
289
+ );
290
+ } else {
291
+ console.log(
292
+ "[IMA] Video unmuted after all ads completed (Live mode)"
293
+ );
294
+ }
270
295
  emit("all_ads_completed");
271
296
  });
272
297
  console.log("[IMA] Ads manager event listeners attached");
@@ -280,8 +305,10 @@ function createImaController(video) {
280
305
  adPlaying = false;
281
306
  video.muted = originalMutedState;
282
307
  if (adContainerEl) adContainerEl.style.pointerEvents = "none";
283
- video.play().catch(() => {
284
- });
308
+ if (!options?.continueLiveStreamDuringAds) {
309
+ video.play().catch(() => {
310
+ });
311
+ }
285
312
  if (adsLoadedReject) {
286
313
  adsLoadedReject(new Error("Failed to setup ads manager"));
287
314
  adsLoadedReject = void 0;
@@ -335,8 +362,14 @@ function createImaController(video) {
335
362
  const height = video.clientHeight || 360;
336
363
  console.log(`[IMA] Initializing ads manager (${width}x${height})`);
337
364
  adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);
338
- console.log("[IMA] Pausing video for ad playback");
339
- video.pause();
365
+ if (!options?.continueLiveStreamDuringAds) {
366
+ console.log("[IMA] Pausing video for ad playback (VOD mode)");
367
+ video.pause();
368
+ } else {
369
+ console.log(
370
+ "[IMA] Keeping video playing but muted for ad playback (Live mode)"
371
+ );
372
+ }
340
373
  adPlaying = true;
341
374
  console.log("[IMA] Starting ad playback");
342
375
  adsManager.start();
@@ -344,8 +377,10 @@ function createImaController(video) {
344
377
  } catch (error) {
345
378
  console.error("[IMA] Error starting ad playback:", error);
346
379
  adPlaying = false;
347
- video.play().catch(() => {
348
- });
380
+ if (!options?.continueLiveStreamDuringAds) {
381
+ video.play().catch(() => {
382
+ });
383
+ }
349
384
  return Promise.reject(error);
350
385
  }
351
386
  },
@@ -356,8 +391,13 @@ function createImaController(video) {
356
391
  adsManager?.stop?.();
357
392
  } catch {
358
393
  }
359
- video.play().catch(() => {
360
- });
394
+ if (!options?.continueLiveStreamDuringAds) {
395
+ video.play().catch(() => {
396
+ });
397
+ console.log("[IMA] Video resumed after stop (VOD mode)");
398
+ } else {
399
+ console.log("[IMA] Video unmuted after stop (Live mode)");
400
+ }
361
401
  },
362
402
  destroy() {
363
403
  try {
@@ -654,9 +694,12 @@ var StormcloudVideoPlayer = class {
654
694
  this.currentAdIndex = 0;
655
695
  this.totalAdsInBreak = 0;
656
696
  this.showAds = false;
697
+ this.isLiveStream = false;
657
698
  this.config = config;
658
699
  this.video = config.videoElement;
659
- this.ima = createImaController(this.video);
700
+ this.ima = createImaController(this.video, {
701
+ continueLiveStreamDuringAds: false
702
+ });
660
703
  }
661
704
  async load() {
662
705
  if (!this.attached) {
@@ -675,6 +718,22 @@ var StormcloudVideoPlayer = class {
675
718
  this.initializeTracking();
676
719
  if (this.shouldUseNativeHls()) {
677
720
  this.video.src = this.config.src;
721
+ this.isLiveStream = this.config.lowLatencyMode ?? false;
722
+ if (this.config.debugAdTiming) {
723
+ console.log(
724
+ "[StormcloudVideoPlayer] allowNativeHls: true - VOD mode detected:",
725
+ {
726
+ isLive: this.isLiveStream,
727
+ allowNativeHls: this.config.allowNativeHls,
728
+ adBehavior: "vod (main video pauses during ads)"
729
+ }
730
+ );
731
+ }
732
+ this.ima.destroy();
733
+ this.ima = createImaController(this.video, {
734
+ continueLiveStreamDuringAds: false
735
+ });
736
+ this.ima.initialize();
678
737
  if (this.config.autoplay) {
679
738
  await this.video.play().catch(() => {
680
739
  });
@@ -692,7 +751,23 @@ var StormcloudVideoPlayer = class {
692
751
  this.hls.on(import_hls.default.Events.MEDIA_ATTACHED, () => {
693
752
  this.hls?.loadSource(this.config.src);
694
753
  });
695
- this.hls.on(import_hls.default.Events.MANIFEST_PARSED, async () => {
754
+ this.hls.on(import_hls.default.Events.MANIFEST_PARSED, async (_, data) => {
755
+ this.isLiveStream = this.hls?.levels?.some(
756
+ (level) => level?.details?.live === true || level?.details?.type === "LIVE"
757
+ ) ?? false;
758
+ if (this.config.debugAdTiming) {
759
+ const adBehavior = this.shouldContinueLiveStreamDuringAds() ? "live (main video continues muted during ads)" : "vod (main video pauses during ads)";
760
+ console.log("[StormcloudVideoPlayer] Stream type detected:", {
761
+ isLive: this.isLiveStream,
762
+ allowNativeHls: this.config.allowNativeHls,
763
+ adBehavior
764
+ });
765
+ }
766
+ this.ima.destroy();
767
+ this.ima = createImaController(this.video, {
768
+ continueLiveStreamDuringAds: this.shouldContinueLiveStreamDuringAds()
769
+ });
770
+ this.ima.initialize();
696
771
  if (this.config.autoplay) {
697
772
  await this.video.play().catch(() => {
698
773
  });
@@ -1318,6 +1393,15 @@ var StormcloudVideoPlayer = class {
1318
1393
  }
1319
1394
  return !!(this.config.allowNativeHls && !(this.config.showCustomControls ?? false));
1320
1395
  }
1396
+ shouldContinueLiveStreamDuringAds() {
1397
+ if (this.config.allowNativeHls) {
1398
+ return false;
1399
+ }
1400
+ if (!this.isLiveStream) {
1401
+ return false;
1402
+ }
1403
+ return true;
1404
+ }
1321
1405
  async loadDefaultVastFromAdstorm(adstormApiUrl, params) {
1322
1406
  const usp = new URLSearchParams(params || {});
1323
1407
  const url = `${adstormApiUrl}?${usp.toString()}`;
@@ -1632,6 +1716,9 @@ var StormcloudVideoPlayer = class {
1632
1716
  isFullscreen() {
1633
1717
  return !!document.fullscreenElement;
1634
1718
  }
1719
+ isLive() {
1720
+ return this.isLiveStream;
1721
+ }
1635
1722
  get videoElement() {
1636
1723
  return this.video;
1637
1724
  }