Add ffprobe module

This commit is contained in:
Alex Gleason 2025-02-27 23:38:57 -06:00
parent e46b7bfa85
commit 8f02c4125a
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
4 changed files with 56 additions and 18 deletions

View file

@ -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 });
});

View file

@ -1,17 +1,13 @@
import { ffmpeg } from './ffmpeg.ts';
import { ffprobe } from './ffprobe.ts';
export async function ffmpegDim(
input: ReadableStream<Uint8Array>,
): 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;
}

View file

@ -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 });
});

View file

@ -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<Uint8Array> {
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;
}