From 77e74a5994b59bb7fd7f81bb9c0a83b281aff631 Mon Sep 17 00:00:00 2001 From: Andre <200930841+Andre-Bzk@users.noreply.github.com> Date: Sun, 12 Apr 2026 08:35:18 +0200 Subject: [PATCH] Fix: Seeking optimiert? --- src/main/playback/mpvController.ts | 18 ++++++++++++++++++ src/main/playback/playbackService.ts | 13 +++++++++++-- src/main/playback/streamlink.ts | 6 +----- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/main/playback/mpvController.ts b/src/main/playback/mpvController.ts index 2d09046..8548128 100644 --- a/src/main/playback/mpvController.ts +++ b/src/main/playback/mpvController.ts @@ -15,6 +15,7 @@ export class MpvController { private nextRequestId = 1 private pendingRequests = new Map void>() private propertyObservers = new Map void>>() + private eventObservers = new Map void>>() constructor(private ipcPath: string) {} @@ -61,6 +62,15 @@ export class MpvController { }) } + onEvent(eventName: string, cb: () => void): void { + let observers = this.eventObservers.get(eventName) + if (!observers) { + observers = new Set() + this.eventObservers.set(eventName, observers) + } + observers.add(cb) + } + seek(seconds: number): void { if (this.socket?.writable) { this._send({ command: ['seek', seconds, 'relative'] }) @@ -107,6 +117,7 @@ export class MpvController { this.buf = '' this.pendingRequests.clear() this.propertyObservers.clear() + this.eventObservers.clear() } private _send(msg: object): void { @@ -152,6 +163,13 @@ export class MpvController { for (const observer of observers) observer(msg.data) } } + + if (typeof msg.event === 'string') { + const observers = this.eventObservers.get(msg.event) + if (observers) { + for (const observer of observers) observer() + } + } } catch { /* ignore malformed lines */ } diff --git a/src/main/playback/playbackService.ts b/src/main/playback/playbackService.ts index 1d0466b..f26510f 100644 --- a/src/main/playback/playbackService.ts +++ b/src/main/playback/playbackService.ts @@ -90,7 +90,7 @@ export class PlaybackService extends EventEmitter { } const effectiveStart = startSeconds !== undefined ? startSeconds : resumePos - const proc = spawnMpv(hlsUrl, { ipcPath: this.ipcPath, startSeconds: effectiveStart }) + const proc = spawnMpv(hlsUrl, { ipcPath: this.ipcPath }) let mpvStderrBuf = '' proc.stdout?.on('data', (d: Buffer) => console.log('[mpv]', d.toString().trim())) @@ -125,8 +125,17 @@ export class PlaybackService extends EventEmitter { this.current = { process: proc, mpv } this.emit('playback-event', { kind: 'started' } satisfies PlaybackEvent) - // IPC verbinden und Position tracken + // IPC verbinden, initialen Resume-Seek erst nach `file-loaded` setzen und Position tracken. + // HLS-VODs reagieren auf Linux/Steam Deck robuster auf einen Seek nach dem Laden + // als auf `mpv --start=`. mpv.connect().then(() => { + let initialSeekDone = effectiveStart <= 0 + mpv.onEvent('file-loaded', () => { + if (initialSeekDone) return + initialSeekDone = true + mpv.seekAbsolute(effectiveStart) + }) + let lastWrite = 0 mpv.observeTimePos((seconds) => { const now = Date.now() diff --git a/src/main/playback/streamlink.ts b/src/main/playback/streamlink.ts index 8527b16..9bde15b 100644 --- a/src/main/playback/streamlink.ts +++ b/src/main/playback/streamlink.ts @@ -70,11 +70,10 @@ export function getStreamUrl(url: string, quality: string): Promise { export interface MpvOptions { ipcPath: string - startSeconds?: number } /** Startet mpv direkt mit einer URL (HLS oder lokal). IPC-Socket wird gesetzt. */ -export function spawnMpv(url: string, { ipcPath, startSeconds }: MpvOptions): ChildProcess { +export function spawnMpv(url: string, { ipcPath }: MpvOptions): ChildProcess { const args = [ url, `--input-ipc-server=${ipcPath}`, @@ -83,8 +82,5 @@ export function spawnMpv(url: string, { ipcPath, startSeconds }: MpvOptions): Ch '--hwdec=auto', '--force-window=yes' ] - if (startSeconds && startSeconds > 0) { - args.push(`--start=${startSeconds}`) - } return spawn(MPV_BIN, args, { stdio: ['ignore', 'pipe', 'pipe'] }) }