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:
Cameron CordesandClaude Opus 5.5 committed 2026-11-01 19:38:56 -05:00
1 parent 31c1b14d61
commit deb3d051ac
8 files changed
+308 -31

No files matched your search

+10 -1
View File
@@ -221,6 +221,8 @@ struct TemplateView {
/// Approximate output size; clients warn when the original is larger.
output_megapixels: f64,
warn_above_megapixels: f64,
/// `image` (a PNG version) or `video` (an MP4 clip, e.g. Animate).
output: super::template::OutputKind,
}
#[get("/enhance/templates")]
@@ -248,6 +250,7 @@ pub async fn get_templates(_: Claims, svc: web::Data<EnhanceService>) -> impl Re
default: default.as_deref() == Some(t.cfg.name.as_str()),
output_megapixels: t.cfg.output_megapixels,
warn_above_megapixels: svc.config.warn_above_megapixels,
output: t.output,
})
.collect();
let mut body = json!({
@@ -538,7 +541,13 @@ pub async fn approve(
};
build_response(dao.as_mut(), &original, job.library_id)
.ok()
.and_then(|r| r.versions.into_iter().find(|v| v.hash == hash))
// An approved clip (Animate) is listed under `clips`.
.and_then(|r| {
r.versions
.into_iter()
.chain(r.clips)
.find(|v| v.hash == hash)
})
};
match entry {
Some(v) => HttpResponse::Ok().json(v),