time_offset = 0; current_content = null; player = null; status = ""; function loadCSS(id, href) { if (!document.getElementById(id)) { var link = document.createElement("link"); link.id = id; link.rel = "stylesheet"; link.type = "text/css"; link.href = href; link.media = "all"; document.head.appendChild(link); } } function loadJS(id, src, callback) { if (!document.getElementById(id)) { var script = document.createElement("script"); script.id = id; script.src = src; script.onload = callback; document.head.appendChild(script); } else if (callback) { callback(); } } function createVideoElement(station) { let video = document.createElement("video"); video.id = "liveembedvid"; video.className = "video-js vjs-default-skin"; video.controls = true; // keep this true to enable custom control bar //video.poster = `/${station}/liveposter`; video.preload = "auto"; // Preload the video // Fit to container // Customize control bar video.setAttribute( "data-setup", JSON.stringify({ controlBar: { playToggle: false, currentTimeDisplay: false, timeDivider: false, durationDisplay: false, remainingTimeDisplay: false, progressControl: false, liveDisplay: false, captionsButton: false, subtitlesButton: false, audioTrackButton: false, playbackRateMenuButton: false, chaptersButton: false, descriptionsButton: false, customControlSpacer: false, volumePanel: true, // Enable volume control fullscreenToggle: true, // Enable full-screen toggle loadingSpinner: false, children: { loadingSpinner: false, }, }, }) ); // Initial placeholder source to avoid source error // let source = document.createElement("source"); // video.appendChild(source); return video; } async function updateStreamURL(player, station) { try { const response = await fetch(`https://admin.satellitetvfeed.net/CurrentStreamURL?station=${station}`); if (!response.ok) { player.pause(); player.currentTime(0); player.src(""); showComingSoonPoster(station); return; } const newUrl = await response.json(); serverTime = newUrl.serverTime; if (newUrl.currentVideo.url !== player.src() || player.error_ !== null) { const new_src = { src: newUrl.currentVideo.url, type: newUrl.currentVideo.url.endsWith(".m3u8") ? "application/x-mpegURL" : "video/mp4", }; current_content = newUrl; player.src(new_src); if (newUrl.currentTimeInVideo && newUrl.currentTimeInVideo > 10) { player.currentTime(newUrl.currentTimeInVideo); } if (newUrl.currentVideo.url.endsWith(".mp4")) { player.load(); } player.play(); } } catch (error) { console.error("Fetch error:", error); } } // Function to set up the video player function setupVideoPlayer(station) { loadCSS("vjscss", "//vjs.zencdn.net/7.10.2/video-js.min.css"); loadCSS("livecss", "https://admin.satellitetvfeed.net/css/live.css"); loadJS("vjsscript", "//vjs.zencdn.net/7.10.2/video.min.js", async () => { let video = createVideoElement(station); document.getElementById("liveembedcont").appendChild(video); showPoster(station); player = videojs("liveembedvid"); player.on("ended", function () { console.log("Video ended. Updating stream..."); player.controls(false); updateStreamURL(player, station); }); player.on("timeupdate", async (timeUpdate) => { handleTimeUpdate(timeUpdate); }); player.on("waiting", function () {}); player.on("seeked", function () { }); // on("pause", function () { // showPoster(station); // }); player.on("playing", function () { hidePoster(); player.controls(true); document; }); // Hide vjs poster and spinner let spinner = document.getElementsByClassName("vjs-loading-spinner")[0]; let poster = document.getElementsByClassName("vjs-poster")[0]; spinner.style.display = "none"; poster.style.display = "none"; if (window.location.href.indexOf("autoplay=false") === -1) { updateStreamURL(player, station); } setInterval(() => updateStreamURL(player, station), 10000); }); } function createOverlay() { let overlay = document.getElementById("black-overlay"); if (!overlay) { overlay = document.createElement("div"); overlay.id = "black-overlay"; overlay.style.position = "absolute"; overlay.style.top = 0; overlay.style.left = 0; overlay.style.width = "100%"; overlay.style.height = "100%"; overlay.style.backgroundColor = "black"; overlay.style.zIndex = 1; document.getElementById("liveembedvid").appendChild(overlay); } return overlay; } function handleFadeIn(overlay, player) { let time_left = player.duration() - player.currentTime(); // Ensure video duration is at least 30 seconds before applying fade-in if (player.duration() >= 30) { if (time_left < 1) { overlay.style.display = "block"; overlay.style.opacity = 1 - time_left / 1; } else { overlay.style.opacity = 0; overlay.style.display = "none"; } } else { overlay.style.opacity = 0; overlay.style.display = "none"; // Keep overlay hidden for videos under 30 seconds } } function showPoster(station) { let poster = document.createElement("div"); poster.id = "liveposter"; poster.style.position = "absolute"; poster.style.top = 0; poster.style.left = 0; poster.style.width = "100%"; poster.style.height = "100%"; poster.style.zIndex = 1; poster.style.backgroundImage = `url("https://admin.satellitetvfeed.net/${station}/liveposter")`; poster.style.backgroundSize = "cover"; // or '100% 100%' to stretch without maintaining aspect ratio poster.onclick = function () { status = "playing"; player.play(); hidePoster(); }; // Create the play button let playButton = document.createElement("div"); playButton.className = "vjs-icon-play"; playButton.style.position = "absolute"; playButton.style.top = "50%"; playButton.style.left = "50%"; playButton.style.fontSize = "50px"; playButton.style.transform = "translate(-50%, -50%)"; playButton.style.color = "white"; playButton.style.cursor = "pointer"; // Append the play button to the poster poster.appendChild(playButton); document.getElementById("liveembedcont").appendChild(poster); return poster; } function showComingSoonPoster(station) { const poster = document.createElement("div"); Object.assign(poster.style, { position: "absolute", top: 0, left: 0, width: "100%", height: "100%", zIndex: 1, backgroundImage: `url("https://admin.satellitetvfeed.net/${station}/liveposter")`, backgroundSize: "cover", display: "flex", justifyContent: "center", alignItems: "center", }); const comingSoonText = document.createElement("div"); Object.assign(comingSoonText.style, { color: "#FFFFFF", fontSize: "2em", // Increased font size fontFamily: "'Helvetica Neue', Helvetica, Arial, sans-serif", // Modern font textShadow: "2px 2px 4px rgba(0,0,0,0.5)", // Subtle text shadow for depth padding: "20px 40px", background: "rgba(255, 255, 255, 0.2)", // Vibrant background borderRadius: "15px", border: "2px solid #FFFFFF", // Subtle border backdropFilter: "blur(5px)", // Blur effect for the background }); comingSoonText.innerText = "We'll be back soon"; poster.id = "liveposter"; poster.appendChild(comingSoonText); document.getElementById("liveembedcont").appendChild(poster); return poster; } function hidePoster() { poster = document.getElementById("liveposter") if (poster) { parent = poster.parentElement; parent.removeChild(poster); } } function calculateTimeOffset(current_content, player) { let time_since_content = current_content.serverTime - Date.now() / 1000; let server_position = current_content.currentTimeInVideo - time_since_content; let offset = player.currentTime() - server_position; return offset; } function adjustPlaybackSpeed(player, offset) { let time_left = player.duration() - player.currentTime(); let time_since_content = Date.now() / 1000 - current_content.serverTime; let max_speed = 1.2; // Ensure video duration is at least 60 seconds before adjusting playback speed if (player.duration() >= 60) { if (offset < 0 && time_left > 0) { if (offset < -10) { player.currentTime( current_content.currentTimeInVideo + time_since_content ); } let playback_speed = Math.min(1 + (offset / 20) * -1, max_speed); player.playbackRate(playback_speed); } else { player.playbackRate(1); // Assuming default speed is 1 } } else { player.playbackRate(1); // Reset to default speed if video is less than a minute long } } // function endVideoEarly(player, current_content) { // let serverVideoDuration = current_content.currentVideo.duration; // Ensure the same time units as player.currentTime() // let clientCurrentTime = player.currentTime(); // let time_since_content = current_content.serverTime - Date.now() / 1000; // let serverCurrentTime = // current_content.currentTimeInVideo - time_since_content; // let serverTimeLeft = serverVideoDuration - serverCurrentTime; // if (serverTimeLeft <= 0 && clientCurrentTime < serverVideoDuration) { // console.log( // "Server video has ended, but client video is still playing. Ending client video early." // ); // player.currentTime(serverVideoDuration); // Move to the end of the video // } // } function handleTimeUpdate(timeUpdate) { let overlay = createOverlay(); handleFadeIn(overlay, player); if (current_content) { let offset = calculateTimeOffset(current_content, player); adjustPlaybackSpeed(player, offset); //endVideoEarly(player, current_content); } } // Call this function with the desired station setupVideoPlayer("hmongusatv");