82 lines
2.9 KiB
TypeScript
82 lines
2.9 KiB
TypeScript
export function parseFpsValue(value: unknown): number | null {
|
|
try {
|
|
const n = Number(value);
|
|
if (Number.isFinite(n) && n > 0) return n;
|
|
const s = String(value || "").trim();
|
|
if (!s) return null;
|
|
if (s.includes("/")) {
|
|
const [a, b] = s.split("/");
|
|
const na = Number(a);
|
|
const nb = Number(b);
|
|
if (Number.isFinite(na) && Number.isFinite(nb) && nb !== 0) {
|
|
const fps = na / nb;
|
|
return Number.isFinite(fps) && fps > 0 ? fps : null;
|
|
}
|
|
}
|
|
const f = Number.parseFloat(s);
|
|
return Number.isFinite(f) && f > 0 ? f : null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export function readAssetFps(asset: unknown): number | null {
|
|
try {
|
|
const a = asset as Record<string, unknown>;
|
|
const raw = (a.metadata_raw as Record<string, unknown>) || {};
|
|
const ff = (raw.raw_ffprobe as Record<string, unknown>) || {};
|
|
const vs = (ff.video_stream as Record<string, unknown>) || {};
|
|
return (
|
|
parseFpsValue(vs.avg_frame_rate) ??
|
|
parseFpsValue(vs.r_frame_rate) ??
|
|
parseFpsValue(raw.fps_raw) ??
|
|
parseFpsValue(raw.fps) ??
|
|
parseFpsValue(raw.frame_rate) ??
|
|
parseFpsValue(a.fps)
|
|
);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export function readAssetFrameCount(asset: unknown, fps: number | null | undefined): number | null {
|
|
try {
|
|
const a = asset as Record<string, unknown>;
|
|
const raw = (a.metadata_raw as Record<string, unknown>) || {};
|
|
const ff = (raw.raw_ffprobe as Record<string, unknown>) || {};
|
|
const vs = (ff.video_stream as Record<string, unknown>) || {};
|
|
|
|
const direct =
|
|
Number(a.frame_count) ||
|
|
Number(raw.frame_count) ||
|
|
Number(raw.frames) ||
|
|
Number(vs.nb_frames) ||
|
|
Number(vs.nb_read_frames) ||
|
|
0;
|
|
if (Number.isFinite(direct) && direct > 0) return Math.floor(direct);
|
|
|
|
const dur = Number(a.duration ?? raw.duration ?? vs.duration);
|
|
if (Number.isFinite(dur) && dur > 0 && fps != null && Number.isFinite(fps) && fps > 0) {
|
|
return Math.max(1, Math.round(dur * fps));
|
|
}
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
export function formatFps(fps: unknown): string {
|
|
const n = Number(fps);
|
|
if (!Number.isFinite(n) || n <= 0) return "";
|
|
if (Math.abs(n - Math.round(n)) < 0.001) return `${Math.round(n)} fps`;
|
|
return `${n.toFixed(3).replace(/\.?0+$/, "")} fps`;
|
|
}
|
|
|
|
export function normalizeVideoFps(value: unknown, fallback: unknown = 30): number {
|
|
const parsed = parseFpsValue(value);
|
|
if (parsed != null) return Math.max(1, Math.round(parsed * 1000) / 1000);
|
|
const fallbackParsed = parseFpsValue(fallback);
|
|
if (fallbackParsed != null) return Math.max(1, Math.round(fallbackParsed * 1000) / 1000);
|
|
return 30;
|
|
}
|