48 lines
2.6 KiB
TypeScript
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("供应商当前清晰度不支持所选视频时长,请调整镜头时长");
|
|
}
|
|
}
|