90 lines
2.5 KiB
TypeScript
90 lines
2.5 KiB
TypeScript
import type {
|
|
VideoCanvasReferenceBehavior,
|
|
VideoCanvasReferenceSelectionConfig,
|
|
} from "@/lib/video-canvas/config";
|
|
import type { VideoGenerationMode } from "@/types/ai";
|
|
|
|
export type VideoReferenceEdge = {
|
|
id: string;
|
|
source: string;
|
|
target: string;
|
|
};
|
|
|
|
export type VideoReferenceToggleAction = "add" | "limit" | "remove";
|
|
|
|
function normalizeModelIdentity(value: string) {
|
|
return value.toLowerCase().replace(/[\s._-]+/g, "");
|
|
}
|
|
|
|
export function resolveVideoReferenceSelectionRule(
|
|
config: VideoCanvasReferenceSelectionConfig,
|
|
modelIdentity: string,
|
|
): VideoCanvasReferenceBehavior {
|
|
const normalizedIdentity = normalizeModelIdentity(modelIdentity);
|
|
const matchedRule = config.modelRules.find((rule) => {
|
|
const normalizedPattern = normalizeModelIdentity(rule.modelPattern);
|
|
return normalizedPattern && normalizedIdentity.includes(normalizedPattern);
|
|
});
|
|
const rule = matchedRule || config.defaultRule;
|
|
return {
|
|
autoExit: rule.autoExit,
|
|
hideActionAtLimit: rule.hideActionAtLimit,
|
|
maxImages: rule.maxImages,
|
|
mode: rule.mode,
|
|
};
|
|
}
|
|
|
|
export function resolveVideoReferenceToggleAction<T extends VideoReferenceEdge>(
|
|
referenceEdges: T[],
|
|
sourceId: string,
|
|
targetId: string,
|
|
maxReferences: number,
|
|
): VideoReferenceToggleAction {
|
|
if (
|
|
referenceEdges.some(
|
|
(edge) => edge.source === sourceId && edge.target === targetId,
|
|
)
|
|
) {
|
|
return "remove";
|
|
}
|
|
const referenceCount = referenceEdges.filter(
|
|
(edge) => edge.target === targetId,
|
|
).length;
|
|
return referenceCount >= Math.max(1, Math.round(maxReferences)) ? "limit" : "add";
|
|
}
|
|
|
|
export function selectVideoReferenceImages(
|
|
images: string[],
|
|
mode: VideoGenerationMode,
|
|
maxReferenceImages = 4,
|
|
) {
|
|
if (mode === "text-to-video" || mode === "audio-to-video") return [];
|
|
if (mode === "first-frame") return images.slice(0, 1);
|
|
if (mode === "first-last-frame") return images.slice(0, 2);
|
|
return images.slice(0, Math.max(1, Math.round(maxReferenceImages)));
|
|
}
|
|
|
|
export function removeVideoReferenceEdge<T extends VideoReferenceEdge>(
|
|
edges: T[],
|
|
sourceId: string,
|
|
targetId: string
|
|
) {
|
|
return edges.filter(
|
|
(edge) => !(edge.source === sourceId && edge.target === targetId)
|
|
);
|
|
}
|
|
|
|
export function toggleVideoReferenceEdge<T extends VideoReferenceEdge>(
|
|
edges: T[],
|
|
sourceId: string,
|
|
targetId: string,
|
|
createEdge: () => T
|
|
) {
|
|
const connected = edges.some(
|
|
(edge) => edge.source === sourceId && edge.target === targetId
|
|
);
|
|
return connected
|
|
? removeVideoReferenceEdge(edges, sourceId, targetId)
|
|
: [...edges, createEdge()];
|
|
}
|