Files
ausboss-ComfyUI-AusBoss/js/shared/video_source_card.mjs
ausboss 4fe448ccbe Video Crop + Rotate + Pad: pick an output video from a list, nothing is typed
The second source tab was Server file, a box for a typed path. It is now
Outputs: the videos in ComfyUI's output folder, newest first, in the same
list with a preview that the Uploads tab uses. The list asks the server
each time it opens (/ausboss/transform/video/outputs, no parameters), so a
video rendered a moment ago is in it.

The picked video is saved the way ComfyUI names a file in one of its
folders ("clip.mp4 [output]"). resolve_server_file reads that form and
nothing else: a whole path, a drive, "~", ".." and a network path are
refused from the text alone, and a link that leads out is refused once the
path is resolved. A workflow saved with a typed path shows nothing picked
and a line that asks for the pick.
2026-10-13 11:45:31 -05:00

60 lines
2.2 KiB
JavaScript

export const INPUT_FOLDER_MODE = "input folder";
export const LOCAL_PATH_MODE = "local path";
export function normalizeVideoSourceMode(value) {
return value === LOCAL_PATH_MODE ? LOCAL_PATH_MODE : INPUT_FOLDER_MODE;
}
export function normalizeVideoOptions(values, selected = "") {
const result = [];
for (const value of Array.isArray(values) ? values : []) {
const text = String(value ?? "");
if (text && !result.includes(text)) result.push(text);
}
const current = String(selected ?? "");
if (current && !result.includes(current)) result.push(current);
return result;
}
// A whole path, as a workflow may hold from when this source was a box to
// type one in. The server no longer reads one, so it counts as nothing
// picked and the hint asks for the pick.
export function isWholePath(value) {
return /^"?(?:[\\/~]|[A-Za-z]:)/.test(String(value ?? "").trim());
}
// What the Outputs list has picked: the saved value, or nothing for a whole path.
export function pickedOutput(localPath) {
const text = String(localPath ?? "").trim();
return isWholePath(text) ? "" : text;
}
export function videoSourceState(mode, video, localPath) {
const normalizedMode = normalizeVideoSourceMode(mode);
const local = normalizedMode === LOCAL_PATH_MODE;
const selection = local ? pickedOutput(localPath) : String(video ?? "").trim();
return {
mode: normalizedMode,
selection,
key: selection ? `${local ? "local" : "input"}:${selection}` : "",
hint: !local
? "Choose an uploaded video or add one to ComfyUI's input folder."
: isWholePath(localPath)
? "Pick the video again. A typed path is no longer read."
: "The videos in ComfyUI's output folder, newest first.",
};
}
// Images use the same picker card, but their backend accepts input-folder
// references only. Do not advertise a Local path mode it cannot execute.
export function mediaSourceState(kind, mode, selection, localPath) {
if (kind !== "image") return videoSourceState(mode, selection, localPath);
const image = String(selection ?? "");
return {
mode: INPUT_FOLDER_MODE,
selection: image,
key: image,
hint: "Choose an uploaded image or drop one onto this node.",
};
}