fix(canvas): 远程媒体 - 统一资源地址并校验视频缓存

This commit is contained in:
ddCat
2026-09-19 22:29:09 +08:00
parent 14a78c3c18
commit db9e18da1e
10 changed files with 83 additions and 134 deletions

View File

@@ -7,6 +7,7 @@ import { parseBackendGenerationResult } from "@/services/api/generation-task";
import type { GenerationTask, GenerationTaskOutput } from "@/services/api/task-center";
import { resolveMediaUrl, type UploadedFile } from "@/services/file-storage";
import { resolveImageUrl, uploadImage, type UploadedImage } from "@/services/image-storage";
import { getCachedResourceBlob } from "@/services/resource-blob-cache";
import { useCanvasStore } from "@/stores/canvas/use-canvas-store";
import { useAssetStore } from "@/stores/use-asset-store";
import { applyGenerationConsumerEffect, generationEffectApplied } from "@/services/generation-consumer-dedupe";
@@ -161,17 +162,9 @@ export async function buildGenerationTaskNodeResult(node: CanvasNodeData, task:
}
if (mode === "video") {
if (!result.video?.dataUrl) throw new Error("后端任务没有返回视频");
if (!result.video?.storageKey && !result.video?.dataUrl) throw new Error("后端任务没有返回视频");
const video = result.video.storageKey
? {
url: await resolveMediaUrl(result.video.storageKey, result.video.dataUrl),
storageKey: result.video.storageKey,
width: result.video.width,
height: result.video.height,
durationMs: result.video.durationMs,
bytes: result.video.bytes || 0,
mimeType: result.video.mimeType || "video/mp4",
}
? await cacheGeneratedRemoteVideo({ ...result.video, storageKey: result.video.storageKey })
: await storeGeneratedVideo({ url: result.video.dataUrl, mimeType: result.video.mimeType || "video/mp4" });
const videoSize = fitNodeSize(video.width || node.width || VIDEO_NODE_MAX_SIZE.width, video.height || node.height || VIDEO_NODE_MAX_SIZE.height, VIDEO_NODE_MAX_SIZE.width, VIDEO_NODE_MAX_SIZE.height);
const geometry = node.metadata?.locked
@@ -205,6 +198,36 @@ export async function buildGenerationTaskNodeResult(node: CanvasNodeData, task:
};
}
type GeneratedVideoResult = {
dataUrl: string;
storageKey?: string;
width?: number;
height?: number;
durationMs?: number;
bytes?: number;
mimeType?: string;
};
/**
* 生成任务的远程视频只有在浏览器已拿到可复用的 Blob 后才进入成功态。
* 节点仍保存稳定的资源文件地址,Blob 只作为本地缓存和后续字节处理的加速层。
*/
async function cacheGeneratedRemoteVideo(result: GeneratedVideoResult & { storageKey: string }): Promise<UploadedFile> {
const blob = await getCachedResourceBlob(result.storageKey);
if (!blob) throw new Error("生成视频资源缓存失败,未标记为成功");
const url = await resolveMediaUrl(result.storageKey, result.dataUrl || "");
if (!url) throw new Error("生成视频资源地址为空,未标记为成功");
return {
url,
storageKey: result.storageKey,
width: result.width,
height: result.height,
durationMs: result.durationMs,
bytes: result.bytes || blob.size,
mimeType: result.mimeType || blob.type || "video/mp4",
};
}
export async function applyGenerationTaskResultToNodes(nodes: CanvasNodeData[], task: GenerationTask, targetNodeId?: string) {
const node = findGenerationTaskNode(nodes, task, targetNodeId);
if (!node) return { nodes, updated: false, nodeId: "", node: null };