stormcloud-video-player 0.8.48 → 0.8.50
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 +2 -2
- package/lib/index.cjs +107 -5
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +107 -5
- package/lib/index.js.map +1 -1
- package/lib/player/AdTimingService.cjs +5 -5
- package/lib/player/AdTimingService.cjs.map +1 -1
- package/lib/player/AdTimingService.d.cts +6 -1
- package/lib/player/StormcloudVideoPlayer.cjs +107 -5
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.cjs +107 -5
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +107 -5
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +95 -0
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/types-iDjS8f_7.d.cts +133 -0
- package/lib/ui/StormcloudVideoPlayer.cjs +107 -5
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/package.json +1 -1
package/lib/sdk/hlsAdPlayer.cjs
CHANGED
|
@@ -209,6 +209,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
209
209
|
var mainHlsInstance = options === null || options === void 0 ? void 0 : options.mainHlsInstance;
|
|
210
210
|
var AD_CONTAINER_PROP = "__stormcloudAdContainer";
|
|
211
211
|
var AD_VIDEO_PROP = "__stormcloudAdVideo";
|
|
212
|
+
var FRAME_COUNTER_RELIABLE_PROP = "__stormcloudFrameCounterReliable";
|
|
212
213
|
var adVideoElement = (_contentVideo_AD_VIDEO_PROP = contentVideo[AD_VIDEO_PROP]) !== null && _contentVideo_AD_VIDEO_PROP !== void 0 ? _contentVideo_AD_VIDEO_PROP : void 0;
|
|
213
214
|
var adHls;
|
|
214
215
|
var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
|
|
@@ -223,9 +224,12 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
223
224
|
var pendingTimeouts = [];
|
|
224
225
|
var STALL_TIMEOUT_MS = 4e3;
|
|
225
226
|
var STALL_CHECK_INTERVAL_MS = 1e3;
|
|
227
|
+
var BLACKFRAME_MIN_PLAYBACK_S = 1.5;
|
|
226
228
|
var stallWatchdogId;
|
|
227
229
|
var lastAdProgressTime = 0;
|
|
228
230
|
var lastAdProgressPosition = 0;
|
|
231
|
+
var sawDecodedVideoFrame = false;
|
|
232
|
+
var videoFrameCallbackHandle;
|
|
229
233
|
var trackingFired = {
|
|
230
234
|
impression: false,
|
|
231
235
|
start: false,
|
|
@@ -406,6 +410,11 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
406
410
|
console.warn("[HlsAdPlayer] MediaFile ".concat(index, ' skipped (audio-only, type="').concat(type, '") — audio ads are not played to avoid a black screen'));
|
|
407
411
|
return;
|
|
408
412
|
}
|
|
413
|
+
var hasExplicitDimensions = mf.getAttribute("width") != null && mf.getAttribute("height") != null;
|
|
414
|
+
if (!isHlsMediaFile(mediaFile) && hasExplicitDimensions && (mediaFile.width <= 1 || mediaFile.height <= 1)) {
|
|
415
|
+
console.warn("[HlsAdPlayer] MediaFile ".concat(index, " skipped (degenerate dimensions ").concat(mediaFile.width, "x").concat(mediaFile.height, ', type="').concat(type, '") — likely an audio-only placeholder rendition'));
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
409
418
|
if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {
|
|
410
419
|
mediaFiles.push(mediaFile);
|
|
411
420
|
if (verbose) {
|
|
@@ -873,6 +882,14 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
873
882
|
fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);
|
|
874
883
|
}
|
|
875
884
|
};
|
|
885
|
+
var onLoadedMetadata = function onLoadedMetadata() {
|
|
886
|
+
if (!adPlaying || !adVideoElement) return;
|
|
887
|
+
var videoWidth = adVideoElement.videoWidth, videoHeight = adVideoElement.videoHeight;
|
|
888
|
+
if (videoWidth <= 1 || videoHeight <= 1) {
|
|
889
|
+
console.warn("[HlsAdPlayer] Ad creative has no usable video dimensions (".concat(videoWidth, "x").concat(videoHeight, ") - skipping this creative"));
|
|
890
|
+
handleVideoDecodeFailure();
|
|
891
|
+
}
|
|
892
|
+
};
|
|
876
893
|
var onPlaying = function onPlaying() {
|
|
877
894
|
startStallWatchdog();
|
|
878
895
|
if (!currentAd || trackingFired.start) return;
|
|
@@ -924,6 +941,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
924
941
|
type: "timeupdate",
|
|
925
942
|
handler: onTimeUpdate
|
|
926
943
|
},
|
|
944
|
+
{
|
|
945
|
+
type: "loadedmetadata",
|
|
946
|
+
handler: onLoadedMetadata
|
|
947
|
+
},
|
|
927
948
|
{
|
|
928
949
|
type: "playing",
|
|
929
950
|
handler: onPlaying
|
|
@@ -1095,6 +1116,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1095
1116
|
clearInterval(stallWatchdogId);
|
|
1096
1117
|
stallWatchdogId = void 0;
|
|
1097
1118
|
}
|
|
1119
|
+
cancelVideoFrameProbe();
|
|
1098
1120
|
}
|
|
1099
1121
|
function noteAdProgress() {
|
|
1100
1122
|
lastAdProgressTime = Date.now();
|
|
@@ -1113,13 +1135,86 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1113
1135
|
}
|
|
1114
1136
|
handleAdError();
|
|
1115
1137
|
}
|
|
1138
|
+
function getDecodedVideoFrameCount(video) {
|
|
1139
|
+
try {
|
|
1140
|
+
if (typeof video.getVideoPlaybackQuality === "function") {
|
|
1141
|
+
var quality = video.getVideoPlaybackQuality();
|
|
1142
|
+
if (quality && typeof quality.totalVideoFrames === "number") {
|
|
1143
|
+
return quality.totalVideoFrames;
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
var legacyCount = video.webkitDecodedFrameCount;
|
|
1147
|
+
if (typeof legacyCount === "number") {
|
|
1148
|
+
return legacyCount;
|
|
1149
|
+
}
|
|
1150
|
+
} catch (error) {
|
|
1151
|
+
console.warn("[HlsAdPlayer] Unable to read decoded video frame count:", error);
|
|
1152
|
+
}
|
|
1153
|
+
return void 0;
|
|
1154
|
+
}
|
|
1155
|
+
function isFrameCounterReliable() {
|
|
1156
|
+
return contentVideo[FRAME_COUNTER_RELIABLE_PROP] === true;
|
|
1157
|
+
}
|
|
1158
|
+
function markFrameCounterReliable() {
|
|
1159
|
+
contentVideo[FRAME_COUNTER_RELIABLE_PROP] = true;
|
|
1160
|
+
}
|
|
1161
|
+
function cancelVideoFrameProbe() {
|
|
1162
|
+
if (videoFrameCallbackHandle != null && adVideoElement && typeof adVideoElement.cancelVideoFrameCallback === "function") {
|
|
1163
|
+
try {
|
|
1164
|
+
adVideoElement.cancelVideoFrameCallback(videoFrameCallbackHandle);
|
|
1165
|
+
} catch (error) {
|
|
1166
|
+
console.warn("[HlsAdPlayer] Error cancelling video frame callback:", error);
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
videoFrameCallbackHandle = void 0;
|
|
1170
|
+
}
|
|
1171
|
+
function startVideoFrameProbe() {
|
|
1172
|
+
cancelVideoFrameProbe();
|
|
1173
|
+
if (!adVideoElement) return;
|
|
1174
|
+
var rvfc = adVideoElement.requestVideoFrameCallback;
|
|
1175
|
+
if (typeof rvfc !== "function") return;
|
|
1176
|
+
var onPresentedFrame = function onPresentedFrame() {
|
|
1177
|
+
videoFrameCallbackHandle = void 0;
|
|
1178
|
+
if (!adPlaying) return;
|
|
1179
|
+
sawDecodedVideoFrame = true;
|
|
1180
|
+
};
|
|
1181
|
+
try {
|
|
1182
|
+
videoFrameCallbackHandle = rvfc.call(adVideoElement, onPresentedFrame);
|
|
1183
|
+
} catch (error) {
|
|
1184
|
+
console.warn("[HlsAdPlayer] Error requesting video frame callback:", error);
|
|
1185
|
+
videoFrameCallbackHandle = void 0;
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
function handleVideoDecodeFailure() {
|
|
1189
|
+
console.warn("[HlsAdPlayer] Ad audio is advancing but no video frames decoded (black screen) - skipping this creative");
|
|
1190
|
+
clearStallWatchdog();
|
|
1191
|
+
if (currentAd) {
|
|
1192
|
+
fireTrackingPixels(currentAd.trackingUrls.error);
|
|
1193
|
+
}
|
|
1194
|
+
if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
|
|
1195
|
+
return;
|
|
1196
|
+
}
|
|
1197
|
+
handleAdError();
|
|
1198
|
+
}
|
|
1116
1199
|
function startStallWatchdog() {
|
|
1117
1200
|
clearStallWatchdog();
|
|
1118
1201
|
noteAdProgress();
|
|
1202
|
+
sawDecodedVideoFrame = false;
|
|
1203
|
+
startVideoFrameProbe();
|
|
1119
1204
|
stallWatchdogId = window.setInterval(function() {
|
|
1120
1205
|
if (!adPlaying || !adVideoElement) {
|
|
1121
1206
|
return;
|
|
1122
1207
|
}
|
|
1208
|
+
if (!sawDecodedVideoFrame && !adVideoElement.paused) {
|
|
1209
|
+
var decodedFrames = getDecodedVideoFrameCount(adVideoElement);
|
|
1210
|
+
if (decodedFrames !== void 0 && decodedFrames > 0) {
|
|
1211
|
+
sawDecodedVideoFrame = true;
|
|
1212
|
+
markFrameCounterReliable();
|
|
1213
|
+
} else if (decodedFrames === 0 && adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S && isFrameCounterReliable()) {
|
|
1214
|
+
handleVideoDecodeFailure();
|
|
1215
|
+
return;
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1123
1218
|
if (adVideoElement.currentTime > lastAdProgressPosition + 0.05) {
|
|
1124
1219
|
noteAdProgress();
|
|
1125
1220
|
return;
|