Version 2.0.0

This commit is contained in:
Erik Thiele
2026-04-22 20:26:00 +02:00
parent 6faf207246
commit 5ac9dee8fc
10 changed files with 398 additions and 119 deletions

182
templates/player.html Normal file → Executable file
View File

@@ -1,82 +1,158 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>CANCOM Simple Signage Player</title>
<meta charset="utf-8">
<title>CANCOM Simple Signage Player</title>
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}">
<style>
html, body {
margin: 0;
padding: 0;
background: black;
width: 100%;
height: 100%;
overflow: hidden;
}
<style>
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: black;
overflow: hidden;
}
#image, #video {
position: fixed;
inset: 0;
width: 100vw;
height: 100vh;
object-fit: contain;
background: black;
}
</style>
img, video {
width: 100vw;
height: 100vh;
object-fit: contain;
background: black;
display: none;
}
</style>
</head>
<body>
<img id="image" hidden>
<video id="video" hidden muted autoplay playsinline></video>
<img id="image">
<video id="video" muted autoplay playsinline></video>
<script>
const files = {{ files | tojson }};
const interval = {{ interval }} * 1000;
const screen = "{{ screen }}";
/* -----------------------------
Daten vom Server
----------------------------- */
const normalFiles = {{ normal_files | tojson }};
const prioFiles = {{ prio_files | tojson }};
const interval = {{ interval }} * 1000;
const screen = "{{ screen }}";
/* -----------------------------
Player State
----------------------------- */
let normalIndex = 0;
let prioIndex = 0;
let playPrioNext = false;
let mode = "normal"; // "normal" oder "prio"
let index = 0;
let lastHash = null;
const img = document.getElementById("image");
const video = document.getElementById("video");
const vid = document.getElementById("video");
function isVideo(name) {
return name.toLowerCase().endsWith(".mp4");
/* -----------------------------
Hilfsfunktionen
----------------------------- */
function isVideo(file) {
return file.toLowerCase().endsWith(".mp4");
}
function showNext() {
if (files.length === 0) return;
const file = files[index];
index = (index + 1) % files.length;
function getNextItem() {
if (isVideo(file)) {
img.hidden = true;
video.hidden = false;
video.src = `/media/${screen}/${file}`;
video.load();
video.play();
// ✅ Sonderfall: nur Priority vorhanden
if (normalFiles.length === 0 && prioFiles.length > 0) {
return {
file: prioFiles[prioIndex++ % prioFiles.length],
isPrio: true
};
}
// ✅ Sonderfall: nur normale Playlist vorhanden
if (prioFiles.length === 0 && normalFiles.length > 0) {
return {
file: normalFiles[normalIndex++ % normalFiles.length],
isPrio: false
};
}
// ✅ Normal-Phase
if (mode === "normal") {
const file = normalFiles[normalIndex++];
if (normalIndex >= normalFiles.length) {
normalIndex = 0;
if (prioFiles.length > 0) {
mode = "prio"; // ➜ nach kompletter Normal-Playlist wechseln
}
}
return { file, isPrio: false };
}
// ✅ Priority-Phase
if (mode === "prio") {
const file = prioFiles[prioIndex++];
if (prioIndex >= prioFiles.length) {
prioIndex = 0;
mode = "normal"; // ➜ nach kompletter Priority zurück
}
return { file, isPrio: true };
}
return null;
}
/* -----------------------------
Medien abspielen
----------------------------- */
function playNext() {
const item = getNextItem();
if (!item) return;
const basePath = item.isPrio ? "priority" : screen;
const src = `/media/${basePath}/${item.file}`;
if (isVideo(item.file)) {
img.style.display = "none";
vid.style.display = "block";
vid.src = src;
vid.onended = playNext;
vid.play();
} else {
video.pause();
video.hidden = true;
img.hidden = false;
img.src = `/media/${screen}/${file}`;
setTimeout(showNext, interval);
vid.pause();
vid.style.display = "none";
img.style.display = "block";
img.src = src;
setTimeout(playNext, interval);
}
}
video.addEventListener("ended", showNext);
/* -----------------------------
Auto-Reload bei Änderungen
----------------------------- */
let lastHash = null;
async function checkForUpdate() {
const r = await fetch(`/playlist/${screen}/hash`, { cache: "no-store" });
const hash = await r.text();
if (lastHash && hash !== lastHash) location.reload();
lastHash = hash;
async function checkForUpdates() {
try {
const res = await fetch(`/playlist/${screen}/hash`, { cache: "no-store" });
const hash = await res.text();
if (lastHash && lastHash !== hash) {
location.reload();
}
lastHash = hash;
} catch (e) {
console.warn("Playlist-Check fehlgeschlagen", e);
}
}
setInterval(checkForUpdate, 5000);
showNext();
/* -----------------------------
Start
----------------------------- */
playNext();
setInterval(checkForUpdates, 5000);
</script>
</body>