diff --git a/packages/transcode/analyze.test.ts b/packages/transcode/analyze.test.ts index 67be60b1..aeed6c94 100644 --- a/packages/transcode/analyze.test.ts +++ b/packages/transcode/analyze.test.ts @@ -1,11 +1,11 @@ import { assertEquals } from '@std/assert'; -import { ffmpegDim } from './analyze.ts'; +import { getVideoDimensions } from './analyze.ts'; -Deno.test('ffmpegDim', async () => { - await using file = await Deno.open(new URL('./buckbunny.mp4', import.meta.url)); +Deno.test('getVideoDimensions', async () => { + const uri = new URL('./buckbunny.mp4', import.meta.url); - const result = await ffmpegDim(file.readable); + const dimensions = await getVideoDimensions(uri.href); - assertEquals(result, { width: 1280, height: 720 }); + assertEquals(dimensions, { width: 1920, height: 1080 }); }); diff --git a/packages/transcode/analyze.ts b/packages/transcode/analyze.ts index b3e0e5a9..95a6f6d2 100644 --- a/packages/transcode/analyze.ts +++ b/packages/transcode/analyze.ts @@ -1,17 +1,13 @@ -import { ffmpeg } from './ffmpeg.ts'; +import { ffprobe } from './ffprobe.ts'; -export async function ffmpegDim( - input: ReadableStream, -): Promise<{ width: number; height: number } | undefined> { - const result = ffmpeg(input, { - 'vf': 'showinfo', // Output as JSON - 'f': 'null', // Tell FFmpeg not to produce an output file +export async function getVideoDimensions(path: string): Promise<{ width: number; height: number } | null> { + const stream = ffprobe(path, { + 'v': 'error', + 'select_streams': 'v:0', + 'show_entries': 'stream=width,height', + 'of': 'json', }); - const text = await new Response(result).json(); - console.log(text); - const output = JSON.parse(text); - - const [stream] = output.streams ?? []; - return stream; + const { streams: [result] } = await new Response(stream).json(); + return result ?? null; } diff --git a/packages/transcode/ffprobe.test.ts b/packages/transcode/ffprobe.test.ts new file mode 100644 index 00000000..531e648e --- /dev/null +++ b/packages/transcode/ffprobe.test.ts @@ -0,0 +1,18 @@ +import { assertEquals } from '@std/assert'; + +import { ffprobe } from './ffprobe.ts'; + +Deno.test('ffprobe', async () => { + const uri = new URL('./buckbunny.mp4', import.meta.url); + + const stream = ffprobe(uri, { + 'v': 'error', + 'select_streams': 'v:0', + 'show_entries': 'stream=width,height', + 'of': 'json', + }); + + const { streams: [dimensions] } = await new Response(stream).json(); + + assertEquals(dimensions, { width: 1920, height: 1080 }); +}); diff --git a/packages/transcode/ffprobe.ts b/packages/transcode/ffprobe.ts new file mode 100644 index 00000000..3388cc30 --- /dev/null +++ b/packages/transcode/ffprobe.ts @@ -0,0 +1,24 @@ +export interface FFprobeFlags { + 'v'?: string; + 'select_streams'?: string; + 'show_entries'?: string; + 'of'?: string; + [key: string]: string | undefined; +} + +export function ffprobe(path: URL | string, flags: FFprobeFlags): ReadableStream { + const args = []; + + for (const [key, value] of Object.entries(flags)) { + if (typeof value === 'string') { + args.push(`-${key}`, value); + } + } + + args.push(path instanceof URL ? path.href : path); + + const command = new Deno.Command('ffprobe', { args, stdout: 'piped' }); + const child = command.spawn(); + + return child.stdout; +}