Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
42 lines
2.6 KiB
JavaScript
42 lines
2.6 KiB
JavaScript
// One upscale job from queue to result, and the swap of the new file under every render that plays the old one. Pure of the page.
|
|
export const keyOf = (m) => `${m.type || "output"}/${m.subfolder || ""}/${m.filename}`;
|
|
export const UPSCALED = "funpack_upscaled";
|
|
export const RTX = "NVIDIA RTX Super Resolution"; // sent as the model name for that engine; the same string as modules/output/render/rtx.py NAME
|
|
export const RTX_DEFAULTS = { quality: "ULTRA", resize: "scale", scale: 2, width: 1920, height: 1080, strength: 1, tenbit: false };
|
|
const LEVEL = { LOW: "Low", MEDIUM: "Medium", HIGH: "High", ULTRA: "Ultra" };
|
|
/** "DENOISE_HIGH" -> "Denoise · High": what the SDK calls a quality level, said to a person. */
|
|
export const qualityLabel = (q) => {
|
|
if (q === "BICUBIC") return "Bicubic (no AI)";
|
|
const i = q.lastIndexOf("_"), level = LEVEL[q.slice(i + 1)] || q.slice(i + 1);
|
|
if (i < 0) return `Upscale · ${LEVEL[q] || q}`;
|
|
const kind = { DENOISE: "Denoise", DEBLUR: "Deblur", HIGHBITRATE: "High bitrate", STREAMING: "Streaming" }[q.slice(0, i)] || q.slice(0, i);
|
|
return `${kind} · ${level}`;
|
|
};
|
|
/** Denoise and deblur clean a video at its own size: scale and target size do not apply. */
|
|
export const keepsSize = (q) => q.startsWith("DENOISE_") || q.startsWith("DEBLUR_");
|
|
|
|
/** -> the upscaled media, or throws a sentence. `sleep` is injectable so a test need not wait. */
|
|
export async function upscale(api, media, model, sleep = (ms) => new Promise((r) => setTimeout(r, ms)), rtx) {
|
|
const id = await api.queueUpscale(media, model, rtx);
|
|
let lost = 0;
|
|
for (;;) {
|
|
await sleep(2000);
|
|
const r = await api.upscaleResult(id);
|
|
if (!r) { lost = 0; continue; }
|
|
if (r.retry) { if (++lost < 30) continue; throw new Error("lost contact with ComfyUI"); }
|
|
if (r.gone) { if (++lost < 3) continue; throw new Error("the job left ComfyUI's queue without finishing (interrupted or ComfyUI restarted)"); }
|
|
if (r.error) throw new Error(r.error);
|
|
return r.videos[0];
|
|
}
|
|
}
|
|
|
|
/** One file backs a whole chain run, so every scene render and ghost that plays `from` gets `to`. -> how many were swapped. */
|
|
export function swap(p, from, to) {
|
|
const same = (m) => !!m && keyOf(m) === keyOf(from);
|
|
let n = 0;
|
|
for (const [id, r] of Object.entries(p.scene_renders || {})) if (r && same(r.media)) { p.scene_renders[id] = { ...r, media: to }; n += 1; }
|
|
for (const list of Object.values(p.scene_variants || {})) list.forEach((t) => { if (same(t.media)) { t.media = to; n += 1; } }); // a take stepped back to must be the upscaled file too
|
|
p.scene_ghosts = (p.scene_ghosts || []).map((g) => (same(g.media) ? (n += 1, { ...g, media: to }) : g));
|
|
return n;
|
|
}
|