Derived clips: link MP4 versions, list them apart, video Enhance output
Groundwork for Enhance "Animate" (#208): a video made from a photo. - Version linking reads the XMP link from MP4 / MOV too (top-level uuid box with the XMP UUID, mdat seeked over), at ingest and on Enhance approve. - New kind `animated`, a derived clip (CLIP_KINDS): hidden behind the photo like a version, but not counted in photo_version_counts / version_count, never a display choice (400 clip_not_displayable), and listed as `clips` in GET /image/versions. Approve returns the clip entry. - Templates whose imageapi:save is ImageApiSaveVideoVersion report output "video" in /enhance/templates (no enhance.toml change). Previews already relay ComfyUI's content type (video/mp4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
31c1b14d61
commit
deb3d051ac
8 files changed
+308
-31
No files matched your search
@@ -19,6 +19,19 @@ pub const TITLE_REFERENCE: &str = "imageapi:reference";
|
||||
/// Prompt-node inputs, in the order they are tried.
|
||||
const PROMPT_INPUTS: &[&str] = &["text", "prompt", "value"];
|
||||
|
||||
/// What a template produces, from its `imageapi:save` node's class.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum OutputKind {
|
||||
/// Save Image Version: PNG versions.
|
||||
Image,
|
||||
/// Save Video Version: an MP4 (e.g. a clip animated from the photo).
|
||||
Video,
|
||||
}
|
||||
|
||||
/// The save node class that makes a template's output a video.
|
||||
pub const VIDEO_SAVE_CLASS: &str = "ImageApiSaveVideoVersion";
|
||||
|
||||
/// Output nodes that write into ComfyUI's output folder on every API run.
|
||||
const STRAY_OUTPUT_CLASSES: &[&str] = &[
|
||||
"SaveImage",
|
||||
@@ -38,6 +51,8 @@ pub struct Template {
|
||||
/// `(node id, input name)` of the prompt text.
|
||||
prompt: Option<(String, &'static str)>,
|
||||
reference_id: Option<String>,
|
||||
/// Image or video, from the save node's class.
|
||||
pub output: OutputKind,
|
||||
/// Startup warnings (stray output nodes).
|
||||
pub warnings: Vec<String>,
|
||||
}
|
||||
@@ -143,6 +158,11 @@ impl Template {
|
||||
));
|
||||
}
|
||||
}
|
||||
let output = if workflow[&save_id]["class_type"].as_str() == Some(VIDEO_SAVE_CLASS) {
|
||||
OutputKind::Video
|
||||
} else {
|
||||
OutputKind::Image
|
||||
};
|
||||
Ok(Template {
|
||||
cfg,
|
||||
workflow,
|
||||
@@ -150,6 +170,7 @@ impl Template {
|
||||
save_id,
|
||||
prompt,
|
||||
reference_id,
|
||||
output,
|
||||
warnings,
|
||||
})
|
||||
}
|
||||
@@ -414,6 +435,23 @@ mod tests {
|
||||
assert_ne!(input(&x.prompt, "5", "seed"), input(&y.prompt, "5", "seed"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn output_kind_follows_the_save_node() {
|
||||
assert_eq!(
|
||||
load(RESTORE, PromptMode::Append).unwrap().output,
|
||||
OutputKind::Image
|
||||
);
|
||||
let video = RESTORE.replace(
|
||||
"\"ImageApiSaveImageVersion\"",
|
||||
"\"ImageApiSaveVideoVersion\"",
|
||||
);
|
||||
assert_ne!(video, RESTORE);
|
||||
assert_eq!(
|
||||
load(&video, PromptMode::Append).unwrap().output,
|
||||
OutputKind::Video
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn random_seeds_fit_seedvr2s_u32_limit() {
|
||||
// SeedVR2VideoUpscaler rejects seeds above 2^32 - 1 at validation.
|
||||
|
||||
Reference in new issue
Block a user