ditto/packages/transcode/ffmpeg.ts
2025-02-28 20:52:11 -06:00

52 lines
1.3 KiB
TypeScript

export interface FFmpegFlags {
'safe'?: string;
'nostdin'?: string;
'c:v'?: string;
'preset'?: string;
'loglevel'?: string;
'crf'?: string;
'c:a'?: string;
'b:a'?: string;
'movflags'?: string;
'f'?: string;
[key: string]: string | undefined;
}
export function ffmpeg(input: URL | ReadableStream<Uint8Array>, flags: FFmpegFlags): ReadableStream<Uint8Array> {
const args = ['-i', input instanceof URL ? input.href : 'pipe:0'];
for (const [key, value] of Object.entries(flags)) {
if (typeof value === 'string') {
if (value) {
args.push(`-${key}`, value);
} else {
args.push(`-${key}`);
}
}
}
args.push('pipe:1'); // Output to stdout
// Spawn the FFmpeg process
const command = new Deno.Command('ffmpeg', {
args,
stdin: input instanceof ReadableStream ? 'piped' : 'null',
stdout: 'piped',
});
const child = command.spawn();
// Pipe the input stream into FFmpeg stdin and ensure completion
if (input instanceof ReadableStream) {
input.pipeTo(child.stdin).catch((e: unknown) => {
if (e instanceof Error && e.name === 'BrokenPipe') {
// Ignore. ffprobe closes the pipe once it has read the metadata.
} else {
throw e;
}
});
}
// Return the FFmpeg stdout stream
return child.stdout;
}