Add links-mode embed thumbnails, item metadata, and media filters
This commit is contained in:
@@ -3,11 +3,36 @@
|
||||
* Rules: docs/media-scraper.md. Third-party embeds are never targets here.
|
||||
*/
|
||||
|
||||
import { execFile } from "node:child_process";
|
||||
import { createHash } from "node:crypto";
|
||||
import { writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { promisify } from "node:util";
|
||||
import type { MediaRow } from "./store.js";
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
|
||||
/** Read pixel dimensions with ffprobe. Null when the tool is missing or the file is not media. */
|
||||
export async function probeDimensions(
|
||||
path: string,
|
||||
ffprobe = process.env.VESKSLOP_FFPROBE ?? "ffprobe"
|
||||
): Promise<{ width: number; height: number } | null> {
|
||||
try {
|
||||
const { stdout } = await execFileAsync(
|
||||
ffprobe,
|
||||
["-v", "error", "-select_streams", "v:0", "-show_entries", "stream=width,height", "-of", "json", path],
|
||||
{ timeout: 15_000 }
|
||||
);
|
||||
const stream = JSON.parse(stdout)?.streams?.[0];
|
||||
if (Number.isFinite(stream?.width) && Number.isFinite(stream?.height)) {
|
||||
return { width: stream.width, height: stream.height };
|
||||
}
|
||||
} catch {
|
||||
// missing ffprobe, a timeout, or a non-visual file
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export interface DownloadOptions {
|
||||
fetchImpl?: typeof fetch;
|
||||
/** Skip files larger than this. Default 50 MiB. */
|
||||
|
||||
Reference in New Issue
Block a user