Der Fortschritt ging beim Schließen verloren
Beim Schließen wurde das Video abgeräumt, und dabei fiel currentTime auf null — bevor die Stopp-Meldung hinausging. Jellyfin bekam "gestoppt bei 0:00" und löschte den Fortschritt. Der Film war zur Hälfte gesehen und stand trotzdem nicht unter "Weiterschauen". Jetzt wird die Stelle getrennt vom Element gehalten und die Meldung gesendet, bevor abgeräumt wird. Nachgemessen: bei 45 Sekunden geschlossen, 45 Sekunden gemeldet. Dazu PlayMethod und CanSeek, ohne die Jellyfin die Meldung keiner Art von Wiedergabe zuordnet, und sofortige Meldung bei Anhalten und Weiterlaufen — wer pausiert und weggeht, hatte sonst bis zur nächsten Zehn-Sekunden-Marke nichts hinterlassen. Und das eingefrorene Bild bei laufendem Ton nach einem Anwendungswechsel: Der Browser hält das Entpacken an, während der Tab verdeckt ist, und hls.js findet danach nicht von selbst in den Puffer zurück. Jetzt wird beim Zurückkommen an derselben Stelle neu angestoßen, mit einem winzigen Sprung — ohne den bleibt das zuletzt gezeigte Bild stehen, obwohl längst wieder Segmente ankommen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
fa8d9de2e9
commit
b51bb16de0
+51
-7
@@ -1754,8 +1754,14 @@ function openPlayer(item) {
|
||||
// --- Schließen ---
|
||||
function close() {
|
||||
removeEventListener('keydown', keys);
|
||||
document.removeEventListener('visibilitychange', wieder);
|
||||
clearTimeout(hideTimer);
|
||||
if (document.fullscreenElement) document.exitFullscreen?.();
|
||||
|
||||
// **Erst melden, dann abräumen.** Andersherum steht die Stelle schon auf
|
||||
// null, wenn die Meldung hinausgeht.
|
||||
lauf.sitzung?.melden?.('/Sessions/Playing/Stopped');
|
||||
|
||||
v.__hls?.destroy(); v.__hls = null;
|
||||
v.pause(); v.removeAttribute('src'); v.load();
|
||||
layer.remove();
|
||||
@@ -1763,6 +1769,23 @@ function openPlayer(item) {
|
||||
// Die Startseite kennt den neuen Fortschritt noch nicht.
|
||||
if (current === 'home') renderHome();
|
||||
}
|
||||
|
||||
/* **Zurück aus dem Hintergrund.**
|
||||
Wer die Anwendung wechselt, kommt zu einem stehenden Bild bei laufendem
|
||||
Ton zurück: der Browser hält das Entpacken an, während der Tab verdeckt
|
||||
ist, und hls.js findet danach nicht von selbst zurück in den Puffer.
|
||||
Ein Anstoß an derselben Stelle setzt das Bild wieder in Gang. */
|
||||
const wieder = () => {
|
||||
if (document.hidden || v.paused) return;
|
||||
const h = v.__hls;
|
||||
if (!h) return;
|
||||
const stelle = v.currentTime;
|
||||
h.startLoad(stelle);
|
||||
// Ein winziger Sprung erzwingt einen neuen Schlüsselbildpunkt. Ohne ihn
|
||||
// bleibt das zuletzt gezeigte Bild stehen, obwohl Segmente ankommen.
|
||||
if (stelle > 0.5) v.currentTime = stelle - 0.1;
|
||||
};
|
||||
document.addEventListener('visibilitychange', wieder);
|
||||
el2('pl-close').onclick = close;
|
||||
|
||||
// Womit gerade gespielt wird — und was die Auswahl hergibt.
|
||||
@@ -1956,7 +1979,8 @@ async function startStream(item, v, fail, lauf) {
|
||||
if (lauf.stelle > 1) v.currentTime = lauf.stelle;
|
||||
v.play();
|
||||
}, { once: true });
|
||||
wireProgress(v, { id: info.PlaySessionId, sourceID: source.Id || item.Id, itemID: item.Id });
|
||||
lauf.sitzung = { id: info.PlaySessionId, sourceID: source.Id || item.Id, itemID: item.Id };
|
||||
wireProgress(v, lauf.sitzung);
|
||||
|
||||
if (v.canPlayType('application/vnd.apple.mpegurl')) { v.src = url; return; }
|
||||
|
||||
@@ -2019,7 +2043,15 @@ async function playbackInfo(item, lauf = {}) {
|
||||
Fortschritt wird nie gespeichert — „Weiterschauen" wäre im Web für immer
|
||||
eine leere Reihe. Alle zehn Sekunden genügt. */
|
||||
function wireProgress(video, session) {
|
||||
const send = (path, extra = {}) => {
|
||||
// **Die zuletzt bekannte Stelle, getrennt vom Element gehalten.**
|
||||
//
|
||||
// Das ist der Kern der Sache: Beim Schließen wird das Video abgeräumt, und
|
||||
// dabei fällt `currentTime` auf null — *bevor* die Stopp-Meldung hinausgeht.
|
||||
// Jellyfin bekam dann „gestoppt bei 0:00" und löschte den Fortschritt. Der
|
||||
// Film war gesehen und stand trotzdem nicht unter „Weiterschauen".
|
||||
session.stelle = 0;
|
||||
|
||||
const send = (path, stelle = session.stelle, extra = {}) => {
|
||||
// Absichtlich ohne await: eine verlorene Meldung kostet ein paar Sekunden
|
||||
// Fortschritt. Dafür mitten im Film einen Fehler zu zeigen wäre die
|
||||
// schlechtere Hälfte des Tauschs.
|
||||
@@ -2028,23 +2060,35 @@ function wireProgress(video, session) {
|
||||
body: JSON.stringify({
|
||||
ItemId: session.itemID, PlaySessionId: session.id,
|
||||
MediaSourceId: session.sourceID,
|
||||
PositionTicks: Math.round(video.currentTime * 10_000_000), ...extra,
|
||||
PositionTicks: Math.round(stelle * 10_000_000),
|
||||
// Jellyfin ordnet die Meldung sonst keiner Art von Wiedergabe zu und
|
||||
// verwirft sie stillschweigend.
|
||||
PlayMethod: 'Transcode', CanSeek: true,
|
||||
...extra,
|
||||
}),
|
||||
}).catch(() => {});
|
||||
};
|
||||
session.melden = send;
|
||||
|
||||
video.addEventListener('playing', () => send('/Sessions/Playing'), { once: true });
|
||||
|
||||
let last = 0;
|
||||
video.addEventListener('timeupdate', () => {
|
||||
if (video.currentTime > 0) session.stelle = video.currentTime;
|
||||
if (video.currentTime - last < 10) return;
|
||||
last = video.currentTime;
|
||||
send('/Sessions/Playing/Progress', { IsPaused: video.paused });
|
||||
send('/Sessions/Playing/Progress', session.stelle, { IsPaused: video.paused });
|
||||
});
|
||||
|
||||
const stop = () => send('/Sessions/Playing/Stopped');
|
||||
video.addEventListener('ended', stop);
|
||||
video.addEventListener('emptied', stop);
|
||||
// Anhalten und Weiterlaufen sofort melden: wer pausiert und weggeht, hat
|
||||
// sonst bis zur nächsten Zehn-Sekunden-Marke nichts hinterlassen.
|
||||
video.addEventListener('pause', () =>
|
||||
send('/Sessions/Playing/Progress', session.stelle, { IsPaused: true }));
|
||||
video.addEventListener('play', () =>
|
||||
send('/Sessions/Playing/Progress', session.stelle, { IsPaused: false }));
|
||||
|
||||
// Am Ende steht die Stelle nicht mehr zur Verfügung — gemeint ist das Ende.
|
||||
video.addEventListener('ended', () => send('/Sessions/Playing/Stopped', video.duration || session.stelle));
|
||||
}
|
||||
|
||||
/* Eine Adresse mit Anmeldung im Anhang.
|
||||
|
||||
Reference in New Issue
Block a user