ai-chatbot/lib/ai/vip98k-video-parameters.ts

48 lines
2.6 KiB
TypeScript

function object(value: unknown): Record<string, any> {
return value && typeof value === "object" && !Array.isArray(value) ? value as Record<string, any> : {};
}
export function canonicalVip98kVideoRatio(value: string) {
return value === "landscape" ? "16:9" : value === "portrait" ? "9:16" : value;
}
export function vip98kVideoDurationBounds(schema: unknown, resolution?: string) {
let min = 0, max = Infinity;
let durations: number[] | undefined;
const visit = (value: unknown) => {
const current = object(value), properties = object(current.properties);
const field = object(properties.duration_seconds || properties.duration);
if (Number.isFinite(field.minimum)) min = Math.max(min, field.minimum);
if (Number.isFinite(field.maximum)) max = Math.min(max, field.maximum);
const allowed = Array.isArray(field.enum) ? field.enum : Number.isFinite(field.const) ? [field.const] : undefined;
if (allowed) {
const numbers = allowed.filter((n: unknown): n is number => typeof n === "number" && Number.isFinite(n) && n > 0);
durations = durations ? durations.filter(n => numbers.includes(n)) : numbers;
}
for (const child of Array.isArray(current.allOf) ? current.allOf : []) visit(child);
const condition = object(object(current.if).properties).resolution;
if (resolution && object(condition).const === resolution) visit(current.then);
};
visit(schema);
return { min, max, durations };
}
export function mapVip98kVideoParameters(body: Record<string, unknown>, schema: unknown) {
const properties = object(object(schema).properties);
const ratios = object(properties.aspect_ratio).enum;
if (Array.isArray(ratios) && !ratios.includes(body.aspect_ratio)) {
const alias = body.aspect_ratio === "16:9" ? "landscape" : body.aspect_ratio === "9:16" ? "portrait" : undefined;
if (!alias || !ratios.includes(alias)) throw Error("供应商当前线路不支持所选视频比例");
body.aspect_ratio = alias;
}
const resolutions = object(properties.resolution).enum;
if (body.resolution && Array.isArray(resolutions) && !resolutions.includes(body.resolution))
throw Error("供应商当前线路不支持所选视频清晰度,请同步模型规格后重试");
const seconds = Number(body.duration_seconds ?? body.duration);
if (seconds) {
const bounds = vip98kVideoDurationBounds(schema, String(body.resolution || ""));
if (seconds < bounds.min || seconds > bounds.max || (bounds.durations && !bounds.durations.includes(seconds)))
throw Error("供应商当前清晰度不支持所选视频时长,请调整镜头时长");
}
}