focal-point: trajni predpomnilnik zarisov na /uploads, da deploy ne analizira vseh slik znova
This commit is contained in:
@@ -26,6 +26,42 @@ function loadDetected() {
|
|||||||
|
|
||||||
const cache = new Map<string, { x: number; y: number }>();
|
const cache = new Map<string, { x: number; y: number }>();
|
||||||
|
|
||||||
|
// Trajni predpomnilnik LLM zarisov. Lezi na /opt/folxtv-uploads (bind mount),
|
||||||
|
// zato prezivi deploy in restart — brez tega je vsak deploy pomenil ponovno
|
||||||
|
// analizo vseh naslovnih slik na gpt-4o-mini.
|
||||||
|
const CACHE_PATH = path.join(process.cwd(), "client/public/uploads/focal_cache.json");
|
||||||
|
let cacheLoaded = false;
|
||||||
|
let cacheDirty = false;
|
||||||
|
|
||||||
|
function loadCache() {
|
||||||
|
if (cacheLoaded) return;
|
||||||
|
cacheLoaded = true;
|
||||||
|
try {
|
||||||
|
const raw = JSON.parse(fs.readFileSync(CACHE_PATH, "utf-8")) as Record<string, { x: number; y: number }>;
|
||||||
|
for (const [k, v] of Object.entries(raw)) {
|
||||||
|
if (v && typeof v.x === "number" && typeof v.y === "number") cache.set(k, v);
|
||||||
|
}
|
||||||
|
console.log("[focal-point] iz predpomnilnika nalozenih:", cache.size);
|
||||||
|
} catch {
|
||||||
|
console.log("[focal-point] predpomnilnika se ni, zacenjam prazen");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveCache() {
|
||||||
|
if (!cacheDirty) return;
|
||||||
|
try {
|
||||||
|
const obj: Record<string, { x: number; y: number }> = {};
|
||||||
|
for (const [k, v] of cache.entries()) obj[k] = v;
|
||||||
|
fs.mkdirSync(path.dirname(CACHE_PATH), { recursive: true });
|
||||||
|
fs.writeFileSync(CACHE_PATH + ".tmp", JSON.stringify(obj));
|
||||||
|
fs.renameSync(CACHE_PATH + ".tmp", CACHE_PATH);
|
||||||
|
cacheDirty = false;
|
||||||
|
console.log("[focal-point] predpomnilnik shranjen, vnosov:", cache.size);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("[focal-point] predpomnilnika ni bilo mogoce shraniti:", (e as Error).message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const manualOverrides: Record<string, { x: number; y: number }> = {
|
const manualOverrides: Record<string, { x: number; y: number }> = {
|
||||||
"/uploads/70-jahre-oberkrainer.webp": { x: 50, y: 55 },
|
"/uploads/70-jahre-oberkrainer.webp": { x: 50, y: 55 },
|
||||||
};
|
};
|
||||||
@@ -46,6 +82,7 @@ Return ONLY a JSON object like {"x":42,"y":38} with no other text.`;
|
|||||||
|
|
||||||
export async function analyzeFocalPoint(imagePath: string): Promise<{ x: number; y: number }> {
|
export async function analyzeFocalPoint(imagePath: string): Promise<{ x: number; y: number }> {
|
||||||
const originalPath = imagePath;
|
const originalPath = imagePath;
|
||||||
|
loadCache();
|
||||||
if (manualOverrides[originalPath]) {
|
if (manualOverrides[originalPath]) {
|
||||||
cache.set(originalPath, manualOverrides[originalPath]);
|
cache.set(originalPath, manualOverrides[originalPath]);
|
||||||
return manualOverrides[originalPath];
|
return manualOverrides[originalPath];
|
||||||
@@ -104,6 +141,7 @@ export async function analyzeFocalPoint(imagePath: string): Promise<{ x: number;
|
|||||||
y: Math.max(0, Math.min(100, Number(parsed.y) || 30)),
|
y: Math.max(0, Math.min(100, Number(parsed.y) || 30)),
|
||||||
};
|
};
|
||||||
cache.set(originalPath, point);
|
cache.set(originalPath, point);
|
||||||
|
cacheDirty = true;
|
||||||
return point;
|
return point;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -120,10 +158,12 @@ export async function analyzeAllArticleImages(articles: Array<{ coverImage: stri
|
|||||||
if (!article.coverImage) continue;
|
if (!article.coverImage) continue;
|
||||||
await analyzeFocalPoint(article.coverImage);
|
await analyzeFocalPoint(article.coverImage);
|
||||||
}
|
}
|
||||||
|
saveCache();
|
||||||
console.log("[focal-point] Analyzed", cache.size, "images");
|
console.log("[focal-point] Analyzed", cache.size, "images");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCachedFocalPoints(): Record<string, { x: number; y: number }> {
|
export function getCachedFocalPoints(): Record<string, { x: number; y: number }> {
|
||||||
|
loadCache();
|
||||||
loadDetected();
|
loadDetected();
|
||||||
const result: Record<string, { x: number; y: number }> = {};
|
const result: Record<string, { x: number; y: number }> = {};
|
||||||
for (const [key, value] of cache.entries()) {
|
for (const [key, value] of cache.entries()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user