// Video region playback, retry, and source probe helpers. var videoRegionLastGoodSrcCache = Object.create(null); var videoRegionProbeStateCache = Object.create(null); var videoRegionProbeTimerCache = Object.create(null); var VIDEO_REGION_RETRY_DELAY_MS = 5000; function getVideoRegionCacheKey(region) { return String(region && (region.regionKey || region.label) || '').trim(); } function isDirectlyRenderableSource(src) { return /^(?:https?:)?\/\//i.test(src) || /^data:/i.test(src) || /^blob:/i.test(src) || /^\/media\//i.test(src); } function appendCacheBust(src, cacheBust) { var key = String(cacheBust || '').trim(); var raw = String(src || '').trim(); if (!raw || !key) { return raw; } return raw + (raw.indexOf('?') === -1 ? '?' : '&') + 'v=' + encodeURIComponent(key); } function getVideoSourceAvailability(src) { return videoRegionProbeStateCache[String(src || '').trim()] || null; } function setVideoSourceAvailability(src, available) { var key = String(src || '').trim(); if (!key) { return; } videoRegionProbeStateCache[key] = { available: available === null ? null : Boolean(available), checkedAt: Date.now() }; } function logVideoRegionStatus(message, details, level) { if (typeof logDebug === 'function') { logDebug(message, details || '', level || 'info'); } } function triggerVideoRegionSourceRefresh() { if (typeof window.notifyVideoRegionSourceReady === 'function') { window.notifyVideoRegionSourceReady(); return; } if (typeof videoRegionRenderVersion === 'number') { videoRegionRenderVersion += 1; } slideMarkupCache = Object.create(null); if (typeof showCurrent === 'function' && slides && slides.length) { showCurrent(); } } function scheduleVideoSourceProbe(regionKey, src, isRetry) { var key = String(src || '').trim(); if (!regionKey || !key || isDirectlyRenderableSource(key)) { if (key) { setVideoSourceAvailability(key, true); } return; } if (videoRegionProbeTimerCache[key]) { return; } if (!isRetry) { logVideoRegionStatus('Video source changed; probing mirrored file before swapping.', 'region=' + regionKey + ' src=' + key); } else { logVideoRegionStatus('Video source still unavailable; retrying mirrored file probe.', 'region=' + regionKey + ' src=' + key, 'warn'); } videoRegionProbeTimerCache[key] = window.setTimeout(function () { delete videoRegionProbeTimerCache[key]; fetch(key, { method: 'HEAD', cache: 'no-store', credentials: 'same-origin' }).then(function (response) { if (response && response.ok) { setVideoSourceAvailability(key, true); if (videoRegionLastGoodSrcCache[regionKey] !== key) { videoRegionLastGoodSrcCache[regionKey] = key; logVideoRegionStatus('Mirrored video is ready; switching to the new source.', 'region=' + regionKey + ' src=' + key); triggerVideoRegionSourceRefresh(); } return; } setVideoSourceAvailability(key, false); logVideoRegionStatus('Mirrored video probe returned unavailable; keeping the old source for now.', 'region=' + regionKey + ' src=' + key, 'warn'); scheduleVideoSourceProbe(regionKey, key, true); }).catch(function () { setVideoSourceAvailability(key, false); logVideoRegionStatus('Mirrored video probe failed; keeping the old source for now.', 'region=' + regionKey + ' src=' + key, 'warn'); scheduleVideoSourceProbe(regionKey, key, true); }); }, isRetry ? VIDEO_REGION_RETRY_DELAY_MS : 0); } function renderVideoRegion(region, regionContent) { var requestedSrc = String(regionContent && regionContent.value || '').trim(); var requestedSrcVersioned = appendCacheBust(requestedSrc, regionContent && regionContent.cache_bust); var regionKey = getVideoRegionCacheKey(region); var cachedSrc = regionKey ? String(videoRegionLastGoodSrcCache[regionKey] || '').trim() : ''; var cachedSrcVersioned = appendCacheBust(cachedSrc, regionContent && regionContent.cache_bust); var disableAudio = regionContent && regionContent.disable_audio === undefined ? true : Boolean(regionContent && regionContent.disable_audio); if (!requestedSrc) { return ''; } if (isDirectlyRenderableSource(requestedSrc)) { if (regionKey) { videoRegionLastGoodSrcCache[regionKey] = requestedSrc; } setVideoSourceAvailability(requestedSrc, true); return '
'; } var requestedState = getVideoSourceAvailability(requestedSrc); var requestedReady = Boolean(requestedState && requestedState.available === true); if (requestedReady) { if (regionKey) { videoRegionLastGoodSrcCache[regionKey] = requestedSrc; } return '
'; } scheduleVideoSourceProbe(regionKey, requestedSrc, false); if (cachedSrc) { if (cachedSrc !== requestedSrc) { logVideoRegionStatus('Keeping the previous playable video until the new mirrored file finishes transferring.', 'region=' + regionKey + ' old=' + cachedSrc + ' new=' + requestedSrc); } return '
'; } return ''; } if (window.pulsePlayerRegionTypes && typeof window.pulsePlayerRegionTypes.register === 'function') { window.pulsePlayerRegionTypes.register('video', { renderRegion: renderVideoRegion }); }