Make analyze return a lot more information

This commit is contained in:
Alex Gleason 2025-02-28 19:48:22 -06:00
parent ad9cc676e6
commit a28e6509fd
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
3 changed files with 99 additions and 20 deletions

View file

@ -1,10 +1,13 @@
import { assertEquals } from '@std/assert'; import { assertObjectMatch } from '@std/assert';
import { getVideoDimensions } from './analyze.ts'; import { analyzeFile } from './analyze.ts';
Deno.test('getVideoDimensions', async () => { Deno.test('analyzeFile', async () => {
const uri = new URL('./buckbunny.mp4', import.meta.url); const uri = new URL('./buckbunny.mp4', import.meta.url);
const dimensions = await getVideoDimensions(uri);
assertEquals(dimensions, { width: 1920, height: 1080 }); const { streams } = await analyzeFile(uri);
const videoStream = streams.find((stream) => stream.codec_type === 'video')!;
assertObjectMatch(videoStream, { width: 1920, height: 1080 });
}); });

View file

@ -1,23 +1,99 @@
import { ffprobe } from './ffprobe.ts'; import { ffprobe } from './ffprobe.ts';
export async function getVideoDimensions( interface AnalyzeResult {
input: URL | ReadableStream<Uint8Array>, streams: Stream[];
): Promise<{ width: number; height: number } | null> { format: Format;
}
interface Stream {
index: number;
codec_tag_string: string;
codec_tag: string;
codec_name?: string;
codec_long_name?: string;
profile?: string;
codec_type?: string;
width?: number;
height?: number;
coded_width?: number;
coded_height?: number;
closed_captions?: number;
has_b_frames?: number;
sample_aspect_ratio?: string;
display_aspect_ratio?: string;
pix_fmt?: string;
level?: number;
color_range?: string;
color_space?: string;
color_transfer?: string;
color_primaries?: string;
chroma_location?: string;
field_order?: string;
refs?: number;
sample_fmt?: string;
sample_rate?: string;
channels?: number;
channel_layout?: string;
bits_per_sample?: number;
id?: string;
r_frame_rate?: string;
avg_frame_rate?: string;
time_base?: string;
start_pts?: number;
start_time?: string;
duration_ts?: number;
duration?: string;
bit_rate?: string;
max_bit_rate?: string;
bits_per_raw_sample?: string;
nb_frames?: string;
nb_read_frames?: string;
nb_read_packets?: string;
disposition?: Disposition;
tags?: Record<string, string>;
}
interface Format {
filename: string;
nb_streams: number;
nb_programs: number;
format_name: string;
probe_score: number;
format_long_name?: string;
start_time?: string;
duration?: string;
size?: string;
bit_rate?: string;
tags?: Record<string, string>;
}
interface Disposition {
default: number;
dub: number;
original: number;
comment: number;
lyrics: number;
karaoke: number;
forced: number;
hearing_impaired: number;
visual_impaired: number;
clean_effects: number;
attached_pic: number;
timed_thumbnails: number;
captions: number;
descriptions: number;
metadata: number;
dependent: number;
still_image: number;
}
export function analyzeFile(input: URL | ReadableStream<Uint8Array>): Promise<AnalyzeResult> {
const stream = ffprobe(input, { const stream = ffprobe(input, {
'v': 'error', 'v': 'error',
'select_streams': 'v:0',
'show_streams': '', 'show_streams': '',
'show_format': '',
'of': 'json', 'of': 'json',
}); });
const { streams } = await new Response(stream).json(); return new Response(stream).json();
for (const stream of streams) {
if (stream.codec_type === 'video') {
const { width, height } = stream;
return { width, height };
}
}
return null;
} }

View file

@ -1,4 +1,4 @@
export { getVideoDimensions } from './analyze.ts'; export { analyzeFile } from './analyze.ts';
export { ffmpeg, type FFmpegFlags } from './ffmpeg.ts'; export { ffmpeg, type FFmpegFlags } from './ffmpeg.ts';
export { ffprobe, type FFprobeFlags } from './ffprobe.ts'; export { ffprobe, type FFprobeFlags } from './ffprobe.ts';
export { extractVideoFrame } from './frame.ts'; export { extractVideoFrame } from './frame.ts';