|
|
|
|
@@ -1,4 +1,4 @@
|
|
|
|
|
/*
|
|
|
|
|
/*
|
|
|
|
|
* Jellyfin Slideshow by M0RPH3US v4.0.1
|
|
|
|
|
* Modified by CodeDevMLH
|
|
|
|
|
*
|
|
|
|
|
@@ -67,6 +67,8 @@ const CONFIG = {
|
|
|
|
|
customOverlayPositionX: 0,
|
|
|
|
|
customOverlayPositionY: 0,
|
|
|
|
|
customOverlayScale: 100,
|
|
|
|
|
backdropVideoDelay: 0,
|
|
|
|
|
constrainPlotWidth: false,
|
|
|
|
|
enableCustomMediaIds: true,
|
|
|
|
|
enableSeasonalContent: false,
|
|
|
|
|
customMediaIds: "",
|
|
|
|
|
@@ -110,6 +112,7 @@ const STATE = {
|
|
|
|
|
customTrailerUrls: {},
|
|
|
|
|
ytPromise: null,
|
|
|
|
|
autoplayTimeouts: [],
|
|
|
|
|
playSignals: {},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@@ -396,6 +399,7 @@ const resetSlideshowState = () => {
|
|
|
|
|
STATE.slideshow.customTrailerUrls = {};
|
|
|
|
|
STATE.slideshow.totalItems = 0;
|
|
|
|
|
STATE.slideshow.isLoading = false;
|
|
|
|
|
STATE.slideshow.playSignals = {};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -1802,7 +1806,7 @@ const SlideCreator = {
|
|
|
|
|
// Create an iframe upfront
|
|
|
|
|
const ytPlayerIframe = SlideUtils.createElement("iframe", {
|
|
|
|
|
id: `youtube-player-${itemId}`,
|
|
|
|
|
src: `https://www.youtube-nocookie.com/embed/${videoId}?enablejsapi=1&origin=${encodeURIComponent(window.location.origin)}`,
|
|
|
|
|
src: `https://www.youtube-nocookie.com/embed/${videoId}?enablejsapi=1&autoplay=0&controls=0&playsinline=1&mute=${STATE.slideshow.isMuted ? 1 : 0}&origin=${encodeURIComponent(window.location.origin)}`,
|
|
|
|
|
style: "width: 100%; height: 100%; border: none;",
|
|
|
|
|
allow: "autoplay; encrypted-media",
|
|
|
|
|
referrerpolicy: "strict-origin-when-cross-origin",
|
|
|
|
|
@@ -1877,11 +1881,11 @@ const SlideCreator = {
|
|
|
|
|
event.target.setPlaybackQuality(quality);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Only play if this is the active slide
|
|
|
|
|
// Only play if this is the active slide and the play signal has been issued (delay finished)
|
|
|
|
|
const slide = document.querySelector(`.slide[data-item-id="${itemId}"]`);
|
|
|
|
|
const isVideoPlayerOpen = document.querySelector('.videoPlayerContainer') || document.querySelector('.youtubePlayerContainer');
|
|
|
|
|
|
|
|
|
|
if (slide && slide.classList.contains('active') && !document.hidden && (!isVideoPlayerOpen || isVideoPlayerOpen.classList.contains('hide'))) {
|
|
|
|
|
if (slide && slide.classList.contains('active') && STATE.slideshow.playSignals[itemId] === true && !document.hidden && (!isVideoPlayerOpen || isVideoPlayerOpen.classList.contains('hide'))) {
|
|
|
|
|
event.target.playVideo();
|
|
|
|
|
|
|
|
|
|
// Check if it actually started playing after a short delay (handling autoplay blocks)
|
|
|
|
|
@@ -2479,6 +2483,7 @@ const SlideshowManager = {
|
|
|
|
|
|
|
|
|
|
void currentSlide.offsetWidth;
|
|
|
|
|
currentSlide.classList.add("active");
|
|
|
|
|
STATE.slideshow.playSignals[currentItemId] = false;
|
|
|
|
|
|
|
|
|
|
// Manage Video Playback: Stop others, Play current
|
|
|
|
|
// 1. Stop all other YouTube players and local video elements, release connections
|
|
|
|
|
@@ -2579,34 +2584,42 @@ const SlideshowManager = {
|
|
|
|
|
// play logic
|
|
|
|
|
const playVideoLogic = () => {
|
|
|
|
|
if (!currentSlide.classList.contains('active')) return;
|
|
|
|
|
|
|
|
|
|
STATE.slideshow.playSignals[currentItemId] = true;
|
|
|
|
|
|
|
|
|
|
if (videoBackdrop.tagName === 'VIDEO') {
|
|
|
|
|
videoBackdrop.play().catch(e => {
|
|
|
|
|
// Check if it actually started playing after a short delay (handling autoplay blocks)
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
if (videoBackdrop.paused && currentSlide.classList.contains('active')) {
|
|
|
|
|
console.warn("🎬 Media Bar:", `Autoplay blocked for ${currentItemId}, attempting muted fallback`);
|
|
|
|
|
videoBackdrop.muted = true;
|
|
|
|
|
videoBackdrop.play().catch(err => console.error("🎬 Media Bar:", "Muted fallback failed", err));
|
|
|
|
|
}
|
|
|
|
|
}, 1000);
|
|
|
|
|
if (!STATE.slideshow.isMuted) {
|
|
|
|
|
// Check if it actually started playing after a short delay (handling autoplay blocks)
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
if (videoBackdrop.paused && currentSlide.classList.contains('active')) {
|
|
|
|
|
console.warn("🎬 Media Bar:", `Autoplay blocked for ${currentItemId}, attempting muted fallback`);
|
|
|
|
|
videoBackdrop.muted = true;
|
|
|
|
|
videoBackdrop.play().catch(err => console.error("🎬 Media Bar:", "Muted fallback failed", err));
|
|
|
|
|
}
|
|
|
|
|
}, 1000);
|
|
|
|
|
} else {
|
|
|
|
|
console.error("🎬 Media Bar:", "Playback failed despite being muted", e);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else if (STATE.slideshow.videoPlayers && STATE.slideshow.videoPlayers[currentItemId]) {
|
|
|
|
|
const player = STATE.slideshow.videoPlayers[currentItemId];
|
|
|
|
|
if (player && typeof player.playVideo === 'function') {
|
|
|
|
|
player.playVideo();
|
|
|
|
|
|
|
|
|
|
// Check if playback successfully started, otherwise fallback to muted
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
if (!currentSlide.classList.contains('active')) return;
|
|
|
|
|
if (player.getPlayerState &&
|
|
|
|
|
player.getPlayerState() !== YT.PlayerState.PLAYING &&
|
|
|
|
|
player.getPlayerState() !== YT.PlayerState.BUFFERING) {
|
|
|
|
|
console.log("🎬 Media Bar:", "YouTube didn't start playback, retrying muted...");
|
|
|
|
|
player.mute();
|
|
|
|
|
player.playVideo();
|
|
|
|
|
}
|
|
|
|
|
}, 1000);
|
|
|
|
|
if (!STATE.slideshow.isMuted) {
|
|
|
|
|
// Check if playback successfully started, otherwise fallback to muted
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
if (!currentSlide.classList.contains('active')) return;
|
|
|
|
|
if (player.getPlayerState &&
|
|
|
|
|
player.getPlayerState() !== YT.PlayerState.PLAYING &&
|
|
|
|
|
player.getPlayerState() !== YT.PlayerState.BUFFERING) {
|
|
|
|
|
console.log("🎬 Media Bar:", "YouTube didn't start playback, retrying muted...");
|
|
|
|
|
player.mute();
|
|
|
|
|
player.playVideo();
|
|
|
|
|
}
|
|
|
|
|
}, 1000);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|