diff --git a/packages/transcode/ffmpeg.test.ts b/packages/transcode/ffmpeg.test.ts index 106efb48..57d69f80 100644 --- a/packages/transcode/ffmpeg.test.ts +++ b/packages/transcode/ffmpeg.test.ts @@ -4,13 +4,9 @@ Deno.test('ffmpeg', async () => { await using file = await Deno.open(new URL('./buckbunny.mp4', import.meta.url)); const output = ffmpeg(file.readable, { - 'i': 'pipe:0', 'c:v': 'libx264', 'preset': 'veryfast', 'loglevel': 'fatal', - 'crf': '23', - 'c:a': 'aac', - 'b:a': '128k', 'movflags': 'frag_keyframe+empty_moov', 'f': 'mp4', }); diff --git a/packages/transcode/ffmpeg.ts b/packages/transcode/ffmpeg.ts index c33b68b0..c52ff3e7 100644 --- a/packages/transcode/ffmpeg.ts +++ b/packages/transcode/ffmpeg.ts @@ -1,31 +1,33 @@ export type FFmpegFlags = { - 'i': string; - 'c:v': string; - 'preset': string; - 'loglevel': string; - 'crf': string; - 'c:a': string; - 'b:a': string; - 'movflags': string; - 'f': string; - [key: string]: 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: BodyInit, flags: FFmpegFlags): ReadableStream { - const command = new Deno.Command('ffmpeg', { - args: [ - ...Object.entries(flags).flatMap(([k, v]) => [`-${k}`, v]), - 'pipe:1', // Output to stdout - ], - stdin: 'piped', - stdout: 'piped', - }); +export function ffmpeg(input: ReadableStream, flags: FFmpegFlags): ReadableStream { + const args = ['-i', 'pipe:0']; // Input from stdin + + for (const [key, value] of Object.entries(flags)) { + if (typeof value === 'string') { + args.push(`-${key}`, value); + } + } + + args.push('pipe:1'); // Output to stdout // Spawn the FFmpeg process + const command = new Deno.Command('ffmpeg', { args, stdin: 'piped', stdout: 'piped' }); const child = command.spawn(); // Pipe the input stream into FFmpeg stdin and ensure completion - new Response(input).body!.pipeTo(child.stdin); + input.pipeTo(child.stdin); + // Return the FFmpeg stdout stream return child.stdout; } diff --git a/packages/transcode/transcode.ts b/packages/transcode/transcode.ts index 23271588..d56e37d8 100644 --- a/packages/transcode/transcode.ts +++ b/packages/transcode/transcode.ts @@ -1,6 +1,7 @@ +import { ffmpeg } from './ffmpeg.ts'; + export function transcodeVideo(input: ReadableStream): ReadableStream { - const opts = { - 'i': 'pipe:0', // Read input from stdin + return ffmpeg(input, { 'c:v': 'libx264', // Convert to H.264 'preset': 'veryfast', // Encoding speed 'loglevel': 'fatal', // Suppress logs @@ -9,22 +10,5 @@ export function transcodeVideo(input: ReadableStream): ReadableStrea 'b:a': '128k', // Audio bitrate 'movflags': 'frag_keyframe+empty_moov', // Ensures MP4 streaming compatibility 'f': 'mp4', // Force MP4 format - }; - - const command = new Deno.Command('ffmpeg', { - args: [ - ...Object.entries(opts).flatMap(([k, v]) => [`-${k}`, v]), - 'pipe:1', // Output to stdout - ], - stdin: 'piped', - stdout: 'piped', }); - - // Spawn the FFmpeg process - const child = command.spawn(); - - // Pipe the input stream into FFmpeg stdin and ensure completion - input.pipeTo(child.stdin); - - return child.stdout; }