Update public/script.js
Browse files- public/script.js +15 -21
public/script.js
CHANGED
|
@@ -4,11 +4,9 @@ const videoPlayer = document.getElementById("tvPlayer");
|
|
| 4 |
videoPlayer.setAttribute("webkit-playsinline", "true");
|
| 5 |
videoPlayer.setAttribute("playsinline", "true");
|
| 6 |
|
| 7 |
-
// Store and restore last viewed channel
|
| 8 |
const LAST_CHANNEL_KEY = "last_selected_channel";
|
| 9 |
let currentChannel = null;
|
| 10 |
|
| 11 |
-
// Fetch and display available channels dynamically
|
| 12 |
async function fetchChannels() {
|
| 13 |
try {
|
| 14 |
const response = await fetch("/channels");
|
|
@@ -31,7 +29,6 @@ async function fetchChannels() {
|
|
| 31 |
channelButtons.appendChild(button);
|
| 32 |
});
|
| 33 |
|
| 34 |
-
// Restore last watched channel or auto-select the first one
|
| 35 |
const lastChannel = localStorage.getItem(LAST_CHANNEL_KEY);
|
| 36 |
const initialChannel = data.channels.includes(lastChannel) ? lastChannel : data.channels[0];
|
| 37 |
changeChannel(initialChannel);
|
|
@@ -41,9 +38,8 @@ async function fetchChannels() {
|
|
| 41 |
}
|
| 42 |
}
|
| 43 |
|
| 44 |
-
// Function to switch channel and stream from backend
|
| 45 |
async function changeChannel(channel) {
|
| 46 |
-
if (currentChannel === channel) return;
|
| 47 |
currentChannel = channel;
|
| 48 |
|
| 49 |
document.getElementById("channelName").textContent = `Channel ${channel}`;
|
|
@@ -51,7 +47,6 @@ async function changeChannel(channel) {
|
|
| 51 |
|
| 52 |
const streamUrl = `/hls/${channel}/index.m3u8`;
|
| 53 |
|
| 54 |
-
// Fetch correct timestamp from backend
|
| 55 |
let seekTime = 0;
|
| 56 |
try {
|
| 57 |
const response = await fetch(`/timestamp?channel=${channel}`);
|
|
@@ -62,7 +57,6 @@ async function changeChannel(channel) {
|
|
| 62 |
}
|
| 63 |
|
| 64 |
if (seekTime < 0 || isNaN(seekTime)) seekTime = 0;
|
| 65 |
-
|
| 66 |
localStorage.setItem(LAST_CHANNEL_KEY, channel);
|
| 67 |
|
| 68 |
if (Hls.isSupported()) {
|
|
@@ -71,10 +65,10 @@ async function changeChannel(channel) {
|
|
| 71 |
}
|
| 72 |
|
| 73 |
const hls = new Hls({
|
| 74 |
-
maxBufferLength:
|
| 75 |
-
maxMaxBufferLength:
|
| 76 |
-
maxBufferSize:
|
| 77 |
-
liveSyncDurationCount:
|
| 78 |
});
|
| 79 |
|
| 80 |
hls.loadSource(streamUrl);
|
|
@@ -85,8 +79,8 @@ async function changeChannel(channel) {
|
|
| 85 |
videoPlayer.play().catch(err => console.error("Playback error:", err));
|
| 86 |
});
|
| 87 |
|
| 88 |
-
hls.on(Hls.Events.
|
| 89 |
-
if (seekTime >
|
| 90 |
console.log("Seeking to:", seekTime);
|
| 91 |
videoPlayer.currentTime = seekTime;
|
| 92 |
}
|
|
@@ -106,25 +100,27 @@ async function changeChannel(channel) {
|
|
| 106 |
hls.recoverMediaError();
|
| 107 |
break;
|
| 108 |
default:
|
| 109 |
-
console.error("Critical error,
|
| 110 |
hls.destroy();
|
| 111 |
-
setTimeout(() => changeChannel(channel), 5000);
|
| 112 |
break;
|
| 113 |
}
|
| 114 |
}
|
| 115 |
});
|
| 116 |
|
| 117 |
-
// Handle stall recovery properly
|
| 118 |
videoPlayer.addEventListener("waiting", () => {
|
| 119 |
-
|
| 120 |
-
|
|
|
|
|
|
|
| 121 |
});
|
| 122 |
|
| 123 |
document.getElementById("currentShow").textContent = `Now Playing: Channel ${channel}`;
|
| 124 |
} else if (videoPlayer.canPlayType("application/vnd.apple.mpegurl")) {
|
| 125 |
videoPlayer.src = streamUrl;
|
| 126 |
videoPlayer.addEventListener("loadedmetadata", () => {
|
| 127 |
-
videoPlayer.currentTime
|
|
|
|
|
|
|
| 128 |
videoPlayer.play().catch(err => console.error("Playback error:", err));
|
| 129 |
});
|
| 130 |
|
|
@@ -132,7 +128,6 @@ async function changeChannel(channel) {
|
|
| 132 |
}
|
| 133 |
}
|
| 134 |
|
| 135 |
-
// Controls
|
| 136 |
function togglePlay() {
|
| 137 |
if (videoPlayer.paused) {
|
| 138 |
videoPlayer.play();
|
|
@@ -157,5 +152,4 @@ function toggleFullscreen() {
|
|
| 157 |
}
|
| 158 |
}
|
| 159 |
|
| 160 |
-
// Load channels on page load
|
| 161 |
window.onload = fetchChannels;
|
|
|
|
| 4 |
videoPlayer.setAttribute("webkit-playsinline", "true");
|
| 5 |
videoPlayer.setAttribute("playsinline", "true");
|
| 6 |
|
|
|
|
| 7 |
const LAST_CHANNEL_KEY = "last_selected_channel";
|
| 8 |
let currentChannel = null;
|
| 9 |
|
|
|
|
| 10 |
async function fetchChannels() {
|
| 11 |
try {
|
| 12 |
const response = await fetch("/channels");
|
|
|
|
| 29 |
channelButtons.appendChild(button);
|
| 30 |
});
|
| 31 |
|
|
|
|
| 32 |
const lastChannel = localStorage.getItem(LAST_CHANNEL_KEY);
|
| 33 |
const initialChannel = data.channels.includes(lastChannel) ? lastChannel : data.channels[0];
|
| 34 |
changeChannel(initialChannel);
|
|
|
|
| 38 |
}
|
| 39 |
}
|
| 40 |
|
|
|
|
| 41 |
async function changeChannel(channel) {
|
| 42 |
+
if (currentChannel === channel) return;
|
| 43 |
currentChannel = channel;
|
| 44 |
|
| 45 |
document.getElementById("channelName").textContent = `Channel ${channel}`;
|
|
|
|
| 47 |
|
| 48 |
const streamUrl = `/hls/${channel}/index.m3u8`;
|
| 49 |
|
|
|
|
| 50 |
let seekTime = 0;
|
| 51 |
try {
|
| 52 |
const response = await fetch(`/timestamp?channel=${channel}`);
|
|
|
|
| 57 |
}
|
| 58 |
|
| 59 |
if (seekTime < 0 || isNaN(seekTime)) seekTime = 0;
|
|
|
|
| 60 |
localStorage.setItem(LAST_CHANNEL_KEY, channel);
|
| 61 |
|
| 62 |
if (Hls.isSupported()) {
|
|
|
|
| 65 |
}
|
| 66 |
|
| 67 |
const hls = new Hls({
|
| 68 |
+
maxBufferLength: 30,
|
| 69 |
+
maxMaxBufferLength: 90,
|
| 70 |
+
maxBufferSize: 100 * 1000 * 1000,
|
| 71 |
+
liveSyncDurationCount: 2
|
| 72 |
});
|
| 73 |
|
| 74 |
hls.loadSource(streamUrl);
|
|
|
|
| 79 |
videoPlayer.play().catch(err => console.error("Playback error:", err));
|
| 80 |
});
|
| 81 |
|
| 82 |
+
hls.on(Hls.Events.BUFFER_APPENDED, () => {
|
| 83 |
+
if (Math.abs(videoPlayer.currentTime - seekTime) > 1) {
|
| 84 |
console.log("Seeking to:", seekTime);
|
| 85 |
videoPlayer.currentTime = seekTime;
|
| 86 |
}
|
|
|
|
| 100 |
hls.recoverMediaError();
|
| 101 |
break;
|
| 102 |
default:
|
| 103 |
+
console.error("Critical error, destroying stream...");
|
| 104 |
hls.destroy();
|
|
|
|
| 105 |
break;
|
| 106 |
}
|
| 107 |
}
|
| 108 |
});
|
| 109 |
|
|
|
|
| 110 |
videoPlayer.addEventListener("waiting", () => {
|
| 111 |
+
if (videoPlayer.readyState < 2) {
|
| 112 |
+
console.warn("Video stalled, attempting recovery...");
|
| 113 |
+
hls.recoverMediaError();
|
| 114 |
+
}
|
| 115 |
});
|
| 116 |
|
| 117 |
document.getElementById("currentShow").textContent = `Now Playing: Channel ${channel}`;
|
| 118 |
} else if (videoPlayer.canPlayType("application/vnd.apple.mpegurl")) {
|
| 119 |
videoPlayer.src = streamUrl;
|
| 120 |
videoPlayer.addEventListener("loadedmetadata", () => {
|
| 121 |
+
if (Math.abs(videoPlayer.currentTime - seekTime) > 1) {
|
| 122 |
+
videoPlayer.currentTime = seekTime;
|
| 123 |
+
}
|
| 124 |
videoPlayer.play().catch(err => console.error("Playback error:", err));
|
| 125 |
});
|
| 126 |
|
|
|
|
| 128 |
}
|
| 129 |
}
|
| 130 |
|
|
|
|
| 131 |
function togglePlay() {
|
| 132 |
if (videoPlayer.paused) {
|
| 133 |
videoPlayer.play();
|
|
|
|
| 152 |
}
|
| 153 |
}
|
| 154 |
|
|
|
|
| 155 |
window.onload = fetchChannels;
|