89 lines
5.4 KiB
TypeScript
89 lines
5.4 KiB
TypeScript
import { SEEDANCE_25_MODEL } from "@/lib/video-settings";
|
|
|
|
export type VideoInputEngine = "seedance" | "minimax" | "bailian";
|
|
export type VideoInputMode = "reference" | "frames";
|
|
export type VideoMaterialKind = "image" | "video" | "audio";
|
|
|
|
export const BAILIAN_27_VIDEO_MODEL = "wan2.7-i2v-2026-04-25";
|
|
export const BAILIAN_30_VIDEO_MODEL = "wan3.0-video";
|
|
export const BAILIAN_VIDEO_MODELS = [
|
|
{ id: BAILIAN_27_VIDEO_MODEL, label: "Wan 2.7 · 首尾帧" },
|
|
{ id: BAILIAN_30_VIDEO_MODEL, label: "Wan 3.0 · 多图参考" }
|
|
] as const;
|
|
|
|
export type VideoInputSelection = {
|
|
engine: VideoInputEngine;
|
|
model: string;
|
|
inputMode: VideoInputMode;
|
|
};
|
|
|
|
export function videoInputHint(selection: VideoInputSelection): string {
|
|
if (selection.engine === "seedance") {
|
|
return selection.model === SEEDANCE_25_MODEL
|
|
? "多素材参考:最多 30 张图片、10 段视频、10 段音频,总计 50 个。可在提示词中用 @图片1 等编号指定用途。"
|
|
: "多素材参考:最多 9 张图片、3 段视频、3 段音频;音频需要搭配图片或视频。可用 @图片1 等编号指定用途。";
|
|
}
|
|
if (selection.engine === "minimax") {
|
|
return selection.inputMode === "frames"
|
|
? "首帧模式:可不上传图片,或上传 1 张图片固定视频开头;有首帧时比例跟随图片。若想用多张图共同指导内容,请切换到「多图参考」。"
|
|
: "多图参考:最多 9 张图片。图片用于指导人物、服装或场景,不会被固定为视频首帧;可在提示词中引用 @图片1 等编号。";
|
|
}
|
|
if (selection.model === BAILIAN_27_VIDEO_MODEL) {
|
|
return "Wan 2.7 首尾帧:上传 1 张图片作为首帧,或按顺序上传 2 张作为首帧和尾帧。多图参考请切换到 Wan 3.0。";
|
|
}
|
|
return selection.inputMode === "frames"
|
|
? "首尾帧:上传 1 张首帧图,或按顺序上传 2 张首尾帧图。若想让更多图片共同指导内容,请切换到「多图参考」。"
|
|
: "多图参考:可只输入文字,或上传最多 10 张图片指导人物、服装和场景;参考图不会固定为首尾帧,可在提示词中引用 @图片1 等编号。";
|
|
}
|
|
|
|
export function videoMaterialError(selection: VideoInputSelection, materials: readonly { type: VideoMaterialKind }[]): string | null {
|
|
const imageCount = materials.filter((item) => item.type === "image").length;
|
|
const videoCount = materials.filter((item) => item.type === "video").length;
|
|
const audioCount = materials.filter((item) => item.type === "audio").length;
|
|
if (selection.engine === "seedance") {
|
|
const is25 = selection.model === SEEDANCE_25_MODEL;
|
|
const maxImages = is25 ? 30 : 9;
|
|
const maxVideo = is25 ? 10 : 3;
|
|
const maxAudio = is25 ? 10 : 3;
|
|
if (imageCount > maxImages || videoCount > maxVideo || audioCount > maxAudio || is25 && materials.length > 50) {
|
|
return `${is25 ? "Seedance 2.5" : "Seedance 2.0"} 最多支持 ${maxImages} 张图片、${maxVideo} 段视频、${maxAudio} 段音频${is25 ? ",总计 50 个素材" : ""};请移除超出的素材。`;
|
|
}
|
|
if (!is25 && audioCount > 0 && imageCount + videoCount === 0) {
|
|
return "Seedance 2.0 的音频不能单独生成视频;请添加至少 1 张图片或 1 段视频,或切换到 Seedance 2.5。";
|
|
}
|
|
return null;
|
|
}
|
|
if (selection.engine === "minimax") {
|
|
if (videoCount || audioCount) return "MiniMax H3 当前只接受图片素材;请移除视频和音频,或切换到 Seedance。";
|
|
if (selection.inputMode === "frames" && imageCount > 1) {
|
|
return "MiniMax H3 首帧模式最多只能上传 1 张图;请切换到「多图参考」或移除多余图片。";
|
|
}
|
|
if (selection.inputMode === "reference" && imageCount > 9) {
|
|
return "MiniMax H3 多图参考最多支持 9 张图片;请移除多余图片。";
|
|
}
|
|
return null;
|
|
}
|
|
if (videoCount || audioCount) return "百炼当前只接受图片素材;请移除视频和音频,或切换到 Seedance。";
|
|
if (selection.model === BAILIAN_27_VIDEO_MODEL || selection.inputMode === "frames") {
|
|
if (!imageCount) return "首尾帧模式需要至少 1 张图片作为首帧;请上传图片,或切换到 Wan 3.0 多图参考。";
|
|
if (imageCount > 2) return "首尾帧模式最多支持 2 张图片;请切换到 Wan 3.0 多图参考,或移除多余图片。";
|
|
return null;
|
|
}
|
|
if (imageCount > 10) return "Wan 3.0 多图参考最多支持 10 张图片;请移除多余图片。";
|
|
return null;
|
|
}
|
|
|
|
export function videoImageFileError(selection: VideoInputSelection, file: Pick<File, "name" | "size" | "type">): string | null {
|
|
if (selection.engine === "seedance" || selection.engine === "bailian" && selection.model === BAILIAN_27_VIDEO_MODEL) return null;
|
|
const format = file.name.split(".").pop()?.toLowerCase() || file.type.split("/").pop()?.toLowerCase() || "";
|
|
const isMinimax = selection.engine === "minimax";
|
|
const formats = isMinimax ? ["jpg", "jpeg", "png", "webp", "heic", "heif"] : ["jpg", "jpeg", "png", "bmp", "webp"];
|
|
const maxBytes = (isMinimax ? 30 : 20) * 1024 * 1024;
|
|
const modelLabel = isMinimax ? "MiniMax H3" : "Wan 3.0";
|
|
if (!formats.includes(format)) {
|
|
return `${modelLabel} 不支持「${file.name}」的格式;请转换为 ${isMinimax ? "JPG、PNG、WEBP、HEIC 或 HEIF" : "JPG、PNG、BMP 或 WEBP"} 后上传。`;
|
|
}
|
|
if (file.size > maxBytes) return `${modelLabel} 的单张图片不能超过 ${isMinimax ? 30 : 20} MB;请压缩「${file.name}」后重试。`;
|
|
return null;
|
|
}
|