fix(canvas): 视频参考协议 - 统一首尾帧与角色资产语义

This commit is contained in:
ddCat
2026-08-30 16:52:09 +08:00
parent b5f8b66622
commit 37eb2b7e48
15 changed files with 479 additions and 68 deletions

View File

@@ -0,0 +1,45 @@
import type { ReferenceImage } from "@/types/image";
import type { RequestOptions } from "./video-contracts";
export type VideoImageRole = "first_frame" | "last_frame" | "reference_image";
export type ResolvedVideoImageReference = {
image: ReferenceImage;
role: VideoImageRole;
};
type VideoReferenceContext = {
videoCount?: number;
audioCount?: number;
};
export function resolveVideoImageReferences(images: ReferenceImage[], options?: RequestOptions, context: VideoReferenceContext = {}): ResolvedVideoImageReference[] {
const operation = options?.videoEditOperation?.trim();
if (operation === "reference_to_video") {
return images.map((image) => ({ image, role: "reference_image" }));
}
const startFrameId = options?.videoStartFrameNodeId?.trim();
const endFrameId = options?.videoEndFrameNodeId?.trim();
if (startFrameId || endFrameId) {
return images.map((image) => ({
image,
role: image.id === startFrameId ? "first_frame" : image.id === endFrameId ? "last_frame" : "reference_image",
}));
}
if (context.videoCount || context.audioCount) {
return images.map((image) => ({ image, role: "reference_image" }));
}
// 传统创作页没有帧节点 ID:保留单图首帧、双图首尾帧的历史语义。
return images.map((image, index) => ({
image,
role: index === 0 ? "first_frame" : index === 1 && images.length === 2 ? "last_frame" : "reference_image",
}));
}
export function hasExplicitVideoFrames(options?: RequestOptions) {
return options?.videoEditOperation !== "reference_to_video" && Boolean(options?.videoStartFrameNodeId || options?.videoEndFrameNodeId);
}