stormcloud-video-player 0.8.46 → 0.8.48
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/dist/stormcloud-vp.min.js +1 -1
- package/lib/index.cjs +209 -88
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +2 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.js +206 -89
- package/lib/index.js.map +1 -1
- package/lib/player/AdBreakOrchestrator.cjs +17 -3
- package/lib/player/AdBreakOrchestrator.cjs.map +1 -1
- package/lib/player/AdBreakOrchestrator.d.cts +1 -0
- package/lib/player/HlsEngine.cjs +22 -3
- package/lib/player/HlsEngine.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +205 -88
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.cjs +205 -88
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +205 -88
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +158 -82
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +205 -88
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/utils/browserCompat.cjs +9 -0
- package/lib/utils/browserCompat.cjs.map +1 -1
- package/lib/utils/browserCompat.d.cts +2 -1
- package/package.json +1 -1
package/lib/index.d.cts
CHANGED
|
@@ -4001,6 +4001,7 @@ interface BrowserInfo {
|
|
|
4001
4001
|
chromeVersion?: number | undefined;
|
|
4002
4002
|
}
|
|
4003
4003
|
declare function detectBrowser(): BrowserInfo;
|
|
4004
|
+
declare function requiresMediaPipelineResetAfterAds(): boolean;
|
|
4004
4005
|
declare function getBrowserConfigOverrides(): {
|
|
4005
4006
|
allowNativeHls?: boolean;
|
|
4006
4007
|
pauseContentDuringAds?: boolean;
|
|
@@ -4043,4 +4044,4 @@ interface PalNonceManager {
|
|
|
4043
4044
|
}
|
|
4044
4045
|
declare function createPalNonceManager(): PalNonceManager;
|
|
4045
4046
|
|
|
4046
|
-
export { type AdBreak, type AdController, type AdControllerOptions, type AdDetectInfo, type AdImpressionInfo, type AdLoadedInfo, type AdSchedule, type BaseStormcloudPlayerProps, type BrowserInfo, type ClientInfo, DEFAULT_MQTT_CONFIG, type HeartbeatData, IS_BROWSER, IS_GLOBAL, IS_IOS, IS_SAFARI, type ImaController, type ImaControllerOptions, type LateJoinPolicy, type MQTTConfig, type MQTTStatus, MQTT_CA_CERT_FILE, type OnProgressProps, type PalNonceManager, type PalNonceOptions, type PlayerAnalyticsContext, SUPPORTS_DASH, SUPPORTS_HLS, StormcloudPlayer, StormcloudVideoPlayer, StormcloudVideoPlayerComponent, type StormcloudVideoPlayerConfig, type StormcloudVideoPlayerProps, type TrackingData, applyMQTTConfig, buildAnalyticsContext, buildMQTTBrokerUrl, buildPlayerTopic, canPlay, configureMQTT, createHlsAdPlayer, createPalNonceManager, createStormcloudPlayer, StormcloudVideoPlayerComponent as default, detectBrowser, disconnectMQTT, ensureMQTTClient, getBrowserConfigOverrides, getBrowserID, getClientInfo, getMQTTStatus, initMQTTClient, initializePolyfills, isMQTTConfigured, isMQTTConnected, isMQTTEnabled, isMediaStream, lazy, logBrowserInfo, merge, mqttConfig, omit, parseQuery, players, publishMQTT, randomString, sendAdDetectTracking, sendAdImpressionTracking, sendAdLoadedTracking, sendHeartbeat, sendInitialTracking, supportsFeature, supportsModernJS, supportsWebKitPresentationMode };
|
|
4047
|
+
export { type AdBreak, type AdController, type AdControllerOptions, type AdDetectInfo, type AdImpressionInfo, type AdLoadedInfo, type AdSchedule, type BaseStormcloudPlayerProps, type BrowserInfo, type ClientInfo, DEFAULT_MQTT_CONFIG, type HeartbeatData, IS_BROWSER, IS_GLOBAL, IS_IOS, IS_SAFARI, type ImaController, type ImaControllerOptions, type LateJoinPolicy, type MQTTConfig, type MQTTStatus, MQTT_CA_CERT_FILE, type OnProgressProps, type PalNonceManager, type PalNonceOptions, type PlayerAnalyticsContext, SUPPORTS_DASH, SUPPORTS_HLS, StormcloudPlayer, StormcloudVideoPlayer, StormcloudVideoPlayerComponent, type StormcloudVideoPlayerConfig, type StormcloudVideoPlayerProps, type TrackingData, applyMQTTConfig, buildAnalyticsContext, buildMQTTBrokerUrl, buildPlayerTopic, canPlay, configureMQTT, createHlsAdPlayer, createPalNonceManager, createStormcloudPlayer, StormcloudVideoPlayerComponent as default, detectBrowser, disconnectMQTT, ensureMQTTClient, getBrowserConfigOverrides, getBrowserID, getClientInfo, getMQTTStatus, initMQTTClient, initializePolyfills, isMQTTConfigured, isMQTTConnected, isMQTTEnabled, isMediaStream, lazy, logBrowserInfo, merge, mqttConfig, omit, parseQuery, players, publishMQTT, randomString, requiresMediaPipelineResetAfterAds, sendAdDetectTracking, sendAdImpressionTracking, sendAdLoadedTracking, sendHeartbeat, sendInitialTracking, supportsFeature, supportsModernJS, supportsWebKitPresentationMode };
|
package/lib/index.d.ts
CHANGED
|
@@ -4001,6 +4001,7 @@ interface BrowserInfo {
|
|
|
4001
4001
|
chromeVersion?: number | undefined;
|
|
4002
4002
|
}
|
|
4003
4003
|
declare function detectBrowser(): BrowserInfo;
|
|
4004
|
+
declare function requiresMediaPipelineResetAfterAds(): boolean;
|
|
4004
4005
|
declare function getBrowserConfigOverrides(): {
|
|
4005
4006
|
allowNativeHls?: boolean;
|
|
4006
4007
|
pauseContentDuringAds?: boolean;
|
|
@@ -4043,4 +4044,4 @@ interface PalNonceManager {
|
|
|
4043
4044
|
}
|
|
4044
4045
|
declare function createPalNonceManager(): PalNonceManager;
|
|
4045
4046
|
|
|
4046
|
-
export { type AdBreak, type AdController, type AdControllerOptions, type AdDetectInfo, type AdImpressionInfo, type AdLoadedInfo, type AdSchedule, type BaseStormcloudPlayerProps, type BrowserInfo, type ClientInfo, DEFAULT_MQTT_CONFIG, type HeartbeatData, IS_BROWSER, IS_GLOBAL, IS_IOS, IS_SAFARI, type ImaController, type ImaControllerOptions, type LateJoinPolicy, type MQTTConfig, type MQTTStatus, MQTT_CA_CERT_FILE, type OnProgressProps, type PalNonceManager, type PalNonceOptions, type PlayerAnalyticsContext, SUPPORTS_DASH, SUPPORTS_HLS, StormcloudPlayer, StormcloudVideoPlayer, StormcloudVideoPlayerComponent, type StormcloudVideoPlayerConfig, type StormcloudVideoPlayerProps, type TrackingData, applyMQTTConfig, buildAnalyticsContext, buildMQTTBrokerUrl, buildPlayerTopic, canPlay, configureMQTT, createHlsAdPlayer, createPalNonceManager, createStormcloudPlayer, StormcloudVideoPlayerComponent as default, detectBrowser, disconnectMQTT, ensureMQTTClient, getBrowserConfigOverrides, getBrowserID, getClientInfo, getMQTTStatus, initMQTTClient, initializePolyfills, isMQTTConfigured, isMQTTConnected, isMQTTEnabled, isMediaStream, lazy, logBrowserInfo, merge, mqttConfig, omit, parseQuery, players, publishMQTT, randomString, sendAdDetectTracking, sendAdImpressionTracking, sendAdLoadedTracking, sendHeartbeat, sendInitialTracking, supportsFeature, supportsModernJS, supportsWebKitPresentationMode };
|
|
4047
|
+
export { type AdBreak, type AdController, type AdControllerOptions, type AdDetectInfo, type AdImpressionInfo, type AdLoadedInfo, type AdSchedule, type BaseStormcloudPlayerProps, type BrowserInfo, type ClientInfo, DEFAULT_MQTT_CONFIG, type HeartbeatData, IS_BROWSER, IS_GLOBAL, IS_IOS, IS_SAFARI, type ImaController, type ImaControllerOptions, type LateJoinPolicy, type MQTTConfig, type MQTTStatus, MQTT_CA_CERT_FILE, type OnProgressProps, type PalNonceManager, type PalNonceOptions, type PlayerAnalyticsContext, SUPPORTS_DASH, SUPPORTS_HLS, StormcloudPlayer, StormcloudVideoPlayer, StormcloudVideoPlayerComponent, type StormcloudVideoPlayerConfig, type StormcloudVideoPlayerProps, type TrackingData, applyMQTTConfig, buildAnalyticsContext, buildMQTTBrokerUrl, buildPlayerTopic, canPlay, configureMQTT, createHlsAdPlayer, createPalNonceManager, createStormcloudPlayer, StormcloudVideoPlayerComponent as default, detectBrowser, disconnectMQTT, ensureMQTTClient, getBrowserConfigOverrides, getBrowserID, getClientInfo, getMQTTStatus, initMQTTClient, initializePolyfills, isMQTTConfigured, isMQTTConnected, isMQTTEnabled, isMediaStream, lazy, logBrowserInfo, merge, mqttConfig, omit, parseQuery, players, publishMQTT, randomString, requiresMediaPipelineResetAfterAds, sendAdDetectTracking, sendAdImpressionTracking, sendAdLoadedTracking, sendHeartbeat, sendInitialTracking, supportsFeature, supportsModernJS, supportsWebKitPresentationMode };
|
package/lib/index.js
CHANGED
|
@@ -372,15 +372,19 @@ import React, { useEffect, useRef, useMemo, useCallback } from "react";
|
|
|
372
372
|
import Hls from "hls.js";
|
|
373
373
|
var MAX_VAST_WRAPPER_DEPTH = 5;
|
|
374
374
|
function createHlsAdPlayer(contentVideo, options) {
|
|
375
|
+
var _contentVideo_AD_VIDEO_PROP, _contentVideo_AD_CONTAINER_PROP;
|
|
375
376
|
var adPlaying = false;
|
|
376
377
|
var originalMutedState = false;
|
|
377
378
|
var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
|
|
378
379
|
var listeners = /* @__PURE__ */ new Map();
|
|
379
380
|
var licenseKey = options === null || options === void 0 ? void 0 : options.licenseKey;
|
|
380
381
|
var mainHlsInstance = options === null || options === void 0 ? void 0 : options.mainHlsInstance;
|
|
381
|
-
var
|
|
382
|
+
var AD_CONTAINER_PROP = "__stormcloudAdContainer";
|
|
383
|
+
var AD_VIDEO_PROP = "__stormcloudAdVideo";
|
|
384
|
+
var adVideoElement = (_contentVideo_AD_VIDEO_PROP = contentVideo[AD_VIDEO_PROP]) !== null && _contentVideo_AD_VIDEO_PROP !== void 0 ? _contentVideo_AD_VIDEO_PROP : void 0;
|
|
382
385
|
var adHls;
|
|
383
|
-
var adContainerEl;
|
|
386
|
+
var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
|
|
387
|
+
var adEventHandlers = [];
|
|
384
388
|
var currentAd;
|
|
385
389
|
var podAds = [];
|
|
386
390
|
var podIndex = 0;
|
|
@@ -535,6 +539,56 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
535
539
|
var url = mediaFile.url.toLowerCase();
|
|
536
540
|
return type.startsWith("video/") || url.endsWith(".mp4") || url.includes(".mp4?");
|
|
537
541
|
}
|
|
542
|
+
function isAudioMediaFile(mediaFile) {
|
|
543
|
+
var type = mediaFile.type.toLowerCase();
|
|
544
|
+
var url = (mediaFile.url.toLowerCase().split("?")[0] || "").trim();
|
|
545
|
+
return type.startsWith("audio/") || url.endsWith(".mp3") || url.endsWith(".aac") || url.endsWith(".m4a") || url.endsWith(".ogg") || url.endsWith(".oga") || url.endsWith(".opus") || url.endsWith(".wav") || url.endsWith(".weba");
|
|
546
|
+
}
|
|
547
|
+
function collectVideoMediaFiles(scope, verbose) {
|
|
548
|
+
var mediaFileElements = scope.querySelectorAll("MediaFile");
|
|
549
|
+
var mediaFiles = [];
|
|
550
|
+
if (verbose) {
|
|
551
|
+
console.log("[HlsAdPlayer] Found ".concat(mediaFileElements.length, " MediaFile element(s) in VAST XML"));
|
|
552
|
+
}
|
|
553
|
+
mediaFileElements.forEach(function(mf, index) {
|
|
554
|
+
var _mf_textContent;
|
|
555
|
+
var type = mf.getAttribute("type") || "";
|
|
556
|
+
var url = ((_mf_textContent = mf.textContent) === null || _mf_textContent === void 0 ? void 0 : _mf_textContent.trim()) || "";
|
|
557
|
+
var width = mf.getAttribute("width") || "";
|
|
558
|
+
var height = mf.getAttribute("height") || "";
|
|
559
|
+
if (verbose) {
|
|
560
|
+
console.log("[HlsAdPlayer] MediaFile ".concat(index, ': type="').concat(type, '", url="').concat(url, '", width="').concat(width, '", height="').concat(height, '"'));
|
|
561
|
+
}
|
|
562
|
+
if (!url) {
|
|
563
|
+
if (verbose) {
|
|
564
|
+
console.warn("[HlsAdPlayer] MediaFile ".concat(index, " has empty URL"));
|
|
565
|
+
}
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
var bitrateAttr = mf.getAttribute("bitrate");
|
|
569
|
+
var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
|
|
570
|
+
var mediaFile = {
|
|
571
|
+
url: url,
|
|
572
|
+
type: type,
|
|
573
|
+
width: parseInt(width || "1920", 10),
|
|
574
|
+
height: parseInt(height || "1080", 10),
|
|
575
|
+
bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
|
|
576
|
+
};
|
|
577
|
+
if (isAudioMediaFile(mediaFile)) {
|
|
578
|
+
console.warn("[HlsAdPlayer] MediaFile ".concat(index, ' skipped (audio-only, type="').concat(type, '") — audio ads are not played to avoid a black screen'));
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {
|
|
582
|
+
mediaFiles.push(mediaFile);
|
|
583
|
+
if (verbose) {
|
|
584
|
+
console.log("[HlsAdPlayer] Added ".concat(isHlsMediaFile(mediaFile) ? "HLS" : "progressive", " MediaFile: ").concat(url));
|
|
585
|
+
}
|
|
586
|
+
} else if (verbose) {
|
|
587
|
+
console.log("[HlsAdPlayer] MediaFile ".concat(index, ' ignored (type="').concat(type, '" is not supported)'));
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
return mediaFiles;
|
|
591
|
+
}
|
|
538
592
|
function createEmptyTrackingUrls() {
|
|
539
593
|
return {
|
|
540
594
|
impression: [],
|
|
@@ -622,37 +676,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
622
676
|
var durationText = ((_xmlDoc_querySelector3 = xmlDoc.querySelector("Duration")) === null || _xmlDoc_querySelector3 === void 0 ? void 0 : _xmlDoc_querySelector3.textContent) || "00:00:30";
|
|
623
677
|
var durationParts = durationText.split(":");
|
|
624
678
|
var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
|
|
625
|
-
var
|
|
626
|
-
var mediaFiles = [];
|
|
627
|
-
console.log("[HlsAdPlayer] Found ".concat(mediaFileElements.length, " MediaFile element(s) in VAST XML"));
|
|
628
|
-
mediaFileElements.forEach(function(mf, index) {
|
|
629
|
-
var _mf_textContent;
|
|
630
|
-
var type = mf.getAttribute("type") || "";
|
|
631
|
-
var url = ((_mf_textContent = mf.textContent) === null || _mf_textContent === void 0 ? void 0 : _mf_textContent.trim()) || "";
|
|
632
|
-
var width = mf.getAttribute("width") || "";
|
|
633
|
-
var height = mf.getAttribute("height") || "";
|
|
634
|
-
console.log("[HlsAdPlayer] MediaFile ".concat(index, ': type="').concat(type, '", url="').concat(url, '", width="').concat(width, '", height="').concat(height, '"'));
|
|
635
|
-
var mediaFile = {
|
|
636
|
-
url: url,
|
|
637
|
-
type: type,
|
|
638
|
-
width: parseInt(width || "1920", 10),
|
|
639
|
-
height: parseInt(height || "1080", 10),
|
|
640
|
-
bitrate: void 0
|
|
641
|
-
};
|
|
642
|
-
if (!url) {
|
|
643
|
-
console.warn("[HlsAdPlayer] MediaFile ".concat(index, " has empty URL"));
|
|
644
|
-
return;
|
|
645
|
-
}
|
|
646
|
-
var bitrateAttr = mf.getAttribute("bitrate");
|
|
647
|
-
var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
|
|
648
|
-
mediaFile.bitrate = bitrateValue && bitrateValue > 0 ? bitrateValue : void 0;
|
|
649
|
-
if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {
|
|
650
|
-
mediaFiles.push(mediaFile);
|
|
651
|
-
console.log("[HlsAdPlayer] Added ".concat(isHlsMediaFile(mediaFile) ? "HLS" : "progressive", " MediaFile: ").concat(url));
|
|
652
|
-
} else {
|
|
653
|
-
console.log("[HlsAdPlayer] MediaFile ".concat(index, ' ignored (type="').concat(type, '" is not supported)'));
|
|
654
|
-
}
|
|
655
|
-
});
|
|
679
|
+
var mediaFiles = collectVideoMediaFiles(xmlDoc, true);
|
|
656
680
|
if (mediaFiles.length === 0) {
|
|
657
681
|
if (isNoAdAvailable) {
|
|
658
682
|
console.warn("[HlsAdPlayer] No ads available (VAST response indicates no ads)");
|
|
@@ -700,28 +724,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
700
724
|
var durationText = ((_adElement_querySelector3 = adElement.querySelector("Duration")) === null || _adElement_querySelector3 === void 0 ? void 0 : _adElement_querySelector3.textContent) || "00:00:30";
|
|
701
725
|
var durationParts = durationText.split(":");
|
|
702
726
|
var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
|
|
703
|
-
var
|
|
704
|
-
var mediaFiles = [];
|
|
705
|
-
mediaFileElements.forEach(function(mf) {
|
|
706
|
-
var _mf_textContent;
|
|
707
|
-
var type = mf.getAttribute("type") || "";
|
|
708
|
-
var url = ((_mf_textContent = mf.textContent) === null || _mf_textContent === void 0 ? void 0 : _mf_textContent.trim()) || "";
|
|
709
|
-
var width = mf.getAttribute("width") || "";
|
|
710
|
-
var height = mf.getAttribute("height") || "";
|
|
711
|
-
if (!url) return;
|
|
712
|
-
var bitrateAttr = mf.getAttribute("bitrate");
|
|
713
|
-
var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
|
|
714
|
-
var mediaFile = {
|
|
715
|
-
url: url,
|
|
716
|
-
type: type,
|
|
717
|
-
width: parseInt(width || "1920", 10),
|
|
718
|
-
height: parseInt(height || "1080", 10),
|
|
719
|
-
bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
|
|
720
|
-
};
|
|
721
|
-
if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {
|
|
722
|
-
mediaFiles.push(mediaFile);
|
|
723
|
-
}
|
|
724
|
-
});
|
|
727
|
+
var mediaFiles = collectVideoMediaFiles(adElement, false);
|
|
725
728
|
if (mediaFiles.length === 0) {
|
|
726
729
|
if (isNoAdAvailable) {
|
|
727
730
|
console.warn("[HlsAdPlayer] Pod <Ad> indicates no ad available");
|
|
@@ -1024,7 +1027,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1024
1027
|
}
|
|
1025
1028
|
function setupAdEventListeners() {
|
|
1026
1029
|
if (!adVideoElement || !currentAd) return;
|
|
1027
|
-
|
|
1030
|
+
if (adEventHandlers.length > 0) return;
|
|
1031
|
+
var onTimeUpdate = function onTimeUpdate() {
|
|
1028
1032
|
if (!currentAd || !adVideoElement) return;
|
|
1029
1033
|
noteAdProgress();
|
|
1030
1034
|
var progress = adVideoElement.currentTime / currentAd.duration;
|
|
@@ -1040,15 +1044,15 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1040
1044
|
trackingFired.thirdQuartile = true;
|
|
1041
1045
|
fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);
|
|
1042
1046
|
}
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1047
|
+
};
|
|
1048
|
+
var onPlaying = function onPlaying() {
|
|
1045
1049
|
startStallWatchdog();
|
|
1046
1050
|
if (!currentAd || trackingFired.start) return;
|
|
1047
1051
|
trackingFired.start = true;
|
|
1048
1052
|
fireTrackingPixels(currentAd.trackingUrls.start);
|
|
1049
1053
|
console.log("[HlsAdPlayer] Ad started playing");
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1054
|
+
};
|
|
1055
|
+
var onEnded = function onEnded() {
|
|
1052
1056
|
if (!currentAd || trackingFired.complete) return;
|
|
1053
1057
|
trackingFired.complete = true;
|
|
1054
1058
|
fireTrackingPixels(currentAd.trackingUrls.complete);
|
|
@@ -1057,8 +1061,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1057
1061
|
return;
|
|
1058
1062
|
}
|
|
1059
1063
|
handleAdComplete();
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1064
|
+
};
|
|
1065
|
+
var onError = function onError(e) {
|
|
1062
1066
|
if (!adPlaying) return;
|
|
1063
1067
|
console.error("[HlsAdPlayer] Ad video error:", e);
|
|
1064
1068
|
if (currentAd) {
|
|
@@ -1068,25 +1072,100 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1068
1072
|
return;
|
|
1069
1073
|
}
|
|
1070
1074
|
handleAdError();
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
|
-
if (!currentAd) return;
|
|
1075
|
+
};
|
|
1076
|
+
var onVolumeChange = function onVolumeChange() {
|
|
1077
|
+
if (!currentAd || !adVideoElement) return;
|
|
1074
1078
|
if (adVideoElement.muted) {
|
|
1075
1079
|
fireTrackingPixels(currentAd.trackingUrls.mute);
|
|
1076
1080
|
} else {
|
|
1077
1081
|
fireTrackingPixels(currentAd.trackingUrls.unmute);
|
|
1078
1082
|
}
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
if (currentAd && !adVideoElement.ended) {
|
|
1083
|
+
};
|
|
1084
|
+
var onPause = function onPause() {
|
|
1085
|
+
if (currentAd && adVideoElement && !adVideoElement.ended) {
|
|
1082
1086
|
fireTrackingPixels(currentAd.trackingUrls.pause);
|
|
1083
1087
|
}
|
|
1084
|
-
}
|
|
1085
|
-
|
|
1086
|
-
if (currentAd && adVideoElement.currentTime > 0) {
|
|
1088
|
+
};
|
|
1089
|
+
var onPlay = function onPlay() {
|
|
1090
|
+
if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {
|
|
1087
1091
|
fireTrackingPixels(currentAd.trackingUrls.resume);
|
|
1088
1092
|
}
|
|
1089
|
-
}
|
|
1093
|
+
};
|
|
1094
|
+
adEventHandlers = [
|
|
1095
|
+
{
|
|
1096
|
+
type: "timeupdate",
|
|
1097
|
+
handler: onTimeUpdate
|
|
1098
|
+
},
|
|
1099
|
+
{
|
|
1100
|
+
type: "playing",
|
|
1101
|
+
handler: onPlaying
|
|
1102
|
+
},
|
|
1103
|
+
{
|
|
1104
|
+
type: "ended",
|
|
1105
|
+
handler: onEnded
|
|
1106
|
+
},
|
|
1107
|
+
{
|
|
1108
|
+
type: "error",
|
|
1109
|
+
handler: onError
|
|
1110
|
+
},
|
|
1111
|
+
{
|
|
1112
|
+
type: "volumechange",
|
|
1113
|
+
handler: onVolumeChange
|
|
1114
|
+
},
|
|
1115
|
+
{
|
|
1116
|
+
type: "pause",
|
|
1117
|
+
handler: onPause
|
|
1118
|
+
},
|
|
1119
|
+
{
|
|
1120
|
+
type: "play",
|
|
1121
|
+
handler: onPlay
|
|
1122
|
+
}
|
|
1123
|
+
];
|
|
1124
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
1125
|
+
try {
|
|
1126
|
+
for(var _iterator = adEventHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
1127
|
+
var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
|
|
1128
|
+
adVideoElement.addEventListener(type, handler);
|
|
1129
|
+
}
|
|
1130
|
+
} catch (err) {
|
|
1131
|
+
_didIteratorError = true;
|
|
1132
|
+
_iteratorError = err;
|
|
1133
|
+
} finally{
|
|
1134
|
+
try {
|
|
1135
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
1136
|
+
_iterator.return();
|
|
1137
|
+
}
|
|
1138
|
+
} finally{
|
|
1139
|
+
if (_didIteratorError) {
|
|
1140
|
+
throw _iteratorError;
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
function teardownAdEventListeners() {
|
|
1146
|
+
if (adVideoElement) {
|
|
1147
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
1148
|
+
try {
|
|
1149
|
+
for(var _iterator = adEventHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
1150
|
+
var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
|
|
1151
|
+
adVideoElement.removeEventListener(type, handler);
|
|
1152
|
+
}
|
|
1153
|
+
} catch (err) {
|
|
1154
|
+
_didIteratorError = true;
|
|
1155
|
+
_iteratorError = err;
|
|
1156
|
+
} finally{
|
|
1157
|
+
try {
|
|
1158
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
1159
|
+
_iterator.return();
|
|
1160
|
+
}
|
|
1161
|
+
} finally{
|
|
1162
|
+
if (_didIteratorError) {
|
|
1163
|
+
throw _iteratorError;
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
adEventHandlers = [];
|
|
1090
1169
|
}
|
|
1091
1170
|
function setAdPlayingFlag(isPlaying) {
|
|
1092
1171
|
if (isPlaying) {
|
|
@@ -1232,15 +1311,13 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1232
1311
|
adHls = void 0;
|
|
1233
1312
|
}
|
|
1234
1313
|
if (adVideoElement) {
|
|
1235
|
-
adVideoElement.pause();
|
|
1236
|
-
adVideoElement.removeAttribute("src");
|
|
1237
1314
|
try {
|
|
1315
|
+
adVideoElement.pause();
|
|
1316
|
+
adVideoElement.removeAttribute("src");
|
|
1238
1317
|
adVideoElement.load();
|
|
1239
1318
|
} catch (error) {
|
|
1240
|
-
console.warn("[HlsAdPlayer]
|
|
1319
|
+
console.warn("[HlsAdPlayer] Error releasing ad decoder:", error);
|
|
1241
1320
|
}
|
|
1242
|
-
adVideoElement.remove();
|
|
1243
|
-
adVideoElement = void 0;
|
|
1244
1321
|
}
|
|
1245
1322
|
if (adContainerEl) {
|
|
1246
1323
|
adContainerEl.style.display = "none";
|
|
@@ -1303,6 +1380,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1303
1380
|
(_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
|
|
1304
1381
|
adContainerEl = container;
|
|
1305
1382
|
}
|
|
1383
|
+
contentVideo[AD_CONTAINER_PROP] = adContainerEl;
|
|
1306
1384
|
},
|
|
1307
1385
|
requestAds: function requestAds(vastTagUrl) {
|
|
1308
1386
|
return _async_to_generator(function() {
|
|
@@ -1405,8 +1483,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1405
1483
|
if (!adVideoElement) {
|
|
1406
1484
|
adVideoElement = createAdVideoElement();
|
|
1407
1485
|
adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.appendChild(adVideoElement);
|
|
1408
|
-
|
|
1486
|
+
contentVideo[AD_VIDEO_PROP] = adVideoElement;
|
|
1409
1487
|
}
|
|
1488
|
+
setupAdEventListeners();
|
|
1410
1489
|
resetQuartileTracking(true);
|
|
1411
1490
|
contentVolume = contentVideo.volume;
|
|
1412
1491
|
originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
|
|
@@ -1534,11 +1613,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1534
1613
|
setAdPlayingFlag(false);
|
|
1535
1614
|
contentVideo.muted = originalMutedState;
|
|
1536
1615
|
contentVideo.volume = Math.max(0, Math.min(1, originalVolume));
|
|
1616
|
+
teardownAdEventListeners();
|
|
1537
1617
|
releaseAdDecoder();
|
|
1538
|
-
if (adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.parentElement) {
|
|
1539
|
-
adContainerEl.parentElement.removeChild(adContainerEl);
|
|
1540
|
-
}
|
|
1541
|
-
adContainerEl = void 0;
|
|
1542
1618
|
currentAd = void 0;
|
|
1543
1619
|
podAds = [];
|
|
1544
1620
|
podIndex = 0;
|
|
@@ -3974,6 +4050,11 @@ function detectBrowser() {
|
|
|
3974
4050
|
chromeVersion: chromeVersionNum
|
|
3975
4051
|
};
|
|
3976
4052
|
}
|
|
4053
|
+
function requiresMediaPipelineResetAfterAds() {
|
|
4054
|
+
var _browser_tizenVersion;
|
|
4055
|
+
var browser = detectBrowser();
|
|
4056
|
+
return browser.name === "Samsung Tizen" && ((_browser_tizenVersion = browser.tizenVersion) !== null && _browser_tizenVersion !== void 0 ? _browser_tizenVersion : 0) >= 5;
|
|
4057
|
+
}
|
|
3977
4058
|
function getBrowserConfigOverrides() {
|
|
3978
4059
|
var browser = detectBrowser();
|
|
3979
4060
|
var overrides = {};
|
|
@@ -6764,30 +6845,49 @@ var HlsEngine = /*#__PURE__*/ function() {
|
|
|
6764
6845
|
{
|
|
6765
6846
|
key: "reloadLiveStream",
|
|
6766
6847
|
value: function reloadLiveStream() {
|
|
6848
|
+
var _this = this;
|
|
6767
6849
|
var hls = this.hls;
|
|
6768
6850
|
if (!hls) {
|
|
6769
6851
|
return;
|
|
6770
6852
|
}
|
|
6771
6853
|
if (this.debug) {
|
|
6772
|
-
console.log("[StormcloudVideoPlayer] Hard-reloading live stream (
|
|
6854
|
+
console.log("[StormcloudVideoPlayer] Hard-reloading live stream (destroy hls \u2192 reset video \u2192 fresh setupHls)");
|
|
6773
6855
|
}
|
|
6774
6856
|
try {
|
|
6775
6857
|
this.reloadingLiveStream = true;
|
|
6776
6858
|
hls.stopLoad();
|
|
6777
6859
|
hls.detachMedia();
|
|
6860
|
+
hls.destroy();
|
|
6861
|
+
this.hls = void 0;
|
|
6778
6862
|
try {
|
|
6779
6863
|
this.video.removeAttribute("src");
|
|
6780
6864
|
this.video.load();
|
|
6781
6865
|
} catch (error) {
|
|
6782
6866
|
console.warn("[StormcloudVideoPlayer] video.load() threw after src removal:", error);
|
|
6783
6867
|
}
|
|
6784
|
-
hls.attachMedia(this.video);
|
|
6785
6868
|
} catch (error) {
|
|
6786
6869
|
this.reloadingLiveStream = false;
|
|
6870
|
+
this.hls = void 0;
|
|
6787
6871
|
if (this.debug) {
|
|
6788
|
-
console.warn("[StormcloudVideoPlayer] Failed to hard-reload
|
|
6872
|
+
console.warn("[StormcloudVideoPlayer] Failed to tear down during hard-reload:", error);
|
|
6789
6873
|
}
|
|
6874
|
+
return;
|
|
6790
6875
|
}
|
|
6876
|
+
var recreateDelayMs = 600;
|
|
6877
|
+
window.setTimeout(function() {
|
|
6878
|
+
if (_this.hls) {
|
|
6879
|
+
_this.reloadingLiveStream = false;
|
|
6880
|
+
return;
|
|
6881
|
+
}
|
|
6882
|
+
try {
|
|
6883
|
+
_this.setupHls();
|
|
6884
|
+
} catch (error) {
|
|
6885
|
+
_this.reloadingLiveStream = false;
|
|
6886
|
+
if (_this.debug) {
|
|
6887
|
+
console.warn("[StormcloudVideoPlayer] Failed to rebuild pipeline during hard-reload:", error);
|
|
6888
|
+
}
|
|
6889
|
+
}
|
|
6890
|
+
}, recreateDelayMs);
|
|
6791
6891
|
}
|
|
6792
6892
|
},
|
|
6793
6893
|
{
|
|
@@ -8101,6 +8201,14 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
|
|
|
8101
8201
|
this.host.video.style.visibility = "visible";
|
|
8102
8202
|
this.host.video.style.opacity = "1";
|
|
8103
8203
|
if (this.host.isLiveStream()) {
|
|
8204
|
+
if (this.host.requiresMediaPipelineResetAfterAds()) {
|
|
8205
|
+
if (this.debug) {
|
|
8206
|
+
console.log("[StormcloudVideoPlayer] Live break end \u2014 hard-reloading stream to reacquire decoder (single-decoder platform)");
|
|
8207
|
+
}
|
|
8208
|
+
this.host.reloadLiveStream();
|
|
8209
|
+
this.monitorLiveResumeStall(this.host.video.currentTime);
|
|
8210
|
+
return;
|
|
8211
|
+
}
|
|
8104
8212
|
var liveSyncPos = this.host.getLiveSyncPosition();
|
|
8105
8213
|
if (liveSyncPos != null && liveSyncPos > this.host.video.currentTime) {
|
|
8106
8214
|
if (this.debug) {
|
|
@@ -8162,9 +8270,10 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
|
|
|
8162
8270
|
key: "monitorLiveResumeStall",
|
|
8163
8271
|
value: function monitorLiveResumeStall(resumeBaseline) {
|
|
8164
8272
|
var _this = this;
|
|
8273
|
+
var needsReset = this.host.requiresMediaPipelineResetAfterAds();
|
|
8165
8274
|
var pollIntervalMs = 1e3;
|
|
8166
|
-
var graceMs = 5e3;
|
|
8167
|
-
var recoveryCooldownMs = 5e3;
|
|
8275
|
+
var graceMs = needsReset ? 8e3 : 5e3;
|
|
8276
|
+
var recoveryCooldownMs = needsReset ? 7e3 : 5e3;
|
|
8168
8277
|
var maxRecoveries = 3;
|
|
8169
8278
|
var maxMonitorMs = 45e3;
|
|
8170
8279
|
var startTime = Date.now();
|
|
@@ -8278,7 +8387,12 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
|
|
|
8278
8387
|
if (canRecover) {
|
|
8279
8388
|
recoveries++;
|
|
8280
8389
|
lastRecoveryAt = Date.now();
|
|
8281
|
-
if (
|
|
8390
|
+
if (needsReset) {
|
|
8391
|
+
if (_this.debug) {
|
|
8392
|
+
console.warn("[StormcloudVideoPlayer] Content still wedged after ad break — hard-reloading live stream (recovery ".concat(recoveries, "/").concat(maxRecoveries, ") — ").concat(_this.describeVideoState()));
|
|
8393
|
+
}
|
|
8394
|
+
_this.host.reloadLiveStream();
|
|
8395
|
+
} else if (recoveries === 1) {
|
|
8282
8396
|
if (_this.debug) {
|
|
8283
8397
|
console.warn("[StormcloudVideoPlayer] Content wedged after ad break — calling recoverMediaError() (recovery ".concat(recoveries, "/").concat(maxRecoveries, ") — ").concat(_this.describeVideoState()));
|
|
8284
8398
|
}
|
|
@@ -8492,6 +8606,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
8492
8606
|
recoverMediaError: function recoverMediaError() {
|
|
8493
8607
|
return _this.hlsEngine.recoverMediaError();
|
|
8494
8608
|
},
|
|
8609
|
+
requiresMediaPipelineResetAfterAds: function requiresMediaPipelineResetAfterAds1() {
|
|
8610
|
+
return requiresMediaPipelineResetAfterAds();
|
|
8611
|
+
},
|
|
8495
8612
|
generatePodVastUrl: function generatePodVastUrl(base, breakDurationMs) {
|
|
8496
8613
|
return _this.generatePodVastUrl(base, breakDurationMs);
|
|
8497
8614
|
}
|
|
@@ -11804,5 +11921,5 @@ var createStormcloudPlayer = function createStormcloudPlayer(playerList, fallbac
|
|
|
11804
11921
|
};
|
|
11805
11922
|
var StormcloudPlayer = createStormcloudPlayer(players_default, players_default[players_default.length - 1]);
|
|
11806
11923
|
var StormcloudPlayer_default = StormcloudPlayer;
|
|
11807
|
-
export { DEFAULT_MQTT_CONFIG, IS_BROWSER, IS_GLOBAL, IS_IOS, IS_SAFARI, MQTT_CA_CERT_FILE, SUPPORTS_DASH, SUPPORTS_HLS, StormcloudPlayer_default as StormcloudPlayer, StormcloudVideoPlayer, StormcloudVideoPlayerComponent, applyMQTTConfig, buildAnalyticsContext, buildMQTTBrokerUrl, buildPlayerTopic, canPlay, configureMQTT, createHlsAdPlayer, createPalNonceManager, createStormcloudPlayer, StormcloudVideoPlayerComponent as default, detectBrowser, disconnectMQTT, ensureMQTTClient, getBrowserConfigOverrides, getBrowserID, getClientInfo, getMQTTStatus, initMQTTClient, initializePolyfills, isMQTTConfigured, isMQTTConnected, isMQTTEnabled, isMediaStream, lazy, logBrowserInfo, merge, mqttConfig, omit, parseQuery, players_default as players, publishMQTT, randomString, sendAdDetectTracking, sendAdImpressionTracking, sendAdLoadedTracking, sendHeartbeat, sendInitialTracking, supportsFeature, supportsModernJS, supportsWebKitPresentationMode };
|
|
11924
|
+
export { DEFAULT_MQTT_CONFIG, IS_BROWSER, IS_GLOBAL, IS_IOS, IS_SAFARI, MQTT_CA_CERT_FILE, SUPPORTS_DASH, SUPPORTS_HLS, StormcloudPlayer_default as StormcloudPlayer, StormcloudVideoPlayer, StormcloudVideoPlayerComponent, applyMQTTConfig, buildAnalyticsContext, buildMQTTBrokerUrl, buildPlayerTopic, canPlay, configureMQTT, createHlsAdPlayer, createPalNonceManager, createStormcloudPlayer, StormcloudVideoPlayerComponent as default, detectBrowser, disconnectMQTT, ensureMQTTClient, getBrowserConfigOverrides, getBrowserID, getClientInfo, getMQTTStatus, initMQTTClient, initializePolyfills, isMQTTConfigured, isMQTTConnected, isMQTTEnabled, isMediaStream, lazy, logBrowserInfo, merge, mqttConfig, omit, parseQuery, players_default as players, publishMQTT, randomString, requiresMediaPipelineResetAfterAds, sendAdDetectTracking, sendAdImpressionTracking, sendAdLoadedTracking, sendHeartbeat, sendInitialTracking, supportsFeature, supportsModernJS, supportsWebKitPresentationMode };
|
|
11808
11925
|
//# sourceMappingURL=index.js.map
|