feat(canvas): 媒体产出模型与选用模型分离 (#597)
Co-authored-by: ddcat666 <26564566+ddcat666@users.noreply.github.com>
This commit is contained in:
1 parent
a89bd4aead
commit
357450e52c
28 files changed
+367
-52
No files matched your search
@@ -8,6 +8,7 @@ import { nodeSizeFromRatio } from "@/lib/canvas/canvas-node-size";
|
||||
import { canvasImageReferenceLimitError, buildImageGenerationMetadata, getGenerationCount, isGenerationCanceled, resetGenerationTaskMetadata, runCanvasGenerationTaskToConsumer } from "@/lib/canvas/canvas-project-generation";
|
||||
import { imageGenerationReferenceConnections } from "@/lib/canvas/canvas-resource-references";
|
||||
import { canvasGenerationPromptMetadata } from "@/lib/canvas/canvas-generation-submission";
|
||||
import { commitProducedModel } from "@/lib/canvas/produced-model";
|
||||
import { CONTENT_MODERATION_ERROR_CODE, generationFailureMetadata, type GenerationFailureMetadata } from "@/lib/generation-error";
|
||||
import { CanvasNodeType, type CanvasNodeData } from "@/types/canvas";
|
||||
import { useCanvasStore } from "@/stores/canvas/use-canvas-store";
|
||||
@@ -227,18 +228,21 @@ export async function executeImageGeneration({
|
||||
? {
|
||||
...node,
|
||||
...geometry,
|
||||
metadata: {
|
||||
...node.metadata,
|
||||
content: child.metadata?.content,
|
||||
storageKey: child.metadata?.storageKey,
|
||||
mimeType: child.metadata?.mimeType,
|
||||
bytes: child.metadata?.bytes,
|
||||
naturalWidth: child.metadata?.naturalWidth,
|
||||
naturalHeight: child.metadata?.naturalHeight,
|
||||
assetId: child.metadata?.assetId,
|
||||
primaryImageId: targetId,
|
||||
status: NODE_STATUS_SUCCESS,
|
||||
},
|
||||
metadata: commitProducedModel(
|
||||
{
|
||||
...node.metadata,
|
||||
content: child.metadata?.content,
|
||||
storageKey: child.metadata?.storageKey,
|
||||
mimeType: child.metadata?.mimeType,
|
||||
bytes: child.metadata?.bytes,
|
||||
naturalWidth: child.metadata?.naturalWidth,
|
||||
naturalHeight: child.metadata?.naturalHeight,
|
||||
assetId: child.metadata?.assetId,
|
||||
primaryImageId: targetId,
|
||||
status: NODE_STATUS_SUCCESS,
|
||||
},
|
||||
child.metadata?.producedModel,
|
||||
),
|
||||
}
|
||||
: node,
|
||||
);
|
||||
|
||||
@@ -6,6 +6,7 @@ import { nodeSizeFromRatio } from "@/lib/canvas/canvas-node-size";
|
||||
import { nextCanvasVersionLabel } from "@/lib/canvas/canvas-layout";
|
||||
import { buildAudioGenerationMetadata, buildVideoGenerationMetadata, generationReferenceUrls, runCanvasGenerationTaskToConsumer } from "@/lib/canvas/canvas-project-generation";
|
||||
import { canvasGenerationPromptMetadata } from "@/lib/canvas/canvas-generation-submission";
|
||||
import { producedModelCandidateForGeneration } from "@/lib/canvas/produced-model";
|
||||
import { CanvasNodeType, type CanvasNodeData } from "@/types/canvas";
|
||||
|
||||
import type { CanvasGenerationExecution } from "./canvas-generation-executor-types";
|
||||
@@ -58,6 +59,7 @@ export async function executeVideoGeneration({
|
||||
resourceReloadAvailable: undefined,
|
||||
failedPromptFingerprint: undefined,
|
||||
model: generationConfig.model,
|
||||
producedModelCandidate: producedModelCandidateForGeneration(generationConfig),
|
||||
size: generationConfig.size,
|
||||
seconds: generationConfig.videoSeconds,
|
||||
vquality: generationConfig.vquality,
|
||||
|
||||
@@ -152,7 +152,7 @@ export function useCanvasDirector({
|
||||
position: existingPreview?.position || { x: sourceNode.position.x - previewSize.width - 36, y: sourceNode.position.y },
|
||||
width: previewSize.width,
|
||||
height: previewSize.height,
|
||||
metadata: { ...existingPreview?.metadata, ...imageMetadata(image), prompt: output.prompt, workflowKind: "reference_set", assetTags: ["导演台构图", `镜头:${sourceNode.title}`] },
|
||||
metadata: { ...existingPreview?.metadata, ...imageMetadata(image), prompt: output.prompt, workflowKind: "reference_set", assetTags: ["导演台构图", `镜头:${sourceNode.title}`], producedModel: undefined, producedModelCandidate: undefined },
|
||||
};
|
||||
if (previewIndex >= 0) nextNodes[previewIndex] = previewNode;
|
||||
else nextNodes.push(previewNode);
|
||||
@@ -170,7 +170,7 @@ export function useCanvasDirector({
|
||||
position: existingVideo?.position || { x: sourceNode.position.x, y: sourceNode.position.y + sourceNode.height + 48 },
|
||||
width: existingVideo?.width || 360,
|
||||
height: existingVideo?.height || 220,
|
||||
metadata: { ...existingVideo?.metadata, ...videoMetadata(videoUpload), prompt: output.prompt, workflowKind: "reference_video", assetTags: ["导演台白膜", `镜头:${sourceNode.title}`] },
|
||||
metadata: { ...existingVideo?.metadata, ...videoMetadata(videoUpload), prompt: output.prompt, workflowKind: "reference_video", assetTags: ["导演台白膜", `镜头:${sourceNode.title}`], producedModel: undefined, producedModelCandidate: undefined },
|
||||
};
|
||||
if (videoIndex >= 0) nextNodes[videoIndex] = videoNode;
|
||||
else nextNodes.push(videoNode);
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useCallback, type Dispatch, type SetStateAction } from "react";
|
||||
import { App } from "antd";
|
||||
|
||||
import { buildNodeGenerationContext, hydrateNodeGenerationContext } from "@/components/canvas/canvas-node-generation";
|
||||
import { producedModelCandidateForGeneration } from "@/lib/canvas/produced-model";
|
||||
import type { CanvasNodeGenerationMode } from "@/components/canvas/canvas-node-prompt-panel";
|
||||
import { buildEmotionImageArtifacts, emotionGenerationSize, emotionProviderMask, normalizeEmotionPromptForProvider, resolveEmotionEditPlan } from "@/lib/canvas/canvas-emotion";
|
||||
import {
|
||||
@@ -289,6 +290,7 @@ export function useCanvasGenerationRetry({
|
||||
...item.metadata,
|
||||
prompt: mediaPrompt,
|
||||
model: generationConfig.model,
|
||||
producedModelCandidate: producedModelCandidateForGeneration(generationConfig),
|
||||
size: generationConfig.size,
|
||||
seconds: generationConfig.videoSeconds,
|
||||
vquality: generationConfig.vquality,
|
||||
@@ -388,6 +390,7 @@ export function useCanvasGenerationRetry({
|
||||
? {
|
||||
generationType: savedImageMetadata.generationType,
|
||||
model: generationConfig.model,
|
||||
producedModelCandidate: producedModelCandidateForGeneration(generationConfig),
|
||||
size: generationConfig.size,
|
||||
quality: generationConfig.quality,
|
||||
transparentBackground: generationConfig.transparentBackground,
|
||||
|
||||
@@ -20,6 +20,7 @@ import { NODE_DEFAULT_SIZE } from "@/constant/canvas";
|
||||
import { cropDataUrl, splitDataUrl, upscaleDataUrl } from "@/lib/canvas/canvas-image-data";
|
||||
import { isValidGridSplit, layoutGridSplitCells } from "@/lib/canvas/canvas-grid-split";
|
||||
import { audioMetadata, imageMetadata, videoMetadata } from "@/lib/canvas/canvas-generation-task-sync";
|
||||
import { commitProducedModel } from "@/lib/canvas/produced-model";
|
||||
import { findAvailableGenerationGroupPosition, imageGenerationChildPosition, imageGenerationGroupSize } from "@/lib/canvas/canvas-generation-layout";
|
||||
import { canvasGenerationPromptMetadata } from "@/lib/canvas/canvas-generation-submission";
|
||||
import { cancelIncompleteImageBatch } from "@/lib/canvas/canvas-image-batch-retry";
|
||||
@@ -775,11 +776,11 @@ export function useCanvasMediaTools({
|
||||
const size = fitNodeSize(uploaded.width, uploaded.height, node.width, node.height);
|
||||
const currentNode = nodesRef.current.find((item) => item.id === targetId);
|
||||
if (!currentNode) throw new Error("局部编辑节点已被删除");
|
||||
const finalizedNode = { ...currentNode, width: size.width, height: size.height, metadata: { ...currentNode.metadata, ...imageMetadata(uploaded), prompt: effectivePrompt, ...generationMetadata } };
|
||||
const finalizedNode = { ...currentNode, width: size.width, height: size.height, metadata: commitProducedModel({ ...currentNode.metadata, ...imageMetadata(uploaded), prompt: effectivePrompt, ...generationMetadata }) };
|
||||
setNodes((current) => current.map((item) => {
|
||||
if (item.id === targetId) return finalizedNode;
|
||||
if (item.id !== rootId || requestedCount <= 1 || item.metadata?.primaryImageId) return item;
|
||||
return { ...item, width: size.width, height: size.height, metadata: { ...item.metadata, ...imageMetadata(uploaded), primaryImageId: targetId, status: NODE_STATUS_SUCCESS } };
|
||||
return { ...item, width: size.width, height: size.height, metadata: commitProducedModel({ ...item.metadata, ...imageMetadata(uploaded), primaryImageId: targetId, status: NODE_STATUS_SUCCESS }) };
|
||||
}));
|
||||
await persistMediaNodes([finalizedNode]);
|
||||
hasSuccess = true;
|
||||
@@ -872,7 +873,7 @@ export function useCanvasMediaTools({
|
||||
const size = fitNodeSize(uploaded.width, uploaded.height, node.width, node.height);
|
||||
const currentNode = nodesRef.current.find((item) => item.id === childId);
|
||||
if (!currentNode) throw new Error("图片编辑节点已被删除");
|
||||
const finalizedNode = { ...currentNode, width: size.width, height: size.height, metadata: { ...currentNode.metadata, ...imageMetadata(uploaded), prompt, status: NODE_STATUS_SUCCESS, ...generationMetadata } };
|
||||
const finalizedNode = { ...currentNode, width: size.width, height: size.height, metadata: commitProducedModel({ ...currentNode.metadata, ...imageMetadata(uploaded), prompt, status: NODE_STATUS_SUCCESS, ...generationMetadata }) };
|
||||
setNodes((current) => current.map((item) => item.id === childId ? finalizedNode : item));
|
||||
await persistMediaNodes([finalizedNode]);
|
||||
} catch (error) {
|
||||
@@ -965,7 +966,7 @@ export function useCanvasMediaTools({
|
||||
const size = fitNodeSize(uploaded.width, uploaded.height, node.width, node.height);
|
||||
const currentNode = nodesRef.current.find((item) => item.id === childId);
|
||||
if (!currentNode) throw new Error("标注编辑节点已被删除");
|
||||
const finalizedNode = { ...currentNode, width: size.width, height: size.height, metadata: { ...currentNode.metadata, ...imageMetadata(uploaded), prompt, status: NODE_STATUS_SUCCESS, ...generationMetadata } };
|
||||
const finalizedNode = { ...currentNode, width: size.width, height: size.height, metadata: commitProducedModel({ ...currentNode.metadata, ...imageMetadata(uploaded), prompt, status: NODE_STATUS_SUCCESS, ...generationMetadata }) };
|
||||
setNodes((current) => current.map((item) => item.id === childId ? finalizedNode : item));
|
||||
await persistMediaNodes([finalizedNode]);
|
||||
} catch (error) {
|
||||
@@ -1034,7 +1035,7 @@ export function useCanvasMediaTools({
|
||||
position: { x: position.x + (index % 2) * (size.width + 48), y: position.y + Math.floor(index / 2) * (size.height + 48) },
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
metadata: { ...imageMetadata(uploaded), prompt, status: NODE_STATUS_SUCCESS, pluginId: "image-tools", pluginNodeId: "layer-decomposition", pluginData: { layerIndex: index + 1, sourceNodeId: node.id }, ...generationMetadata },
|
||||
metadata: commitProducedModel({ ...imageMetadata(uploaded), prompt, status: NODE_STATUS_SUCCESS, pluginId: "image-tools", pluginNodeId: "layer-decomposition", pluginData: { layerIndex: index + 1, sourceNodeId: node.id }, ...generationMetadata }),
|
||||
});
|
||||
}
|
||||
setNodes((current) => [...current.filter((item) => item.id !== taskNodeId), ...layerNodes]);
|
||||
@@ -1109,7 +1110,7 @@ export function useCanvasMediaTools({
|
||||
const size = fitNodeSize(uploaded.width, uploaded.height, imageSpec.width, imageSpec.height);
|
||||
const currentNode = nodesRef.current.find((item) => item.id === childId);
|
||||
if (!currentNode) throw new Error("视角生成节点已被删除");
|
||||
const finalizedNode = { ...currentNode, width: size.width, height: size.height, metadata: { ...currentNode.metadata, ...imageMetadata(uploaded), prompt: effectivePrompt, ...generationMetadata } };
|
||||
const finalizedNode = { ...currentNode, width: size.width, height: size.height, metadata: commitProducedModel({ ...currentNode.metadata, ...imageMetadata(uploaded), prompt: effectivePrompt, ...generationMetadata }) };
|
||||
setNodes((current) => current.map((item) => item.id === childId ? finalizedNode : item));
|
||||
await persistMediaNodes([finalizedNode]);
|
||||
} catch (error) {
|
||||
@@ -1219,7 +1220,7 @@ export function useCanvasMediaTools({
|
||||
const size = fitNodeSize(uploaded.width, uploaded.height, node.width, node.height);
|
||||
const currentNode = nodesRef.current.find((item) => item.id === childId);
|
||||
if (!currentNode) throw new Error("表情编辑节点已被删除");
|
||||
const finalizedNode = { ...currentNode, width: size.width, height: size.height, metadata: { ...currentNode.metadata, ...imageMetadata(uploaded), prompt: providerPrompt, ...generationMetadata, emotionEdit } };
|
||||
const finalizedNode = { ...currentNode, width: size.width, height: size.height, metadata: commitProducedModel({ ...currentNode.metadata, ...imageMetadata(uploaded), prompt: providerPrompt, ...generationMetadata, emotionEdit }) };
|
||||
setNodes((current) => current.map((item) => item.id === childId ? finalizedNode : item));
|
||||
await persistMediaNodes([finalizedNode]);
|
||||
} catch (error) {
|
||||
|
||||
@@ -194,6 +194,7 @@ export function useCanvasUpload({
|
||||
metadata: {
|
||||
...currentNode.metadata, ...metadata,
|
||||
fileUpload: undefined, fileUploadProgress: undefined, errorDetails: undefined,
|
||||
producedModel: undefined, producedModelCandidate: undefined,
|
||||
...(replaceId ? {
|
||||
assetId: undefined, taskId: undefined, freeResize: false,
|
||||
isBatchRoot: undefined, batchRootId: undefined, batchChildIds: undefined,
|
||||
|
||||
Reference in new issue
Block a user