fix(canvas): 分镜脚本 - 补齐拆镜输出契约并让镜头数与每镜时长生效

This commit is contained in:
medivh committed 2026-09-30 11:13:54 +08:00
1 parent 74e7ebed8f
commit 45e51b1df5
4 files changed
+61 -7

No files matched your search

@@ -17,6 +17,7 @@ import {
expandStoryboardTextMentions,
storyboardRowsFromTask,
storyboardPromptTemplateMetadata,
withStoryboardOutputContract,
} from "@/lib/canvas/canvas-project-domain";
import { buildNodeMentionReferences } from "@/lib/canvas/canvas-resource-references";
import { buildStoryboardAssetCatalog } from "@/lib/canvas/canvas-storyboard-assets";
@@ -168,16 +169,18 @@ export function useCanvasStoryboard({
assertCurrent();
setNodes((current) => current.map((node) => node.id === nodeId ? { ...node, metadata: { ...node.metadata, composerContent: prompt, status: NODE_STATUS_LOADING, taskStage: "正在创建任务", taskProgress: 0, errorDetails: undefined, ...skillExecution.metadata } } : node));
assertCurrent();
// 输入框内容只是剧情,拆镜要求与镜头数、每镜时长都必须随契约一起发出去。
const storyboardPrompt = withStoryboardOutputContract(skillExecution.prompt, { shotCount: requestedShotCount, shotDurationSeconds });
const request = {
projectId,
type: "canvas_text",
operation: "storyboard",
prompt: skillExecution.prompt,
prompt: storyboardPrompt,
model: generationConfig.model,
...(logicalModelIDForConfig(generationConfig) ? { logicalModelId: logicalModelIDForConfig(generationConfig) } : {}),
input: {
mode: "text",
prompt: skillExecution.prompt,
prompt: storyboardPrompt,
canvasAssets: buildStoryboardAssetCatalog(nodesRef.current),
requirements: "输出可直接编辑并用于批量生成图片和视频的分镜表。",
projectStyle: storyboardContext.projectStyle,
@@ -1,6 +1,6 @@
import { runBackendCanvasGenerationTask } from "@/lib/canvas/canvas-project-generation";
import { PromptTemplateOperation, promptTemplateTaskPlaceholder } from "@/lib/prompts";
import { storyboardRowsFromTask, storyboardRowsOutputContract } from "@/lib/canvas/canvas-project-domain";
import { storyboardRowsFromTask, withStoryboardOutputContract } from "@/lib/canvas/canvas-project-domain";
import { parseChapterAssetBreakdown, type ChapterAssetBreakdown } from "@/lib/canvas/chapter-asset-breakdown";
import { parseCharacterBreakdown } from "@/lib/canvas/canvas-character-reference";
import { backendProviderConfig, parseBackendGenerationResult } from "@/services/api/generation-task";
@@ -91,10 +91,7 @@ export async function generateChapterStoryboard(input: ChapterStoryboardGenerati
selectedSkillIds: input.selectedSkillIds,
});
// 技能上下文只描述工作流,不会约束输出结构;必须显式带上输出契约,否则模型返回 Markdown 表格。
const prompt = [
skillExecution.prompt,
storyboardRowsOutputContract("每个镜头必须能独立用于生成首帧图片和镜头视频。"),
].join("\n\n");
const prompt = withStoryboardOutputContract(skillExecution.prompt);
const task = await createGenerationTask({
projectId: input.projectId,
type: "canvas_text",