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.
package/lib/index.d.cts CHANGED
@@ -91,6 +91,7 @@ declare class StormcloudVideoPlayer {
91
91
  private currentAdIndex;
92
92
  private totalAdsInBreak;
93
93
  private showAds;
94
+ private isLiveStream;
94
95
  constructor(config: StormcloudVideoPlayerConfig);
95
96
  load(): Promise<void>;
96
97
  private attach;
@@ -114,6 +115,7 @@ declare class StormcloudVideoPlayer {
114
115
  isShowingAds(): boolean;
115
116
  getStreamType(): "hls" | "other";
116
117
  shouldShowNativeControls(): boolean;
118
+ private shouldContinueLiveStreamDuringAds;
117
119
  loadDefaultVastFromAdstorm(adstormApiUrl: string, params?: Record<string, string>): Promise<void>;
118
120
  private handleAdStart;
119
121
  private findCurrentOrNextBreak;
@@ -136,6 +138,7 @@ declare class StormcloudVideoPlayer {
136
138
  toggleFullscreen(): Promise<void>;
137
139
  isMuted(): boolean;
138
140
  isFullscreen(): boolean;
141
+ isLive(): boolean;
139
142
  get videoElement(): HTMLVideoElement;
140
143
  resize(): void;
141
144
  destroy(): void;
package/lib/index.d.ts CHANGED
@@ -91,6 +91,7 @@ declare class StormcloudVideoPlayer {
91
91
  private currentAdIndex;
92
92
  private totalAdsInBreak;
93
93
  private showAds;
94
+ private isLiveStream;
94
95
  constructor(config: StormcloudVideoPlayerConfig);
95
96
  load(): Promise<void>;
96
97
  private attach;
@@ -114,6 +115,7 @@ declare class StormcloudVideoPlayer {
114
115
  isShowingAds(): boolean;
115
116
  getStreamType(): "hls" | "other";
116
117
  shouldShowNativeControls(): boolean;
118
+ private shouldContinueLiveStreamDuringAds;
117
119
  loadDefaultVastFromAdstorm(adstormApiUrl: string, params?: Record<string, string>): Promise<void>;
118
120
  private handleAdStart;
119
121
  private findCurrentOrNextBreak;
@@ -136,6 +138,7 @@ declare class StormcloudVideoPlayer {
136
138
  toggleFullscreen(): Promise<void>;
137
139
  isMuted(): boolean;
138
140
  isFullscreen(): boolean;
141
+ isLive(): boolean;
139
142
  get videoElement(): HTMLVideoElement;
140
143
  resize(): void;
141
144
  destroy(): void;
package/lib/index.js CHANGED
@@ -5,7 +5,7 @@ import React, { useEffect, useRef, useMemo } from "react";
5
5
  import Hls from "hls.js";
6
6
 
7
7
  // src/sdk/ima.ts
8
- function createImaController(video) {
8
+ function createImaController(video, options) {
9
9
  let adPlaying = false;
10
10
  let originalMutedState = false;
11
11
  const listeners = /* @__PURE__ */ new Map();
@@ -198,8 +198,10 @@ function createImaController(video) {
198
198
  "[IMA] Max retries reached, emitting ad_error"
199
199
  );
200
200
  emit("ad_error");
201
- video.play().catch(() => {
202
- });
201
+ if (!options?.continueLiveStreamDuringAds) {
202
+ video.play().catch(() => {
203
+ });
204
+ }
203
205
  }
204
206
  }
205
207
  );
@@ -209,7 +211,14 @@ function createImaController(video) {
209
211
  console.log("[IMA] Content pause requested");
210
212
  originalMutedState = video.muted;
211
213
  video.muted = true;
212
- video.pause();
214
+ if (!options?.continueLiveStreamDuringAds) {
215
+ video.pause();
216
+ console.log("[IMA] Video paused (VOD mode)");
217
+ } else {
218
+ console.log(
219
+ "[IMA] Video continues playing but muted (Live mode)"
220
+ );
221
+ }
213
222
  adPlaying = true;
214
223
  if (adContainerEl)
215
224
  adContainerEl.style.pointerEvents = "auto";
@@ -224,8 +233,15 @@ function createImaController(video) {
224
233
  video.muted = originalMutedState;
225
234
  if (adContainerEl)
226
235
  adContainerEl.style.pointerEvents = "none";
227
- video.play().catch(() => {
228
- });
236
+ if (!options?.continueLiveStreamDuringAds) {
237
+ video.play().catch(() => {
238
+ });
239
+ console.log("[IMA] Video resumed (VOD mode)");
240
+ } else {
241
+ console.log(
242
+ "[IMA] Video unmuted (Live mode - was never paused)"
243
+ );
244
+ }
229
245
  emit("content_resume");
230
246
  }
231
247
  );
@@ -234,8 +250,17 @@ function createImaController(video) {
234
250
  adPlaying = false;
235
251
  video.muted = originalMutedState;
236
252
  if (adContainerEl) adContainerEl.style.pointerEvents = "none";
237
- video.play().catch(() => {
238
- });
253
+ if (!options?.continueLiveStreamDuringAds) {
254
+ video.play().catch(() => {
255
+ });
256
+ console.log(
257
+ "[IMA] Video resumed after all ads completed (VOD mode)"
258
+ );
259
+ } else {
260
+ console.log(
261
+ "[IMA] Video unmuted after all ads completed (Live mode)"
262
+ );
263
+ }
239
264
  emit("all_ads_completed");
240
265
  });
241
266
  console.log("[IMA] Ads manager event listeners attached");
@@ -249,8 +274,10 @@ function createImaController(video) {
249
274
  adPlaying = false;
250
275
  video.muted = originalMutedState;
251
276
  if (adContainerEl) adContainerEl.style.pointerEvents = "none";
252
- video.play().catch(() => {
253
- });
277
+ if (!options?.continueLiveStreamDuringAds) {
278
+ video.play().catch(() => {
279
+ });
280
+ }
254
281
  if (adsLoadedReject) {
255
282
  adsLoadedReject(new Error("Failed to setup ads manager"));
256
283
  adsLoadedReject = void 0;
@@ -304,8 +331,14 @@ function createImaController(video) {
304
331
  const height = video.clientHeight || 360;
305
332
  console.log(`[IMA] Initializing ads manager (${width}x${height})`);
306
333
  adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);
307
- console.log("[IMA] Pausing video for ad playback");
308
- video.pause();
334
+ if (!options?.continueLiveStreamDuringAds) {
335
+ console.log("[IMA] Pausing video for ad playback (VOD mode)");
336
+ video.pause();
337
+ } else {
338
+ console.log(
339
+ "[IMA] Keeping video playing but muted for ad playback (Live mode)"
340
+ );
341
+ }
309
342
  adPlaying = true;
310
343
  console.log("[IMA] Starting ad playback");
311
344
  adsManager.start();
@@ -313,8 +346,10 @@ function createImaController(video) {
313
346
  } catch (error) {
314
347
  console.error("[IMA] Error starting ad playback:", error);
315
348
  adPlaying = false;
316
- video.play().catch(() => {
317
- });
349
+ if (!options?.continueLiveStreamDuringAds) {
350
+ video.play().catch(() => {
351
+ });
352
+ }
318
353
  return Promise.reject(error);
319
354
  }
320
355
  },
@@ -325,8 +360,13 @@ function createImaController(video) {
325
360
  adsManager?.stop?.();
326
361
  } catch {
327
362
  }
328
- video.play().catch(() => {
329
- });
363
+ if (!options?.continueLiveStreamDuringAds) {
364
+ video.play().catch(() => {
365
+ });
366
+ console.log("[IMA] Video resumed after stop (VOD mode)");
367
+ } else {
368
+ console.log("[IMA] Video unmuted after stop (Live mode)");
369
+ }
330
370
  },
331
371
  destroy() {
332
372
  try {
@@ -623,9 +663,12 @@ var StormcloudVideoPlayer = class {
623
663
  this.currentAdIndex = 0;
624
664
  this.totalAdsInBreak = 0;
625
665
  this.showAds = false;
666
+ this.isLiveStream = false;
626
667
  this.config = config;
627
668
  this.video = config.videoElement;
628
- this.ima = createImaController(this.video);
669
+ this.ima = createImaController(this.video, {
670
+ continueLiveStreamDuringAds: false
671
+ });
629
672
  }
630
673
  async load() {
631
674
  if (!this.attached) {
@@ -644,6 +687,22 @@ var StormcloudVideoPlayer = class {
644
687
  this.initializeTracking();
645
688
  if (this.shouldUseNativeHls()) {
646
689
  this.video.src = this.config.src;
690
+ this.isLiveStream = this.config.lowLatencyMode ?? false;
691
+ if (this.config.debugAdTiming) {
692
+ console.log(
693
+ "[StormcloudVideoPlayer] allowNativeHls: true - VOD mode detected:",
694
+ {
695
+ isLive: this.isLiveStream,
696
+ allowNativeHls: this.config.allowNativeHls,
697
+ adBehavior: "vod (main video pauses during ads)"
698
+ }
699
+ );
700
+ }
701
+ this.ima.destroy();
702
+ this.ima = createImaController(this.video, {
703
+ continueLiveStreamDuringAds: false
704
+ });
705
+ this.ima.initialize();
647
706
  if (this.config.autoplay) {
648
707
  await this.video.play().catch(() => {
649
708
  });
@@ -661,7 +720,23 @@ var StormcloudVideoPlayer = class {
661
720
  this.hls.on(Hls.Events.MEDIA_ATTACHED, () => {
662
721
  this.hls?.loadSource(this.config.src);
663
722
  });
664
- this.hls.on(Hls.Events.MANIFEST_PARSED, async () => {
723
+ this.hls.on(Hls.Events.MANIFEST_PARSED, async (_, data) => {
724
+ this.isLiveStream = this.hls?.levels?.some(
725
+ (level) => level?.details?.live === true || level?.details?.type === "LIVE"
726
+ ) ?? false;
727
+ if (this.config.debugAdTiming) {
728
+ const adBehavior = this.shouldContinueLiveStreamDuringAds() ? "live (main video continues muted during ads)" : "vod (main video pauses during ads)";
729
+ console.log("[StormcloudVideoPlayer] Stream type detected:", {
730
+ isLive: this.isLiveStream,
731
+ allowNativeHls: this.config.allowNativeHls,
732
+ adBehavior
733
+ });
734
+ }
735
+ this.ima.destroy();
736
+ this.ima = createImaController(this.video, {
737
+ continueLiveStreamDuringAds: this.shouldContinueLiveStreamDuringAds()
738
+ });
739
+ this.ima.initialize();
665
740
  if (this.config.autoplay) {
666
741
  await this.video.play().catch(() => {
667
742
  });
@@ -1287,6 +1362,15 @@ var StormcloudVideoPlayer = class {
1287
1362
  }
1288
1363
  return !!(this.config.allowNativeHls && !(this.config.showCustomControls ?? false));
1289
1364
  }
1365
+ shouldContinueLiveStreamDuringAds() {
1366
+ if (this.config.allowNativeHls) {
1367
+ return false;
1368
+ }
1369
+ if (!this.isLiveStream) {
1370
+ return false;
1371
+ }
1372
+ return true;
1373
+ }
1290
1374
  async loadDefaultVastFromAdstorm(adstormApiUrl, params) {
1291
1375
  const usp = new URLSearchParams(params || {});
1292
1376
  const url = `${adstormApiUrl}?${usp.toString()}`;
@@ -1601,6 +1685,9 @@ var StormcloudVideoPlayer = class {
1601
1685
  isFullscreen() {
1602
1686
  return !!document.fullscreenElement;
1603
1687
  }
1688
+ isLive() {
1689
+ return this.isLiveStream;
1690
+ }
1604
1691
  get videoElement() {
1605
1692
  return this.video;
1606
1693
  }