ai-chatbot/lib/ai/bltcy-video-models.ts
Your Name d6d8bf021f
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
feat: add bltcy unified video provider
2026-04-23 18:24:39 +08:00

551 lines
18 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
recommendedVideoDurationOptions,
recommendedVideoDurationReferenceCosts,
recommendedVideoResolutionBaseCosts,
} from "@/lib/ai/video-model-config";
export type BltcyVideoModelPreset = {
modelId: string;
displayName: string;
description: string;
family: string;
supportsVision: boolean;
supportsImageGen: boolean;
capabilities?: Record<string, any>;
defaultParams: Record<string, any>;
imageGenConfig?: Record<string, any>;
sortOrder: number;
};
type BltcyVideoMode =
| "text-to-video"
| "first-frame"
| "first-last-frame"
| "reference-images";
type BltcyVideoResolution = "480p" | "720p" | "1080p";
type ModelDefinition = {
sortOrder: number;
modelId: string;
displayName: string;
family: string;
providerName: string;
summary: string;
supportedModes: BltcyVideoMode[];
supportedRatios?: string[];
supportedResolutions?: BltcyVideoResolution[];
durationOptions?: number[];
priceNote?: string;
};
const TRAILING_SLASHES_REGEX = /\/+$/;
const TRAILING_V2_REGEX = /\/v2$/i;
export const BLTCY_VIDEO_BASE_URL = "https://api.bltcy.ai";
export const BLTCY_VIDEO_PRICE_PAGE_URL =
"https://api.bltcy.ai/models?category=%E8%A7%86%E9%A2%91";
export const BLTCY_VIDEO_UNIFIED_DOC_URL =
"https://gpt-best.apifox.cn/doc-7324259";
export const BLTCY_VIDEO_PRICE_CHECKED_AT = "2026-04-23";
export const BLTCY_VIDEO_PROVIDER_PRESET = {
name: "柏拉图统一视频",
type: "bltcy-video" as const,
baseUrl: BLTCY_VIDEO_BASE_URL,
};
const STANDARD_VIDEO_RATIOS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"];
const SEEDANCE_VIDEO_RATIOS = ["16:9", "9:16", "1:1"];
const STANDARD_VIDEO_RESOLUTIONS: BltcyVideoResolution[] = [
"480p",
"720p",
"1080p",
];
const HD_VIDEO_RESOLUTIONS: BltcyVideoResolution[] = ["720p", "1080p"];
function createModeConstraints(
modes: BltcyVideoMode[],
ratios: string[],
resolutions: BltcyVideoResolution[],
durations: number[]
) {
return modes.reduce<Record<string, any>>((acc, mode) => {
acc[mode] = {
ratioOptions: ratios,
durationOptions: durations,
resolutionOptions: resolutions,
defaults: {
mode,
ratio: ratios.includes("16:9") ? "16:9" : ratios[0],
duration: durations.includes(5) ? 5 : durations[0],
resolution: resolutions.includes("720p") ? "720p" : resolutions[0],
},
};
return acc;
}, {});
}
function createPreset(definition: ModelDefinition): BltcyVideoModelPreset {
const supportedRatios =
definition.supportedRatios && definition.supportedRatios.length > 0
? definition.supportedRatios
: STANDARD_VIDEO_RATIOS;
const supportedResolutions =
definition.supportedResolutions && definition.supportedResolutions.length > 0
? definition.supportedResolutions
: STANDARD_VIDEO_RESOLUTIONS;
const durationOptions =
definition.durationOptions && definition.durationOptions.length > 0
? definition.durationOptions
: [...recommendedVideoDurationOptions];
const supportsVision = definition.supportedModes.some((mode) => mode !== "text-to-video");
return {
modelId: definition.modelId,
displayName: definition.displayName,
description: `${definition.displayName},柏拉图统一视频接口模型(${definition.providerName} / ${definition.family})。${definition.summary}${
definition.priceNote ? ` ${definition.priceNote}` : ""
},实际计费以柏拉图价格页为准。`,
family: definition.family,
supportsVision,
supportsImageGen: false,
capabilities: {
provider: "bltcy",
family: definition.family,
apiFormat: "bltcy-unified-video",
supportedModes: definition.supportedModes,
supportedRatios,
supportedResolutions,
durationRange: {
min: Math.min(...durationOptions),
max: Math.max(...durationOptions),
},
durationOptions,
constraints: createModeConstraints(
definition.supportedModes,
supportedRatios,
supportedResolutions,
durationOptions
),
maxReferenceImages: definition.supportedModes.includes("reference-images")
? 8
: definition.supportedModes.includes("first-last-frame")
? 2
: definition.supportedModes.includes("first-frame")
? 1
: 0,
supportReturnLastFrame: definition.supportedModes.includes("first-last-frame"),
supportSeed: false,
endpoints: {
submit: "/v2/videos/generations",
task: "/v2/videos/generations/{task_id}",
},
docs: BLTCY_VIDEO_UNIFIED_DOC_URL,
pricePage: BLTCY_VIDEO_PRICE_PAGE_URL,
priceCheckedAt: BLTCY_VIDEO_PRICE_CHECKED_AT,
},
defaultParams: {
provider: "bltcy",
family: definition.family,
kind: "video",
apiFormat: "bltcy-unified-video",
submitEndpoint: "/v2/videos/generations",
taskEndpoint: "/v2/videos/generations/{task_id}",
docs: BLTCY_VIDEO_UNIFIED_DOC_URL,
pricePage: BLTCY_VIDEO_PRICE_PAGE_URL,
priceCheckedAt: BLTCY_VIDEO_PRICE_CHECKED_AT,
supportedModes: definition.supportedModes,
supportsVision,
providerName: definition.providerName,
},
imageGenConfig: {
creditCostPerVideo: recommendedVideoResolutionBaseCosts["480p"],
videoDurationOptions: durationOptions,
creditCostPerVideoByDuration: recommendedVideoDurationReferenceCosts,
creditCostPerVideoByResolution: recommendedVideoResolutionBaseCosts,
enableLoadingPlaceholder: true,
loadingColor: "cyan",
},
sortOrder: definition.sortOrder,
};
}
export function normalizeBltcyVideoBaseUrl(value?: string | null) {
const normalized = String(value || "")
.trim()
.replace(TRAILING_SLASHES_REGEX, "")
.replace(TRAILING_V2_REGEX, "");
return normalized || BLTCY_VIDEO_BASE_URL;
}
export function isBltcyVideoBaseUrl(value?: string | null) {
const normalized = normalizeBltcyVideoBaseUrl(value);
return normalized === BLTCY_VIDEO_BASE_URL;
}
const MODEL_DEFINITIONS: ModelDefinition[] = [
{
sortOrder: 10,
modelId: "veo3.1",
displayName: "Veo 3.1",
family: "veo",
providerName: "Google",
summary: "支持文生视频、图生视频和多参考图输入的通用 Veo 3.1 模型。",
supportedModes: ["text-to-video", "first-frame", "first-last-frame", "reference-images"],
supportedRatios: STANDARD_VIDEO_RATIOS,
supportedResolutions: HD_VIDEO_RESOLUTIONS,
durationOptions: [4, 5, 6, 8],
priceNote: "柏拉图当前页为按次计费模型。",
},
{
sortOrder: 20,
modelId: "veo3.1-fast",
displayName: "Veo 3.1 Fast",
family: "veo",
providerName: "Google",
summary: "偏速度优先的 Veo 3.1 Fast,适合快速出样。",
supportedModes: ["text-to-video", "first-frame", "first-last-frame", "reference-images"],
supportedRatios: STANDARD_VIDEO_RATIOS,
supportedResolutions: HD_VIDEO_RESOLUTIONS,
durationOptions: [4, 5, 6, 8],
priceNote: "柏拉图当前页为按次计费模型。",
},
{
sortOrder: 30,
modelId: "veo3.1-pro",
displayName: "Veo 3.1 Pro",
family: "veo",
providerName: "Google",
summary: "质量优先的 Veo 3.1 Pro。",
supportedModes: ["text-to-video", "first-frame", "first-last-frame", "reference-images"],
supportedRatios: STANDARD_VIDEO_RATIOS,
supportedResolutions: HD_VIDEO_RESOLUTIONS,
durationOptions: [4, 5, 6, 8],
priceNote: "柏拉图当前页为按次计费模型。",
},
{
sortOrder: 40,
modelId: "veo3.1-pro-4k",
displayName: "Veo 3.1 Pro 4K",
family: "veo",
providerName: "Google",
summary: "4K 版本 Veo 3.1 Pro,当前项目侧仍沿用统一分辨率控件。",
supportedModes: ["text-to-video", "first-frame", "first-last-frame", "reference-images"],
supportedRatios: STANDARD_VIDEO_RATIOS,
supportedResolutions: ["1080p"],
durationOptions: [4, 5, 6, 8],
priceNote: "柏拉图当前页为按次计费模型。",
},
{
sortOrder: 50,
modelId: "veo3.1-components",
displayName: "Veo 3.1 Components",
family: "veo",
providerName: "Google",
summary: "组件化 Veo 3.1 版本,适合多参考图驱动。",
supportedModes: ["text-to-video", "first-frame", "first-last-frame", "reference-images"],
supportedRatios: STANDARD_VIDEO_RATIOS,
supportedResolutions: HD_VIDEO_RESOLUTIONS,
durationOptions: [4, 5, 6, 8],
priceNote: "柏拉图当前页为按次计费模型。",
},
{
sortOrder: 100,
modelId: "doubao-seedance-1-0-lite-t2v-250428",
displayName: "Seedance 1.0 Lite T2V",
family: "seedance",
providerName: "火山豆包",
summary: "轻量文生视频模型。",
supportedModes: ["text-to-video"],
supportedRatios: SEEDANCE_VIDEO_RATIOS,
supportedResolutions: STANDARD_VIDEO_RESOLUTIONS,
durationOptions: [5, 10],
priceNote: "柏拉图当前页为阶梯/按秒计费。",
},
{
sortOrder: 110,
modelId: "doubao-seedance-1-0-lite-i2v-250428",
displayName: "Seedance 1.0 Lite I2V",
family: "seedance",
providerName: "火山豆包",
summary: "轻量图生视频模型。",
supportedModes: ["first-frame"],
supportedRatios: SEEDANCE_VIDEO_RATIOS,
supportedResolutions: STANDARD_VIDEO_RESOLUTIONS,
durationOptions: [5, 10],
priceNote: "柏拉图当前页为阶梯/按秒计费。",
},
{
sortOrder: 120,
modelId: "doubao-seedance-1-0-pro-250528",
displayName: "Seedance 1.0 Pro",
family: "seedance",
providerName: "火山豆包",
summary: "Seedance Pro 通用视频模型。",
supportedModes: ["text-to-video", "first-frame", "first-last-frame", "reference-images"],
supportedRatios: SEEDANCE_VIDEO_RATIOS,
supportedResolutions: STANDARD_VIDEO_RESOLUTIONS,
durationOptions: [5, 10],
priceNote: "柏拉图当前页为阶梯/按秒计费。",
},
{
sortOrder: 130,
modelId: "doubao-seedance-1-0-pro-fast-251015",
displayName: "Seedance 1.0 Pro Fast",
family: "seedance",
providerName: "火山豆包",
summary: "速度优先的 Seedance Pro Fast。",
supportedModes: ["text-to-video", "first-frame", "first-last-frame", "reference-images"],
supportedRatios: SEEDANCE_VIDEO_RATIOS,
supportedResolutions: STANDARD_VIDEO_RESOLUTIONS,
durationOptions: [5, 10],
priceNote: "柏拉图当前页为阶梯/按秒计费。",
},
{
sortOrder: 140,
modelId: "doubao-seedance-1-5-pro-251215",
displayName: "Seedance 1.5 Pro",
family: "seedance",
providerName: "火山豆包",
summary: "更高质量的 Seedance 1.5 Pro。",
supportedModes: ["text-to-video", "first-frame", "first-last-frame", "reference-images"],
supportedRatios: SEEDANCE_VIDEO_RATIOS,
supportedResolutions: STANDARD_VIDEO_RESOLUTIONS,
durationOptions: [5, 10],
priceNote: "柏拉图当前页为阶梯/按秒计费。",
},
{
sortOrder: 150,
modelId: "doubao-seedance-2-0-260128",
displayName: "Seedance 2.0",
family: "seedance",
providerName: "火山豆包",
summary: "Seedance 2.0 通用视频模型。",
supportedModes: ["text-to-video", "first-frame", "first-last-frame", "reference-images"],
supportedRatios: SEEDANCE_VIDEO_RATIOS,
supportedResolutions: STANDARD_VIDEO_RESOLUTIONS,
durationOptions: [5, 10],
priceNote: "柏拉图当前页为按秒计费。",
},
{
sortOrder: 160,
modelId: "doubao-seedance-2-0-fast-260128",
displayName: "Seedance 2.0 Fast",
family: "seedance",
providerName: "火山豆包",
summary: "速度优先的 Seedance 2.0 Fast。",
supportedModes: ["text-to-video", "first-frame", "first-last-frame", "reference-images"],
supportedRatios: SEEDANCE_VIDEO_RATIOS,
supportedResolutions: STANDARD_VIDEO_RESOLUTIONS,
durationOptions: [5, 10],
priceNote: "柏拉图当前页为按秒计费。",
},
{
sortOrder: 200,
modelId: "wanx2.1-t2v-plus",
displayName: "WanX 2.1 T2V Plus",
family: "wan",
providerName: "Aliyun(Qwen)",
summary: "万相 2.1 文生视频模型。",
supportedModes: ["text-to-video"],
durationOptions: [5, 10],
priceNote: "柏拉图当前页为按次计费。",
},
{
sortOrder: 210,
modelId: "wanx2.1-t2v-turbo",
displayName: "WanX 2.1 T2V Turbo",
family: "wan",
providerName: "Aliyun(Qwen)",
summary: "万相 2.1 文生视频极速版。",
supportedModes: ["text-to-video"],
durationOptions: [5, 10],
priceNote: "柏拉图当前页为按次计费。",
},
{
sortOrder: 220,
modelId: "wanx2.1-i2v-plus",
displayName: "WanX 2.1 I2V Plus",
family: "wan",
providerName: "Aliyun(Qwen)",
summary: "万相 2.1 图生视频模型。",
supportedModes: ["first-frame"],
durationOptions: [5, 10],
priceNote: "柏拉图当前页为按次计费。",
},
{
sortOrder: 230,
modelId: "wanx2.1-i2v-turbo",
displayName: "WanX 2.1 I2V Turbo",
family: "wan",
providerName: "Aliyun(Qwen)",
summary: "万相 2.1 图生视频极速版。",
supportedModes: ["first-frame"],
durationOptions: [5, 10],
priceNote: "柏拉图当前页为按次计费。",
},
{
sortOrder: 240,
modelId: "wanx2.1-kf2v-plus",
displayName: "WanX 2.1 KF2V Plus",
family: "wan",
providerName: "Aliyun(Qwen)",
summary: "万相 2.1 关键帧视频模型,适合多图/关键帧驱动。",
supportedModes: ["first-last-frame", "reference-images", "first-frame"],
durationOptions: [5, 10],
priceNote: "柏拉图当前页为按次计费。",
},
{
sortOrder: 250,
modelId: "wanx2.1-vace-plus",
displayName: "WanX 2.1 VACE Plus",
family: "wan",
providerName: "Aliyun(Qwen)",
summary: "万相 2.1 视频编辑类模型,可结合参考图/视频使用。",
supportedModes: ["reference-images", "first-frame", "text-to-video"],
durationOptions: [5, 10],
priceNote: "柏拉图当前页为按次计费。",
},
{
sortOrder: 260,
modelId: "wan2.2-t2v-plus",
displayName: "Wan 2.2 T2V Plus",
family: "wan",
providerName: "Aliyun(Qwen)",
summary: "万相 2.2 文生视频模型。",
supportedModes: ["text-to-video"],
durationOptions: [5, 10],
priceNote: "柏拉图当前页为阶梯/按次计费。",
},
{
sortOrder: 270,
modelId: "wan2.2-i2v-plus",
displayName: "Wan 2.2 I2V Plus",
family: "wan",
providerName: "Aliyun(Qwen)",
summary: "万相 2.2 图生视频模型。",
supportedModes: ["first-frame"],
durationOptions: [5, 10],
priceNote: "柏拉图当前页为阶梯/按次计费。",
},
{
sortOrder: 280,
modelId: "wan2.2-i2v-flash",
displayName: "Wan 2.2 I2V Flash",
family: "wan",
providerName: "Aliyun(Qwen)",
summary: "万相 2.2 图生视频极速版。",
supportedModes: ["first-frame"],
durationOptions: [5, 10],
priceNote: "柏拉图当前页为阶梯/按次计费。",
},
{
sortOrder: 290,
modelId: "wan2.2-kf2v-flash",
displayName: "Wan 2.2 KF2V Flash",
family: "wan",
providerName: "Aliyun(Qwen)",
summary: "万相 2.2 关键帧视频极速版。",
supportedModes: ["first-last-frame", "reference-images", "first-frame"],
durationOptions: [5, 10],
priceNote: "柏拉图当前页为阶梯/按次计费。",
},
{
sortOrder: 300,
modelId: "wan2.2-s2v",
displayName: "Wan 2.2 S2V",
family: "wan",
providerName: "Aliyun(Qwen)",
summary: "万相 2.2 视频生成模型。",
supportedModes: ["text-to-video", "first-frame", "reference-images"],
durationOptions: [5, 10],
priceNote: "柏拉图当前页为按次计费。",
},
{
sortOrder: 310,
modelId: "wan2.2-animate-mix",
displayName: "Wan 2.2 Animate Mix",
family: "wan",
providerName: "Aliyun(Qwen)",
summary: "万相 2.2 动画类视频模型。",
supportedModes: ["reference-images", "first-frame", "text-to-video"],
durationOptions: [5, 10],
priceNote: "柏拉图当前页为按次计费。",
},
{
sortOrder: 320,
modelId: "wan2.2-animate-move",
displayName: "Wan 2.2 Animate Move",
family: "wan",
providerName: "Aliyun(Qwen)",
summary: "万相 2.2 动画运动类视频模型。",
supportedModes: ["reference-images", "first-frame", "text-to-video"],
durationOptions: [5, 10],
priceNote: "柏拉图当前页为阶梯/按次计费。",
},
{
sortOrder: 330,
modelId: "wan2.5-t2v-preview",
displayName: "Wan 2.5 T2V Preview",
family: "wan",
providerName: "Aliyun(Qwen)",
summary: "万相 2.5 文生视频预览版。",
supportedModes: ["text-to-video"],
supportedResolutions: HD_VIDEO_RESOLUTIONS,
durationOptions: [5, 10],
priceNote: "柏拉图当前页为阶梯/按次计费。",
},
{
sortOrder: 340,
modelId: "wan2.5-i2v-preview",
displayName: "Wan 2.5 I2V Preview",
family: "wan",
providerName: "Aliyun(Qwen)",
summary: "万相 2.5 图生视频预览版。",
supportedModes: ["first-frame"],
supportedResolutions: HD_VIDEO_RESOLUTIONS,
durationOptions: [5, 10],
priceNote: "柏拉图当前页为阶梯/按次计费。",
},
{
sortOrder: 350,
modelId: "wan2.6-t2v",
displayName: "Wan 2.6 T2V",
family: "wan",
providerName: "Aliyun(Qwen)",
summary: "万相 2.6 文生视频模型。",
supportedModes: ["text-to-video"],
supportedResolutions: HD_VIDEO_RESOLUTIONS,
durationOptions: [5, 10, 15],
priceNote: "柏拉图当前页为按次计费。",
},
{
sortOrder: 360,
modelId: "wan2.6-i2v",
displayName: "Wan 2.6 I2V",
family: "wan",
providerName: "Aliyun(Qwen)",
summary: "万相 2.6 图生视频模型。",
supportedModes: ["first-frame"],
supportedResolutions: HD_VIDEO_RESOLUTIONS,
durationOptions: [5, 10, 15],
priceNote: "柏拉图当前页为按次计费。",
},
{
sortOrder: 370,
modelId: "wan2.6-r2v",
displayName: "Wan 2.6 R2V",
family: "wan",
providerName: "Aliyun(Qwen)",
summary: "万相 2.6 参考驱动视频模型。",
supportedModes: ["reference-images", "first-frame"],
supportedResolutions: HD_VIDEO_RESOLUTIONS,
durationOptions: [5, 10, 15],
priceNote: "柏拉图当前页为按次计费。",
},
];
export const BLTCY_VIDEO_MODEL_PRESETS: BltcyVideoModelPreset[] =
MODEL_DEFINITIONS.map(createPreset);