player element angepasst

This commit is contained in:
2026-09-29 17:28:54 +02:00
parent c52ade3764
commit 63c2198ccb
+104
View File
@@ -726,6 +726,18 @@ td {
audio { audio {
width: 280px; width: 280px;
max-width: 100%; max-width: 100%;
height: 48px;
}
/* Die Positionsleiste der nativen Audio-Steuerung besser bedienbar machen.
Chromium/WebKit erlaubt zusätzlich eine direkte Vergrößerung der Timeline. */
audio::-webkit-media-controls-timeline {
height: 8px;
}
audio::-webkit-media-controls-current-time-display,
audio::-webkit-media-controls-time-remaining-display {
font-size: 13px;
} }
a.button { a.button {
@@ -1010,6 +1022,98 @@ function applyFilters() {
); );
applyFilters(); applyFilters();
// ------------------------------------------------------------
// Wiedergabeposition merken
// ------------------------------------------------------------
// Die Position wird pro Datei und Browser lokal gespeichert.
// Dadurch kann eine Aufnahme später an der zuletzt gehörten Stelle
// fortgesetzt werden, ohne dass dafür ein Server-Login oder eine
// Datenbank notwendig ist.
const PLAYBACK_KEY_PREFIX = 'event-audio-playback:';
const PLAYBACK_SAVE_INTERVAL = 5000;
function playbackKey(audio) {
const source = audio.querySelector('source');
return source
? PLAYBACK_KEY_PREFIX + source.getAttribute('src')
: null;
}
function savePlaybackPosition(audio) {
const key = playbackKey(audio);
if (!key || !Number.isFinite(audio.currentTime) || audio.currentTime <= 0) {
return;
}
try {
localStorage.setItem(key, JSON.stringify({
position: audio.currentTime,
savedAt: Date.now()
}));
} catch (error) {
console.warn('Wiedergabeposition konnte nicht gespeichert werden:', error);
}
}
function restorePlaybackPosition(audio) {
const key = playbackKey(audio);
if (!key) return;
try {
const saved = JSON.parse(localStorage.getItem(key) || 'null');
if (!saved || !Number.isFinite(saved.position) || saved.position <= 0) {
return;
}
// Erst setzen, wenn die Metadaten/Dauer bekannt sind.
if (Number.isFinite(audio.duration) && audio.duration > 0) {
const position = Math.min(saved.position, Math.max(0, audio.duration - 0.5));
if (position > 0) {
audio.currentTime = position;
}
}
} catch (error) {
console.warn('Wiedergabeposition konnte nicht wiederhergestellt werden:', error);
}
}
document.querySelectorAll('.finished-row audio').forEach(audio => {
let lastSaved = 0;
audio.addEventListener('loadedmetadata', () => {
restorePlaybackPosition(audio);
});
audio.addEventListener('timeupdate', () => {
const now = Date.now();
if (now - lastSaved >= PLAYBACK_SAVE_INTERVAL) {
savePlaybackPosition(audio);
lastSaved = now;
}
});
audio.addEventListener('pause', () => {
if (!audio.ended) {
savePlaybackPosition(audio);
lastSaved = Date.now();
}
});
audio.addEventListener('ended', () => {
const key = playbackKey(audio);
if (!key) return;
try {
localStorage.removeItem(key);
} catch (error) {
console.warn('Gespeicherte Wiedergabeposition konnte nicht gelöscht werden:', error);
}
});
});
window.addEventListener('beforeunload', () => {
document.querySelectorAll('.finished-row audio').forEach(savePlaybackPosition);
});
async function updateLiveSection() { async function updateLiveSection() {
try { try {
const response = await fetch("/api/live", { cache: "no-store" }); const response = await fetch("/api/live", { cache: "no-store" });