52 lines
1.4 KiB
TypeScript
52 lines
1.4 KiB
TypeScript
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;
|
|
}
|
|
}
|
|
}
|