import { execSync } from "node:child_process"; import { extname } from "node:path"; const IMAGE_EXT = new Set([".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg", ".ico"]); export function probe(filePath) { const ext = extname(filePath).toLowerCase(); if (ext === ".svg") return { width: null, height: null, duration: null, codec: "svg" }; try { const raw = execSync( `ffprobe -v quiet -print_format json -show_format -show_streams "${filePath}"`, { encoding: "utf8", timeout: 5000 }, ); const info = JSON.parse(raw); const stream = info.streams?.[0]; const format = info.format; const isImage = IMAGE_EXT.has(ext); const duration = isImage ? null : parseFloat(format?.duration) || parseFloat(stream?.duration) || null; const width = parseInt(stream?.width, 10) || null; const height = parseInt(stream?.height, 10) || null; const codec = stream?.codec_name || null; return { duration: duration != null ? Math.round(duration * 10) / 10 : null, width, height, codec, }; } catch { return { duration: null, width: null, height: null, codec: null }; } }