Phase 4 abgeschlossen

- VOD Historie in Channelscreen implementiert
- VOD-Wiedergabe + Stop-Verhalten verifiziert
This commit is contained in:
Andre
2026-04-08 17:49:30 +02:00
parent 3e8e5c2078
commit ed1f710866
10 changed files with 390 additions and 28 deletions
+45 -1
View File
@@ -23,7 +23,7 @@ export class PlaybackService extends EventEmitter {
}
const sl = spawnStreamlink({
channelLogin,
url: `twitch.tv/${channelLogin}`,
quality,
mpvIpcPath: this.ipcPath
})
@@ -65,6 +65,50 @@ export class PlaybackService extends EventEmitter {
mpv.connect().catch(() => {})
}
async startVod(vodId: string, startSeconds = 0): Promise<void> {
if (this.current) {
await this.stop()
}
const sl = spawnStreamlink({
url: `https://www.twitch.tv/videos/${vodId}`,
quality: 'best',
mpvIpcPath: this.ipcPath,
startSeconds
})
sl.stdout?.on('data', (d: Buffer) => {
console.log('[streamlink stdout]', d.toString().trim())
})
sl.stderr?.on('data', (d: Buffer) => {
console.log('[streamlink stderr]', d.toString().trim())
})
sl.on('error', (e: Error) => {
console.error('[streamlink] spawn error:', e)
if (this.current?.streamlink === sl) this.current = null
this.emit('playback-event', {
kind: 'error',
message: `streamlink Fehler: ${e.message}`
} satisfies PlaybackEvent)
})
sl.on('exit', (code) => {
if (this.current?.streamlink === sl) this.current = null
if (code !== 0 && code !== null) {
console.warn('[streamlink] exit code', code)
}
this.emit('playback-event', { kind: 'stopped' } satisfies PlaybackEvent)
})
const mpv = new MpvController(this.ipcPath)
this.current = { channelLogin: vodId, streamlink: sl, mpv }
this.emit('playback-event', { kind: 'started' } satisfies PlaybackEvent)
mpv.connect().catch(() => {})
}
async stop(): Promise<void> {
if (!this.current) return
const { streamlink: sl, mpv } = this.current
+10 -5
View File
@@ -34,25 +34,30 @@ const STREAMLINK_BIN = resolveStreamlinkBin()
const MPV_BIN = resolveMpvBin()
export interface StreamlinkOptions {
channelLogin: string
url: string
quality: string
mpvIpcPath: string
startSeconds?: number
}
export function spawnStreamlink({
channelLogin,
url,
quality,
mpvIpcPath
mpvIpcPath,
startSeconds
}: StreamlinkOptions): ChildProcess {
const hwdec = process.platform === 'win32' ? 'auto' : 'vaapi'
const playerArgs = `--input-ipc-server=${mpvIpcPath} --fullscreen --hwdec=${hwdec}`
let playerArgs = `--input-ipc-server=${mpvIpcPath} --fullscreen --hwdec=${hwdec}`
if (startSeconds && startSeconds > 0) {
playerArgs += ` --start=${startSeconds}`
}
const args = [
'--player',
MPV_BIN,
'--player-args',
playerArgs,
`twitch.tv/${channelLogin}`,
url,
quality
]