mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 03:19:46 +00:00
Let ffprobe pipe data to stdin
This commit is contained in:
parent
d70a00a8ca
commit
5f10f92d4e
4 changed files with 50 additions and 8 deletions
|
|
@ -4,8 +4,7 @@ import { getVideoDimensions } from './analyze.ts';
|
|||
|
||||
Deno.test('getVideoDimensions', async () => {
|
||||
const uri = new URL('./buckbunny.mp4', import.meta.url);
|
||||
|
||||
const dimensions = await getVideoDimensions(uri.href);
|
||||
const dimensions = await getVideoDimensions(uri);
|
||||
|
||||
assertEquals(dimensions, { width: 1920, height: 1080 });
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import { ffprobe } from './ffprobe.ts';
|
||||
|
||||
export async function getVideoDimensions(path: string): Promise<{ width: number; height: number } | null> {
|
||||
const stream = ffprobe(path, {
|
||||
export async function getVideoDimensions(
|
||||
input: URL | ReadableStream<Uint8Array>,
|
||||
): Promise<{ width: number; height: number } | null> {
|
||||
const stream = ffprobe(input, {
|
||||
'v': 'error',
|
||||
'select_streams': 'v:0',
|
||||
'show_entries': 'stream=width,height',
|
||||
|
|
|
|||
|
|
@ -3,6 +3,21 @@ import { assertEquals } from '@std/assert';
|
|||
import { ffprobe } from './ffprobe.ts';
|
||||
|
||||
Deno.test('ffprobe', async () => {
|
||||
await using file = await Deno.open(new URL('./buckbunny.mp4', import.meta.url));
|
||||
|
||||
const stream = ffprobe(file.readable, {
|
||||
'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 });
|
||||
});
|
||||
|
||||
Deno.test('ffprobe from file', async () => {
|
||||
const uri = new URL('./buckbunny.mp4', import.meta.url);
|
||||
|
||||
const stream = ffprobe(uri, {
|
||||
|
|
|
|||
|
|
@ -6,19 +6,45 @@ export interface FFprobeFlags {
|
|||
[key: string]: string | undefined;
|
||||
}
|
||||
|
||||
export function ffprobe(path: URL | string, flags: FFprobeFlags): ReadableStream<Uint8Array> {
|
||||
export function ffprobe(input: URL | ReadableStream<Uint8Array>, flags: FFprobeFlags): ReadableStream<Uint8Array> {
|
||||
const args = [];
|
||||
|
||||
for (const [key, value] of Object.entries(flags)) {
|
||||
if (typeof value === 'string') {
|
||||
args.push(`-${key}`, value);
|
||||
if (value) {
|
||||
args.push(`-${key}`, value);
|
||||
} else {
|
||||
args.push(`-${key}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
args.push(path instanceof URL ? path.href : path);
|
||||
if (input instanceof URL) {
|
||||
args.push('-i', input.href);
|
||||
} else {
|
||||
args.push('-i', 'pipe:0');
|
||||
}
|
||||
|
||||
// Spawn the FFprobe process
|
||||
const command = new Deno.Command('ffprobe', {
|
||||
args,
|
||||
stdin: input instanceof ReadableStream ? 'piped' : 'null',
|
||||
stdout: 'piped',
|
||||
});
|
||||
|
||||
const command = new Deno.Command('ffprobe', { args, 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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue