diff --git a/packages/transcode/analyze.test.ts b/packages/transcode/analyze.test.ts index e72e1619..c1a23f5e 100644 --- a/packages/transcode/analyze.test.ts +++ b/packages/transcode/analyze.test.ts @@ -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 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 }); }); diff --git a/packages/transcode/analyze.ts b/packages/transcode/analyze.ts index 4221c280..03f4aaff 100644 --- a/packages/transcode/analyze.ts +++ b/packages/transcode/analyze.ts @@ -1,23 +1,99 @@ import { ffprobe } from './ffprobe.ts'; -export async function getVideoDimensions( - input: URL | ReadableStream, -): Promise<{ width: number; height: number } | null> { +interface AnalyzeResult { + streams: Stream[]; + 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; +} + +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; +} + +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): Promise { const stream = ffprobe(input, { 'v': 'error', - 'select_streams': 'v:0', 'show_streams': '', + 'show_format': '', 'of': 'json', }); - const { streams } = await new Response(stream).json(); - - for (const stream of streams) { - if (stream.codec_type === 'video') { - const { width, height } = stream; - return { width, height }; - } - } - - return null; + return new Response(stream).json(); } diff --git a/packages/transcode/mod.ts b/packages/transcode/mod.ts index 2a1580d2..8da45b0e 100644 --- a/packages/transcode/mod.ts +++ b/packages/transcode/mod.ts @@ -1,4 +1,4 @@ -export { getVideoDimensions } from './analyze.ts'; +export { analyzeFile } from './analyze.ts'; export { ffmpeg, type FFmpegFlags } from './ffmpeg.ts'; export { ffprobe, type FFprobeFlags } from './ffprobe.ts'; export { extractVideoFrame } from './frame.ts';