import { ChildProcessWithoutNullStreams } from 'child_process'; export class TranscodeThrottler { private timer?: NodeJS.Timeout; private encoderPosition = 0; private playheadPosition = 0; private userPaused = false; private ffmpegPaused = false; constructor(private readonly process: ChildProcessWithoutNullStreams) {} start(): void { this.timer = setInterval(() => this.tick(), 1000); this.timer.unref(); } stop(): void { if (this.timer) { clearInterval(this.timer); this.timer = undefined; } } updateProgress(stderrLine: string): void { const match = stderrLine.match(/time=(\d{2}):(\d{2}):(\d{2}(?:\.\d+)?)/); if (!match) return; const hours = Number(match[1]); const minutes = Number(match[2]); const seconds = Number(match[3]); this.encoderPosition = hours * 3600 + minutes * 60 + seconds; } updateClient(position: number, isPaused: boolean): void { this.playheadPosition = Math.max(0, position); this.userPaused = isPaused; } private tick(): void { const gap = this.encoderPosition - this.playheadPosition; if (!this.ffmpegPaused && !this.userPaused && gap > 60) { this.process.stdin.write('p\n'); this.ffmpegPaused = true; return; } if (this.ffmpegPaused && (!this.userPaused || gap < 30)) { this.process.stdin.write('u\n'); this.ffmpegPaused = false; } } }