stormcloud-video-player 0.8.21 → 0.8.23
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 +140 -28
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +140 -28
- package/lib/index.js.map +1 -1
- package/lib/player/AdBreakOrchestrator.cjs +7 -0
- package/lib/player/AdBreakOrchestrator.cjs.map +1 -1
- package/lib/player/AdBreakOrchestrator.d.cts +1 -0
- package/lib/player/AdConfigManager.cjs +95 -14
- package/lib/player/AdConfigManager.cjs.map +1 -1
- package/lib/player/HlsEngine.cjs +12 -3
- package/lib/player/HlsEngine.cjs.map +1 -1
- package/lib/player/HlsEngine.d.cts +1 -0
- package/lib/player/StormcloudVideoPlayer.cjs +136 -27
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.cjs +137 -27
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +137 -27
- package/lib/players/index.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +138 -28
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/utils/ctvVastSignals.cjs +88 -7
- package/lib/utils/ctvVastSignals.cjs.map +1 -1
- package/lib/utils/vastEnvironmentSignals.cjs +88 -7
- package/lib/utils/vastEnvironmentSignals.cjs.map +1 -1
- package/lib/utils/vastMacros.cjs.map +1 -1
- package/package.json +1 -1
|
@@ -2317,6 +2317,18 @@ var AIRY_ROKU_APP_ID = "com.freeairytv.roku";
|
|
|
2317
2317
|
var AIRY_APP_NAME = "AiryTV Movies & TV";
|
|
2318
2318
|
var AIRY_DEFAULT_CONTENT_URL = "https://live.airy.tv";
|
|
2319
2319
|
var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
|
|
2320
|
+
var LG_TEST_APP_ID = "com.hulu.plus";
|
|
2321
|
+
var LG_TEST_APP_NAME = "Hulu";
|
|
2322
|
+
var LG_TEST_CONTENT_URL = "https://www.hulu.com/live-tv";
|
|
2323
|
+
var _lgTestDeviceId;
|
|
2324
|
+
function getLgTestDeviceId() {
|
|
2325
|
+
if (!_lgTestDeviceId) _lgTestDeviceId = createUuid();
|
|
2326
|
+
return _lgTestDeviceId;
|
|
2327
|
+
}
|
|
2328
|
+
function isLgWebOS() {
|
|
2329
|
+
if (typeof navigator === "undefined") return false;
|
|
2330
|
+
return /Web0S|webOS|LG Browser|LGSTB|LGE/i.test(navigator.userAgent);
|
|
2331
|
+
}
|
|
2320
2332
|
function getDefaultAppId() {
|
|
2321
2333
|
if (typeof navigator === "undefined") return AIRY_ANDROID_APP_ID;
|
|
2322
2334
|
var ua = navigator.userAgent;
|
|
@@ -2342,17 +2354,20 @@ var ANDROID_ID_TYPES = /* @__PURE__ */ new Set([
|
|
|
2342
2354
|
"adid"
|
|
2343
2355
|
]);
|
|
2344
2356
|
function resolveVastEnvironmentSignals(isCtv) {
|
|
2345
|
-
var _ref
|
|
2357
|
+
var _ref;
|
|
2346
2358
|
var bridgeSignals = readNativeBridgeSignals();
|
|
2347
|
-
var
|
|
2348
|
-
var
|
|
2349
|
-
var
|
|
2359
|
+
var platformDevice = readPlatformNativeDeviceId();
|
|
2360
|
+
var lg = isCtv && isLgWebOS();
|
|
2361
|
+
var deviceId = bridgeSignals.deviceId || readStoredDeviceId() || platformDevice.deviceId || (lg && platformDevice.limitAdTracking !== true ? getLgTestDeviceId() : void 0);
|
|
2362
|
+
var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || readStoredString("idtype") || platformDevice.deviceIdType || inferDeviceIdType() || (lg ? "lgudid" : void 0);
|
|
2363
|
+
var platformLat = bridgeSignals.deviceId ? bridgeSignals.limitAdTracking : platformDevice.limitAdTracking;
|
|
2364
|
+
var limitAdTracking = deviceId != null ? (_ref = platformLat !== null && platformLat !== void 0 ? platformLat : readStoredLimitAdTracking()) !== null && _ref !== void 0 ? _ref : false : void 0;
|
|
2350
2365
|
if (isCtv) {
|
|
2351
2366
|
return _object_spread_props(_object_spread({
|
|
2352
2367
|
isCtv: true,
|
|
2353
|
-
contentUrl: bridgeSignals.contentUrl || readStoredString("contentUrl") || AIRY_DEFAULT_CONTENT_URL,
|
|
2354
|
-
appId: bridgeSignals.appId || readStoredString("appId") || readStoredString("msid") || getDefaultAppId(),
|
|
2355
|
-
appName: bridgeSignals.appName || readStoredString("appName") || readStoredString("an") || AIRY_APP_NAME,
|
|
2368
|
+
contentUrl: bridgeSignals.contentUrl || readStoredString("contentUrl") || (lg ? LG_TEST_CONTENT_URL : AIRY_DEFAULT_CONTENT_URL),
|
|
2369
|
+
appId: bridgeSignals.appId || readStoredString("appId") || readStoredString("msid") || (lg ? LG_TEST_APP_ID : getDefaultAppId()),
|
|
2370
|
+
appName: bridgeSignals.appName || readStoredString("appName") || readStoredString("an") || (lg ? LG_TEST_APP_NAME : AIRY_APP_NAME),
|
|
2356
2371
|
sessionId: getOrCreateCtvSessionId()
|
|
2357
2372
|
}, deviceId ? {
|
|
2358
2373
|
deviceId: deviceId
|
|
@@ -2417,6 +2432,72 @@ function createUuid() {
|
|
|
2417
2432
|
return nibble.toString(16);
|
|
2418
2433
|
});
|
|
2419
2434
|
}
|
|
2435
|
+
function readPlatformNativeDeviceId() {
|
|
2436
|
+
if (typeof window === "undefined") return {};
|
|
2437
|
+
try {
|
|
2438
|
+
var _window_webapis;
|
|
2439
|
+
var adinfo = (_window_webapis = window.webapis) === null || _window_webapis === void 0 ? void 0 : _window_webapis.adinfo;
|
|
2440
|
+
if (adinfo) {
|
|
2441
|
+
var tifa = typeof adinfo.getTIFA === "function" ? adinfo.getTIFA() : adinfo.tifa;
|
|
2442
|
+
if (typeof tifa === "string" && tifa && !isMacroPlaceholder(tifa)) {
|
|
2443
|
+
var lat = typeof adinfo.isLATEnabled === "function" ? adinfo.isLATEnabled() : void 0;
|
|
2444
|
+
return _object_spread({
|
|
2445
|
+
deviceId: tifa,
|
|
2446
|
+
deviceIdType: "tifa"
|
|
2447
|
+
}, typeof lat === "boolean" ? {
|
|
2448
|
+
limitAdTracking: lat
|
|
2449
|
+
} : {});
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
} catch (unused) {}
|
|
2453
|
+
try {
|
|
2454
|
+
var webOSDev = window.webOSDev;
|
|
2455
|
+
if (webOSDev) {
|
|
2456
|
+
var _webOSDev_lgudid;
|
|
2457
|
+
var lgudid = typeof webOSDev.LGUDID === "function" ? webOSDev.LGUDID() : (_webOSDev_lgudid = webOSDev.lgudid) !== null && _webOSDev_lgudid !== void 0 ? _webOSDev_lgudid : webOSDev.LGUDID;
|
|
2458
|
+
if (typeof lgudid === "string" && lgudid) {
|
|
2459
|
+
if (isZeroedAdId(lgudid)) {
|
|
2460
|
+
return {
|
|
2461
|
+
deviceIdType: "lgudid",
|
|
2462
|
+
limitAdTracking: true
|
|
2463
|
+
};
|
|
2464
|
+
}
|
|
2465
|
+
if (!isMacroPlaceholder(lgudid)) {
|
|
2466
|
+
return {
|
|
2467
|
+
deviceId: lgudid,
|
|
2468
|
+
deviceIdType: "lgudid",
|
|
2469
|
+
limitAdTracking: false
|
|
2470
|
+
};
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
} catch (unused) {}
|
|
2475
|
+
try {
|
|
2476
|
+
var roku = window.Roku;
|
|
2477
|
+
if (roku) {
|
|
2478
|
+
var rida = typeof roku.getPublisherUniqueId === "function" ? roku.getPublisherUniqueId() : roku.rida;
|
|
2479
|
+
if (typeof rida === "string" && rida && !isMacroPlaceholder(rida)) {
|
|
2480
|
+
return {
|
|
2481
|
+
deviceId: rida,
|
|
2482
|
+
deviceIdType: "rida",
|
|
2483
|
+
limitAdTracking: false
|
|
2484
|
+
};
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
} catch (unused) {}
|
|
2488
|
+
return {};
|
|
2489
|
+
}
|
|
2490
|
+
var ZEROED_AD_ID_PATTERNS = /* @__PURE__ */ new Set([
|
|
2491
|
+
"38400000-8cf0-11bd-b23e-10b96e40000d",
|
|
2492
|
+
"00000000-0000-0000-0000-000000000000"
|
|
2493
|
+
]);
|
|
2494
|
+
function isMacroPlaceholder(value) {
|
|
2495
|
+
var t = value.trim();
|
|
2496
|
+
return !t || /^(\[[^\]]*\]|\{[^}]*\}|%%[^%]*%%)$/.test(t) || /^(unknown|null|undefined|none|n\/a|\$\{[^}]+\})$/i.test(t) || ZEROED_AD_ID_PATTERNS.has(t.toLowerCase());
|
|
2497
|
+
}
|
|
2498
|
+
function isZeroedAdId(value) {
|
|
2499
|
+
return ZEROED_AD_ID_PATTERNS.has(value.trim().toLowerCase());
|
|
2500
|
+
}
|
|
2420
2501
|
function readNativeBridgeSignals() {
|
|
2421
2502
|
if (typeof window === "undefined") {
|
|
2422
2503
|
return {};
|
|
@@ -2757,7 +2838,7 @@ var INLINE_DEVICE_MACRO_REPLACEMENTS = [
|
|
|
2757
2838
|
}
|
|
2758
2839
|
}
|
|
2759
2840
|
];
|
|
2760
|
-
function
|
|
2841
|
+
function isMacroPlaceholder2(value) {
|
|
2761
2842
|
if (value == null) return true;
|
|
2762
2843
|
var trimmed = value.trim();
|
|
2763
2844
|
if (!trimmed) return true;
|
|
@@ -2816,11 +2897,11 @@ function applyDeviceIdentityParams(params, ctx) {
|
|
|
2816
2897
|
if (runtimeId) {
|
|
2817
2898
|
params.set("rdid", runtimeId);
|
|
2818
2899
|
params.set("idtype", runtimeType || tagType || "aaid");
|
|
2819
|
-
params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue :
|
|
2900
|
+
params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : isMacroPlaceholder2(tagLat) ? "0" : tagLat);
|
|
2820
2901
|
return;
|
|
2821
2902
|
}
|
|
2822
|
-
var tagRdidValid = Boolean(tagRdid && !
|
|
2823
|
-
var tagTypeValid = Boolean(tagType && !
|
|
2903
|
+
var tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder2(tagRdid));
|
|
2904
|
+
var tagTypeValid = Boolean(tagType && !isMacroPlaceholder2(tagType));
|
|
2824
2905
|
if (tagRdidValid && tagTypeValid && runtimeType && !isEquivalentDeviceIdType(tagType, runtimeType)) {
|
|
2825
2906
|
params.delete("rdid");
|
|
2826
2907
|
params.delete("idtype");
|
|
@@ -2828,10 +2909,10 @@ function applyDeviceIdentityParams(params, ctx) {
|
|
|
2828
2909
|
return;
|
|
2829
2910
|
}
|
|
2830
2911
|
if (tagRdidValid) {
|
|
2831
|
-
if (
|
|
2912
|
+
if (isMacroPlaceholder2(tagType) && runtimeType) {
|
|
2832
2913
|
params.set("idtype", runtimeType);
|
|
2833
2914
|
}
|
|
2834
|
-
if (
|
|
2915
|
+
if (isMacroPlaceholder2(tagLat)) {
|
|
2835
2916
|
params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : "0");
|
|
2836
2917
|
}
|
|
2837
2918
|
return;
|
|
@@ -3017,7 +3098,7 @@ function applyVastMacros(baseUrl, ctx) {
|
|
|
3017
3098
|
}
|
|
3018
3099
|
var staleKeys = [];
|
|
3019
3100
|
params.forEach(function(value, key) {
|
|
3020
|
-
if (
|
|
3101
|
+
if (isMacroPlaceholder2(value)) {
|
|
3021
3102
|
staleKeys.push(key);
|
|
3022
3103
|
}
|
|
3023
3104
|
});
|
|
@@ -5966,7 +6047,7 @@ var HlsEngine = /*#__PURE__*/ function() {
|
|
|
5966
6047
|
key: "setupNativeHls",
|
|
5967
6048
|
value: function setupNativeHls() {
|
|
5968
6049
|
return _async_to_generator(function() {
|
|
5969
|
-
var _this_config_isLiveStream, _this_config_lowLatencyMode, _this_video_play;
|
|
6050
|
+
var _this_config_isLiveStream, _this_config_lowLatencyMode, adBehavior, _this_video_play;
|
|
5970
6051
|
return _ts_generator(this, function(_state) {
|
|
5971
6052
|
switch(_state.label){
|
|
5972
6053
|
case 0:
|
|
@@ -5975,10 +6056,11 @@ var HlsEngine = /*#__PURE__*/ function() {
|
|
|
5975
6056
|
this.video.src = this.config.src;
|
|
5976
6057
|
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;
|
|
5977
6058
|
if (this.debug) {
|
|
5978
|
-
|
|
6059
|
+
adBehavior = this.isLiveStream ? "live (main video continues muted during ads)" : "vod (main video pauses during ads)";
|
|
6060
|
+
console.log("[StormcloudVideoPlayer] Using native HLS playback:", {
|
|
5979
6061
|
isLive: this.isLiveStream,
|
|
5980
6062
|
allowNativeHls: this.config.allowNativeHls,
|
|
5981
|
-
adBehavior:
|
|
6063
|
+
adBehavior: adBehavior
|
|
5982
6064
|
});
|
|
5983
6065
|
}
|
|
5984
6066
|
if (!this.config.autoplay) return [
|
|
@@ -6387,6 +6469,14 @@ var HlsEngine = /*#__PURE__*/ function() {
|
|
|
6387
6469
|
});
|
|
6388
6470
|
}
|
|
6389
6471
|
},
|
|
6472
|
+
{
|
|
6473
|
+
key: "getLiveSyncPosition",
|
|
6474
|
+
value: function getLiveSyncPosition() {
|
|
6475
|
+
var _this_hls;
|
|
6476
|
+
var pos = (_this_hls = this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.liveSyncPosition;
|
|
6477
|
+
return typeof pos === "number" && Number.isFinite(pos) ? pos : void 0;
|
|
6478
|
+
}
|
|
6479
|
+
},
|
|
6390
6480
|
{
|
|
6391
6481
|
key: "destroy",
|
|
6392
6482
|
value: function destroy() {
|
|
@@ -7961,6 +8051,13 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
|
|
|
7961
8051
|
this.host.video.volume = restoredVolume;
|
|
7962
8052
|
}
|
|
7963
8053
|
if (this.host.shouldContinueLiveStreamDuringAds()) {
|
|
8054
|
+
var liveSyncPos = this.host.getLiveSyncPosition();
|
|
8055
|
+
if (liveSyncPos != null && liveSyncPos > this.host.video.currentTime) {
|
|
8056
|
+
if (this.debug) {
|
|
8057
|
+
console.log("[StormcloudVideoPlayer] Live break end — snapping to live edge: ".concat(this.host.video.currentTime.toFixed(2), "s → ").concat(liveSyncPos.toFixed(2), "s"));
|
|
8058
|
+
}
|
|
8059
|
+
this.host.video.currentTime = liveSyncPos;
|
|
8060
|
+
}
|
|
7964
8061
|
if (this.host.video.paused) {
|
|
7965
8062
|
var _this_host_video_play;
|
|
7966
8063
|
if (this.debug) console.log("[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback");
|
|
@@ -8103,6 +8200,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
8103
8200
|
shouldContinueLiveStreamDuringAds: function shouldContinueLiveStreamDuringAds() {
|
|
8104
8201
|
return _this.shouldContinueLiveStreamDuringAds();
|
|
8105
8202
|
},
|
|
8203
|
+
getLiveSyncPosition: function getLiveSyncPosition() {
|
|
8204
|
+
return _this.hlsEngine.getLiveSyncPosition();
|
|
8205
|
+
},
|
|
8106
8206
|
generateVastUrls: function generateVastUrls(base, count) {
|
|
8107
8207
|
return _this.generateVastUrls(base, count);
|
|
8108
8208
|
}
|
|
@@ -8144,7 +8244,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
8144
8244
|
// ───────────────────────────────────────────────────────────────
|
|
8145
8245
|
function load() {
|
|
8146
8246
|
return _async_to_generator(function() {
|
|
8147
|
-
var _this, _this_config_lowLatencyMode, error;
|
|
8247
|
+
var _this, _this_config_lowLatencyMode, error, continueLiveStreamDuringAds;
|
|
8148
8248
|
return _ts_generator(this, function(_state) {
|
|
8149
8249
|
switch(_state.label){
|
|
8150
8250
|
case 0:
|
|
@@ -8198,15 +8298,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
8198
8298
|
3,
|
|
8199
8299
|
6
|
|
8200
8300
|
];
|
|
8201
|
-
this.adPlayer.destroy();
|
|
8202
|
-
this.adPlayer = this.createAdPlayer(false);
|
|
8203
|
-
this.adPlayer.initialize();
|
|
8204
8301
|
return [
|
|
8205
8302
|
4,
|
|
8206
8303
|
this.hlsEngine.setupNativeHls()
|
|
8207
8304
|
];
|
|
8208
8305
|
case 5:
|
|
8209
8306
|
_state.sent();
|
|
8307
|
+
continueLiveStreamDuringAds = this.shouldContinueLiveStreamDuringAds();
|
|
8308
|
+
if (this.debug) {
|
|
8309
|
+
console.log("[StormcloudVideoPlayer] Native HLS ad behavior:", {
|
|
8310
|
+
isLive: this.hlsEngine.isLiveStream,
|
|
8311
|
+
continueLiveStreamDuringAds: continueLiveStreamDuringAds
|
|
8312
|
+
});
|
|
8313
|
+
}
|
|
8314
|
+
this.adPlayer.destroy();
|
|
8315
|
+
this.adPlayer = this.createAdPlayer(continueLiveStreamDuringAds);
|
|
8316
|
+
this.adPlayer.initialize();
|
|
8210
8317
|
return [
|
|
8211
8318
|
2
|
|
8212
8319
|
];
|
|
@@ -8314,9 +8421,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
8314
8421
|
{
|
|
8315
8422
|
key: "shouldContinueLiveStreamDuringAds",
|
|
8316
8423
|
value: function shouldContinueLiveStreamDuringAds() {
|
|
8317
|
-
if (this.
|
|
8318
|
-
|
|
8319
|
-
|
|
8424
|
+
if (this.hlsEngine.isLiveStream) {
|
|
8425
|
+
return true;
|
|
8426
|
+
}
|
|
8427
|
+
var duration = this.video.duration;
|
|
8428
|
+
if (!Number.isFinite(duration) || duration === Infinity) {
|
|
8429
|
+
return true;
|
|
8430
|
+
}
|
|
8431
|
+
return false;
|
|
8320
8432
|
}
|
|
8321
8433
|
},
|
|
8322
8434
|
{
|
|
@@ -8614,9 +8726,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
8614
8726
|
this.adBreak.showAds = true;
|
|
8615
8727
|
this.adBreak.inAdBreak = true;
|
|
8616
8728
|
this.timing.currentAdBreakStartWallClockMs = Date.now();
|
|
8617
|
-
if (!this.video.paused) {
|
|
8618
|
-
this.video.pause();
|
|
8619
|
-
}
|
|
8620
8729
|
_state.label = 1;
|
|
8621
8730
|
case 1:
|
|
8622
8731
|
_state.trys.push([
|
|
@@ -8990,7 +9099,8 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
|
|
|
8990
9099
|
setShowSpeedMenu(false);
|
|
8991
9100
|
};
|
|
8992
9101
|
var isHlsStream = (src === null || src === void 0 ? void 0 : src.toLowerCase().includes(".m3u8")) || (src === null || src === void 0 ? void 0 : src.toLowerCase().includes("/hls/"));
|
|
8993
|
-
var
|
|
9102
|
+
var isLiveUiMode = isLiveStream === true;
|
|
9103
|
+
var shouldShowEnhancedControls = showCustomControls && (isHlsStream ? !isLiveUiMode : true);
|
|
8994
9104
|
var criticalPropsKey = (0, import_react.useMemo)(function() {
|
|
8995
9105
|
return CRITICAL_PROPS.map(function(prop) {
|
|
8996
9106
|
return "".concat(prop, ":").concat(props[prop]);
|