stormcloud-video-player 0.8.76 → 0.8.78
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/Player.cjs +2 -0
- package/lib/Player.cjs.map +1 -1
- package/lib/Player.d.cts +9 -1
- package/lib/StormcloudPlayer.cjs +235 -6
- package/lib/StormcloudPlayer.cjs.map +1 -1
- package/lib/index.cjs +235 -6
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.ts +6 -0
- package/lib/index.js +236 -6
- package/lib/index.js.map +1 -1
- package/lib/player/ContentHealthWatchdog.cjs +255 -0
- package/lib/player/ContentHealthWatchdog.cjs.map +1 -0
- package/lib/player/ContentHealthWatchdog.d.cts +40 -0
- package/lib/player/StormcloudVideoPlayer.cjs +225 -6
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +1 -0
- package/lib/players/HlsPlayer.cjs +231 -6
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +231 -6
- package/lib/players/index.cjs.map +1 -1
- package/lib/props.cjs +2 -0
- package/lib/props.cjs.map +1 -1
- package/lib/props.d.cts +5 -1
- package/lib/sdk/hlsAdPlayer.cjs +16 -6
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/types.d.cts +1 -0
- package/lib/ui/StormcloudVideoPlayer.cjs +225 -6
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/utils/browserCompat.cjs +7 -0
- package/lib/utils/browserCompat.cjs.map +1 -1
- package/lib/utils/browserCompat.d.cts +2 -1
- package/package.json +2 -2
package/lib/players/index.cjs
CHANGED
|
@@ -2335,6 +2335,9 @@ function requiresMediaPipelineResetAfterAds() {
|
|
|
2335
2335
|
var browser = detectBrowser();
|
|
2336
2336
|
return browser.name === "Samsung Tizen" && ((_browser_tizenVersion = browser.tizenVersion) !== null && _browser_tizenVersion !== void 0 ? _browser_tizenVersion : 0) >= 5;
|
|
2337
2337
|
}
|
|
2338
|
+
function prefersProgressiveAdMedia() {
|
|
2339
|
+
return detectBrowser().isSmartTV;
|
|
2340
|
+
}
|
|
2338
2341
|
function getBrowserConfigOverrides() {
|
|
2339
2342
|
var browser = detectBrowser();
|
|
2340
2343
|
var overrides = {};
|
|
@@ -3178,6 +3181,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
3178
3181
|
var probe = adVideoElement !== null && adVideoElement !== void 0 ? adVideoElement : document.createElement("video");
|
|
3179
3182
|
var pageIsHttps = typeof location !== "undefined" && location.protocol === "https:";
|
|
3180
3183
|
var target = getMediaTargetQuality();
|
|
3184
|
+
var deprioritizeHls = prefersProgressiveAdMedia();
|
|
3181
3185
|
var accepted = [];
|
|
3182
3186
|
mediaFiles.forEach(function(file, index) {
|
|
3183
3187
|
var isHls = isHlsMediaFile(file);
|
|
@@ -3208,19 +3212,24 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
3208
3212
|
var bitrateDiff = Math.abs((file.bitrate || 5e3) * 1e3 - target.bitrate);
|
|
3209
3213
|
score = resolutionDiff * 2 + bitrateDiff / 1e3;
|
|
3210
3214
|
}
|
|
3215
|
+
var deprioritizedHls = deprioritizeHls && isHls;
|
|
3211
3216
|
accepted.push({
|
|
3212
3217
|
file: file,
|
|
3213
3218
|
score: score,
|
|
3214
|
-
insecure: insecure
|
|
3219
|
+
insecure: insecure,
|
|
3220
|
+
deprioritizedHls: deprioritizedHls
|
|
3215
3221
|
});
|
|
3216
3222
|
logFunnel("media_candidate", _object_spread_props(_object_spread({}, details), {
|
|
3217
3223
|
reason: "accepted",
|
|
3218
|
-
why: insecure ? "insecure_http_deprioritized" : "playable",
|
|
3224
|
+
why: insecure ? "insecure_http_deprioritized" : deprioritizedHls ? "hls_deprioritized_on_tv" : "playable",
|
|
3219
3225
|
score: score
|
|
3220
3226
|
}));
|
|
3221
3227
|
});
|
|
3222
3228
|
accepted.sort(function(a, b) {
|
|
3223
3229
|
if (a.insecure !== b.insecure) return a.insecure ? 1 : -1;
|
|
3230
|
+
if (a.deprioritizedHls !== b.deprioritizedHls) {
|
|
3231
|
+
return a.deprioritizedHls ? 1 : -1;
|
|
3232
|
+
}
|
|
3224
3233
|
return a.score - b.score;
|
|
3225
3234
|
});
|
|
3226
3235
|
return accepted.map(function(entry) {
|
|
@@ -4893,8 +4902,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
4893
4902
|
console.warn("[HlsAdPlayer] Error preparing ad video for new source:", error);
|
|
4894
4903
|
}
|
|
4895
4904
|
}
|
|
4896
|
-
function recreateAdVideoElement() {
|
|
4897
|
-
console.log("[HlsAdPlayer] Recreating ad video element (
|
|
4905
|
+
function recreateAdVideoElement(reason) {
|
|
4906
|
+
console.log("[HlsAdPlayer] Recreating ad video element (".concat(reason, ")"));
|
|
4898
4907
|
teardownAdEventListeners();
|
|
4899
4908
|
prepareVideoElementForNewSource();
|
|
4900
4909
|
if (adVideoElement) {
|
|
@@ -4938,8 +4947,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
4938
4947
|
}
|
|
4939
4948
|
function resetVideoElementForNextSource() {
|
|
4940
4949
|
clearStallWatchdog();
|
|
4941
|
-
|
|
4942
|
-
|
|
4950
|
+
var previousSourceUsedHlsJs = adHls !== void 0;
|
|
4951
|
+
if (requiresMediaPipelineResetAfterAds() || previousSourceUsedHlsJs) {
|
|
4952
|
+
recreateAdVideoElement(previousSourceUsedHlsJs ? "after hls.js source" : "single-decoder platform");
|
|
4943
4953
|
setupAdEventListeners();
|
|
4944
4954
|
} else {
|
|
4945
4955
|
prepareVideoElementForNewSource();
|
|
@@ -12421,6 +12431,181 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
|
|
|
12421
12431
|
]);
|
|
12422
12432
|
return AdBreakOrchestrator;
|
|
12423
12433
|
}();
|
|
12434
|
+
// src/player/ContentHealthWatchdog.ts
|
|
12435
|
+
var POLL_INTERVAL_MS = 2e3;
|
|
12436
|
+
var STALL_THRESHOLD_MS = 12e3;
|
|
12437
|
+
var POST_BREAK_GRACE_MS = 5e4;
|
|
12438
|
+
var MAX_BREAK_SUPPRESSION_MS = 10 * 60 * 1e3;
|
|
12439
|
+
var SELF_INFLICTED_PAUSE_WINDOW_MS = 5e3;
|
|
12440
|
+
var HEALTHY_PLAYBACK_SECONDS = 5;
|
|
12441
|
+
var MAX_NORMAL_ADVANCE_PER_TICK_S = 4;
|
|
12442
|
+
var LIGHT_STEP_COOLDOWN_MS = 1e4;
|
|
12443
|
+
var RELOAD_BASE_COOLDOWN_MS = 15e3;
|
|
12444
|
+
var RELOAD_MAX_COOLDOWN_MS = 12e4;
|
|
12445
|
+
var ContentHealthWatchdog = /*#__PURE__*/ function() {
|
|
12446
|
+
function ContentHealthWatchdog(host) {
|
|
12447
|
+
var _this = this;
|
|
12448
|
+
_class_call_check(this, ContentHealthWatchdog);
|
|
12449
|
+
this.host = host;
|
|
12450
|
+
this.armed = false;
|
|
12451
|
+
this.userPaused = false;
|
|
12452
|
+
this.wasInBreak = false;
|
|
12453
|
+
this.breakStartedAt = 0;
|
|
12454
|
+
this.stuckBreakLogged = false;
|
|
12455
|
+
this.graceUntil = 0;
|
|
12456
|
+
this.lastPosition = 0;
|
|
12457
|
+
this.lastProgressAt = 0;
|
|
12458
|
+
this.lastRealPlaybackAt = 0;
|
|
12459
|
+
this.healthySeconds = 0;
|
|
12460
|
+
this.step = 0;
|
|
12461
|
+
this.nextActionAt = 0;
|
|
12462
|
+
this.lastActionAt = 0;
|
|
12463
|
+
this.onPlaying = function() {
|
|
12464
|
+
if (_this.host.isAdPlaying()) return;
|
|
12465
|
+
_this.armed = true;
|
|
12466
|
+
_this.userPaused = false;
|
|
12467
|
+
};
|
|
12468
|
+
this.onPause = function() {
|
|
12469
|
+
if (_this.host.isBreakActive() || _this.host.isAdPlaying() || Date.now() - _this.lastActionAt < SELF_INFLICTED_PAUSE_WINDOW_MS) {
|
|
12470
|
+
return;
|
|
12471
|
+
}
|
|
12472
|
+
_this.userPaused = true;
|
|
12473
|
+
};
|
|
12474
|
+
this.onPlay = function() {
|
|
12475
|
+
_this.userPaused = false;
|
|
12476
|
+
};
|
|
12477
|
+
}
|
|
12478
|
+
_create_class(ContentHealthWatchdog, [
|
|
12479
|
+
{
|
|
12480
|
+
key: "start",
|
|
12481
|
+
value: function start() {
|
|
12482
|
+
var _this = this;
|
|
12483
|
+
if (this.intervalId !== void 0) return;
|
|
12484
|
+
var video = this.host.video;
|
|
12485
|
+
video.addEventListener("playing", this.onPlaying);
|
|
12486
|
+
video.addEventListener("pause", this.onPause);
|
|
12487
|
+
video.addEventListener("play", this.onPlay);
|
|
12488
|
+
this.resetProgress(Date.now());
|
|
12489
|
+
this.intervalId = window.setInterval(function() {
|
|
12490
|
+
return _this.tick();
|
|
12491
|
+
}, POLL_INTERVAL_MS);
|
|
12492
|
+
}
|
|
12493
|
+
},
|
|
12494
|
+
{
|
|
12495
|
+
key: "stop",
|
|
12496
|
+
value: function stop() {
|
|
12497
|
+
if (this.intervalId !== void 0) {
|
|
12498
|
+
clearInterval(this.intervalId);
|
|
12499
|
+
this.intervalId = void 0;
|
|
12500
|
+
}
|
|
12501
|
+
var video = this.host.video;
|
|
12502
|
+
video.removeEventListener("playing", this.onPlaying);
|
|
12503
|
+
video.removeEventListener("pause", this.onPause);
|
|
12504
|
+
video.removeEventListener("play", this.onPlay);
|
|
12505
|
+
this.armed = false;
|
|
12506
|
+
this.step = 0;
|
|
12507
|
+
}
|
|
12508
|
+
},
|
|
12509
|
+
{
|
|
12510
|
+
key: "resetProgress",
|
|
12511
|
+
value: function resetProgress(now) {
|
|
12512
|
+
this.lastPosition = this.host.video.currentTime;
|
|
12513
|
+
this.lastProgressAt = now;
|
|
12514
|
+
}
|
|
12515
|
+
},
|
|
12516
|
+
{
|
|
12517
|
+
key: "tick",
|
|
12518
|
+
value: function tick() {
|
|
12519
|
+
var now = Date.now();
|
|
12520
|
+
var video = this.host.video;
|
|
12521
|
+
var hidden = typeof document !== "undefined" && document.visibilityState === "hidden";
|
|
12522
|
+
if (!this.armed || this.userPaused || hidden || video.ended || !this.host.isLiveStream() || !this.host.hasHlsInstance()) {
|
|
12523
|
+
this.resetProgress(now);
|
|
12524
|
+
return;
|
|
12525
|
+
}
|
|
12526
|
+
var breakActive = this.host.isBreakActive() || this.host.isAdPlaying();
|
|
12527
|
+
if (breakActive && !this.wasInBreak) {
|
|
12528
|
+
this.wasInBreak = true;
|
|
12529
|
+
this.breakStartedAt = now;
|
|
12530
|
+
this.stuckBreakLogged = false;
|
|
12531
|
+
}
|
|
12532
|
+
if (breakActive && now - this.breakStartedAt < MAX_BREAK_SUPPRESSION_MS) {
|
|
12533
|
+
this.resetProgress(now);
|
|
12534
|
+
return;
|
|
12535
|
+
}
|
|
12536
|
+
if (breakActive && !this.stuckBreakLogged) {
|
|
12537
|
+
this.stuckBreakLogged = true;
|
|
12538
|
+
console.warn("[ContentWatchdog] Ad break state active for over ".concat(MAX_BREAK_SUPPRESSION_MS / 6e4, " min — monitoring content anyway"));
|
|
12539
|
+
}
|
|
12540
|
+
if (!breakActive && this.wasInBreak) {
|
|
12541
|
+
this.wasInBreak = false;
|
|
12542
|
+
this.graceUntil = now + POST_BREAK_GRACE_MS;
|
|
12543
|
+
this.resetProgress(now);
|
|
12544
|
+
return;
|
|
12545
|
+
}
|
|
12546
|
+
var currentTime = video.currentTime;
|
|
12547
|
+
var delta = currentTime - this.lastPosition;
|
|
12548
|
+
this.lastPosition = currentTime;
|
|
12549
|
+
if (delta > 0.25 && delta <= MAX_NORMAL_ADVANCE_PER_TICK_S && !video.paused) {
|
|
12550
|
+
this.lastProgressAt = now;
|
|
12551
|
+
this.lastRealPlaybackAt = now;
|
|
12552
|
+
this.healthySeconds += delta;
|
|
12553
|
+
if (this.step > 0 && this.healthySeconds >= HEALTHY_PLAYBACK_SECONDS) {
|
|
12554
|
+
console.log("[ContentWatchdog] Content playback recovered after ".concat(this.step, " recovery step(s)"));
|
|
12555
|
+
this.step = 0;
|
|
12556
|
+
this.nextActionAt = 0;
|
|
12557
|
+
}
|
|
12558
|
+
return;
|
|
12559
|
+
}
|
|
12560
|
+
if (now < this.graceUntil) {
|
|
12561
|
+
this.lastProgressAt = now;
|
|
12562
|
+
return;
|
|
12563
|
+
}
|
|
12564
|
+
if (now - this.lastProgressAt < STALL_THRESHOLD_MS || now < this.nextActionAt) {
|
|
12565
|
+
return;
|
|
12566
|
+
}
|
|
12567
|
+
this.recover(now);
|
|
12568
|
+
}
|
|
12569
|
+
},
|
|
12570
|
+
{
|
|
12571
|
+
key: "recover",
|
|
12572
|
+
value: function recover(now) {
|
|
12573
|
+
var video = this.host.video;
|
|
12574
|
+
var state = "t=".concat(video.currentTime.toFixed(2), " paused=").concat(video.paused, " readyState=").concat(video.readyState, " networkState=").concat(video.networkState, " error=").concat(video.error ? video.error.code : "none");
|
|
12575
|
+
var stalledForS = ((now - (this.lastRealPlaybackAt || this.lastProgressAt)) / 1e3).toFixed(0);
|
|
12576
|
+
var fullReloadOnly = this.host.requiresMediaPipelineResetAfterAds();
|
|
12577
|
+
var action = fullReloadOnly || this.step >= 2 ? "reload" : this.step === 0 ? "recover_media_error" : "restart_load";
|
|
12578
|
+
console.warn("[ContentWatchdog] Content stalled for ".concat(stalledForS, "s — ").concat(action, " (step ").concat(this.step + 1, ") — ").concat(state));
|
|
12579
|
+
this.lastActionAt = now;
|
|
12580
|
+
this.healthySeconds = 0;
|
|
12581
|
+
if (action === "recover_media_error") {
|
|
12582
|
+
this.host.recoverMediaError();
|
|
12583
|
+
this.nextActionAt = now + LIGHT_STEP_COOLDOWN_MS;
|
|
12584
|
+
} else if (action === "restart_load") {
|
|
12585
|
+
var liveSyncPos = this.host.getLiveSyncPosition();
|
|
12586
|
+
var position = liveSyncPos != null && liveSyncPos > video.currentTime ? liveSyncPos : video.currentTime;
|
|
12587
|
+
if (position !== video.currentTime) {
|
|
12588
|
+
video.currentTime = position;
|
|
12589
|
+
}
|
|
12590
|
+
this.host.restartHlsLoad(position);
|
|
12591
|
+
this.nextActionAt = now + LIGHT_STEP_COOLDOWN_MS;
|
|
12592
|
+
} else {
|
|
12593
|
+
var reloadIndex = fullReloadOnly ? this.step : this.step - 2;
|
|
12594
|
+
var cooldown = Math.min(RELOAD_BASE_COOLDOWN_MS * Math.pow(2, reloadIndex), RELOAD_MAX_COOLDOWN_MS);
|
|
12595
|
+
this.host.reloadLiveStream();
|
|
12596
|
+
this.nextActionAt = now + cooldown;
|
|
12597
|
+
}
|
|
12598
|
+
this.step++;
|
|
12599
|
+
this.resetProgress(now);
|
|
12600
|
+
if (video.paused) {
|
|
12601
|
+
var _video_play;
|
|
12602
|
+
(_video_play = video.play()) === null || _video_play === void 0 ? void 0 : _video_play.catch(function() {});
|
|
12603
|
+
}
|
|
12604
|
+
}
|
|
12605
|
+
}
|
|
12606
|
+
]);
|
|
12607
|
+
return ContentHealthWatchdog;
|
|
12608
|
+
}();
|
|
12424
12609
|
// src/player/StormcloudVideoPlayer.ts
|
|
12425
12610
|
var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
12426
12611
|
function StormcloudVideoPlayer(config) {
|
|
@@ -12551,6 +12736,36 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
12551
12736
|
return _this.palNonce.sendAdTouch(event);
|
|
12552
12737
|
}
|
|
12553
12738
|
}, this.timing, this.adConfig, this.cueManager, this.placeholder);
|
|
12739
|
+
this.contentWatchdog = new ContentHealthWatchdog({
|
|
12740
|
+
video: this.video,
|
|
12741
|
+
isLiveStream: function isLiveStream() {
|
|
12742
|
+
return _this.hlsEngine.isLiveStream;
|
|
12743
|
+
},
|
|
12744
|
+
hasHlsInstance: function hasHlsInstance() {
|
|
12745
|
+
return !!_this.hlsEngine.hls;
|
|
12746
|
+
},
|
|
12747
|
+
isBreakActive: function isBreakActive() {
|
|
12748
|
+
return _this.adBreak.inAdBreak || _this.adBreak.isBreakActive();
|
|
12749
|
+
},
|
|
12750
|
+
isAdPlaying: function isAdPlaying() {
|
|
12751
|
+
return _this.adPlayer.isAdPlaying();
|
|
12752
|
+
},
|
|
12753
|
+
requiresMediaPipelineResetAfterAds: function requiresMediaPipelineResetAfterAds1() {
|
|
12754
|
+
return requiresMediaPipelineResetAfterAds();
|
|
12755
|
+
},
|
|
12756
|
+
getLiveSyncPosition: function getLiveSyncPosition() {
|
|
12757
|
+
return _this.hlsEngine.getLiveSyncPosition();
|
|
12758
|
+
},
|
|
12759
|
+
recoverMediaError: function recoverMediaError() {
|
|
12760
|
+
return _this.hlsEngine.recoverMediaError();
|
|
12761
|
+
},
|
|
12762
|
+
restartHlsLoad: function restartHlsLoad(position) {
|
|
12763
|
+
return _this.hlsEngine.restartLoadAt(position);
|
|
12764
|
+
},
|
|
12765
|
+
reloadLiveStream: function reloadLiveStream() {
|
|
12766
|
+
return _this.hlsEngine.reloadLiveStream();
|
|
12767
|
+
}
|
|
12768
|
+
});
|
|
12554
12769
|
}
|
|
12555
12770
|
_create_class(StormcloudVideoPlayer, [
|
|
12556
12771
|
{
|
|
@@ -12871,6 +13086,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
12871
13086
|
}
|
|
12872
13087
|
};
|
|
12873
13088
|
this.video.addEventListener("emptied", this.emptiedHandler);
|
|
13089
|
+
if (this.config.contentStallWatchdog !== false) {
|
|
13090
|
+
this.contentWatchdog.start();
|
|
13091
|
+
}
|
|
12874
13092
|
}
|
|
12875
13093
|
},
|
|
12876
13094
|
{
|
|
@@ -13355,6 +13573,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
13355
13573
|
key: "destroy",
|
|
13356
13574
|
value: function destroy() {
|
|
13357
13575
|
var _this_adPlayer;
|
|
13576
|
+
this.contentWatchdog.stop();
|
|
13358
13577
|
this.adBreak.cancelScheduledRequest();
|
|
13359
13578
|
this.timing.destroy();
|
|
13360
13579
|
this.adBreak.clearPendingAdBreak();
|
|
@@ -13437,6 +13656,12 @@ var HlsPlayer = /*#__PURE__*/ function(_import_react2_Component) {
|
|
|
13437
13656
|
if (_this1.props.adFailsafeTimeoutMs !== void 0) config.adFailsafeTimeoutMs = _this1.props.adFailsafeTimeoutMs;
|
|
13438
13657
|
if (_this1.props.minSegmentsBeforePlay !== void 0) config.minSegmentsBeforePlay = _this1.props.minSegmentsBeforePlay;
|
|
13439
13658
|
if (_this1.props.ctvAdRequest !== void 0) config.ctvAdRequest = _this1.props.ctvAdRequest;
|
|
13659
|
+
if (_this1.props.vastTagUrl !== void 0) config.vastTagUrl = _this1.props.vastTagUrl;
|
|
13660
|
+
if (_this1.props.isVmap !== void 0) config.isVmap = _this1.props.isVmap;
|
|
13661
|
+
if (_this1.props.vmapUrl !== void 0) config.vmapUrl = _this1.props.vmapUrl;
|
|
13662
|
+
if (_this1.props.minRemainingMsToRequestAd !== void 0) config.minRemainingMsToRequestAd = _this1.props.minRemainingMsToRequestAd;
|
|
13663
|
+
if (_this1.props.maxNoFillsPerBreak !== void 0) config.maxNoFillsPerBreak = _this1.props.maxNoFillsPerBreak;
|
|
13664
|
+
if (_this1.props.maxAdBreakExtensionMs !== void 0) config.maxAdBreakExtensionMs = _this1.props.maxAdBreakExtensionMs;
|
|
13440
13665
|
_this1.player = new StormcloudVideoPlayer(config);
|
|
13441
13666
|
(_this_props_onMount = (_this_props = _this1.props).onMount) === null || _this_props_onMount === void 0 ? void 0 : _this_props_onMount.call(_this_props, _this1);
|
|
13442
13667
|
return [
|