ai-chatbot/lib/video-canvas/smart-edit/highlight-contract.ts

44 lines
2.5 KiB
TypeScript
Raw Permalink 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 { z } from "zod";
import type { EditCandidate } from "./contract";
export const MIN_SEQUENCE_MATCH_SCORE = 60;
export class HighlightValidationError extends Error {
constructor(message: string) { super(message); this.name = "HighlightValidationError"; }
}
const highlightResultSchema = z.object({
selections: z.array(z.object({
id: z.string(),
startSeconds: z.number().finite().min(0),
transition: z.enum(["cut", "fade"]),
reason: z.string().trim().min(1).max(300),
matchScore: z.number().finite().min(0).max(100),
visualIssues: z.array(z.string().trim().min(1).max(160)).max(10).default([]),
})).min(1).max(12),
summary: z.string().max(1000).default(""),
});
export type SequenceHighlight = z.infer<typeof highlightResultSchema>["selections"][number];
export function validateSequenceHighlights(value: unknown, candidates: EditCandidate[], shotDurations: number[]) {
const parsed = highlightResultSchema.safeParse(value);
if (!parsed.success) throw new HighlightValidationError("视频高光分析格式无效,未提交成片合成");
const result = parsed.data;
if (shotDurations.length !== candidates.length || result.selections.length !== candidates.length ||
new Set(result.selections.map(item => item.id)).size !== candidates.length ||
result.selections.some((item, index) => item.id !== candidates[index].id))
throw new HighlightValidationError("视频高光分析遗漏、重复或更改了分镜顺序,未提交成片合成");
for (const [index, item] of result.selections.entries()) {
const available = (candidates[index].end - candidates[index].start) / 1_000_000;
const wanted = shotDurations[index];
if (!Number.isFinite(wanted) || wanted <= 0 || item.startSeconds + wanted > available + 0.001)
throw new HighlightValidationError(`镜头 ${index + 1} 的高光区间超出真实视频长度,请重新选片`);
if (index === 0 && item.transition !== "cut")
throw new HighlightValidationError("首镜头的转场分析无效,请重新选片");
if (item.visualIssues.length)
throw new HighlightValidationError(`镜头 ${index + 1} 存在画面违规:${item.visualIssues.join(";")}。请替换或重新生成该镜头后再合成`);
if (item.matchScore < MIN_SEQUENCE_MATCH_SCORE)
throw new HighlightValidationError(`镜头 ${index + 1} 未达到需求匹配门槛(${item.matchScore}/${MIN_SEQUENCE_MATCH_SCORE}):${item.reason}。请替换或重新生成该镜头后再合成`);
}
return result;
}