feat(canvas): 添加视频节点支持功能
- 在后端添加 AI 视频相关接口处理函数 - 扩展前端画布组件支持视频节点类型 - 实现视频上传、生成和播放功能 - 更新画布数据结构文档以包含视频节点 - 添加视频节点的操作工具栏和配置面板 - 集成视频存储和检索服务 - 优化视频节点的渲染和交互体验
This commit is contained in:
@@ -6,11 +6,13 @@ import { persist, type PersistStorage, type StorageValue } from "zustand/middlew
|
||||
import { nanoid } from "nanoid";
|
||||
import { localForageStorage } from "@/lib/localforage-storage";
|
||||
import { cleanupUnusedImages, resolveImageUrl, uploadImage } from "@/services/image-storage";
|
||||
import { cleanupUnusedMedia, resolveMediaUrl } from "@/services/file-storage";
|
||||
|
||||
export type AssetKind = "text" | "image";
|
||||
export type AssetKind = "text" | "image" | "video";
|
||||
export type TextAsset = AssetBase<"text"> & { data: { content: string } };
|
||||
export type ImageAsset = AssetBase<"image"> & { data: { dataUrl: string; storageKey?: string; width: number; height: number; bytes: number; mimeType: string } };
|
||||
export type Asset = TextAsset | ImageAsset;
|
||||
export type VideoAsset = AssetBase<"video"> & { data: { url: string; storageKey?: string; width: number; height: number; bytes: number; mimeType: string } };
|
||||
export type Asset = TextAsset | ImageAsset | VideoAsset;
|
||||
|
||||
type AssetBase<T extends AssetKind> = {
|
||||
id: string;
|
||||
@@ -42,6 +44,7 @@ const assetStorage: PersistStorage<AssetStore> = {
|
||||
const parsed = JSON.parse(value) as StorageValue<AssetStore>;
|
||||
parsed.state.assets = await Promise.all(
|
||||
parsed.state.assets.map(async (asset) => {
|
||||
if (asset.kind === "video" && asset.data.storageKey) return { ...asset, data: { ...asset.data, url: await resolveMediaUrl(asset.data.storageKey, asset.data.url) } };
|
||||
if (asset.kind !== "image") return asset;
|
||||
if (asset.data.storageKey)
|
||||
return {
|
||||
@@ -84,6 +87,7 @@ export const useAssetStore = create<AssetStore>()(
|
||||
window.setTimeout(async () => {
|
||||
const { useCanvasStore } = await import("@/app/(user)/canvas/stores/use-canvas-store");
|
||||
await cleanupUnusedImages({ assets: get().assets, projects: useCanvasStore.getState().projects, extra });
|
||||
await cleanupUnusedMedia({ assets: get().assets, projects: useCanvasStore.getState().projects, extra });
|
||||
}, 0);
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -13,6 +13,7 @@ export type AiConfig = {
|
||||
apiKey: string;
|
||||
model: string;
|
||||
imageModel: string;
|
||||
videoModel: string;
|
||||
textModel: string;
|
||||
systemPrompt: string;
|
||||
models: string[];
|
||||
@@ -29,6 +30,7 @@ export const defaultConfig: AiConfig = {
|
||||
apiKey: "",
|
||||
model: "gpt-image-2",
|
||||
imageModel: "gpt-image-2",
|
||||
videoModel: "sora-2",
|
||||
textModel: "gpt-5.5",
|
||||
systemPrompt: "",
|
||||
models: [],
|
||||
@@ -61,6 +63,7 @@ function resolveEffectiveConfig(config: AiConfig, modelChannel: AdminPublicSetti
|
||||
models,
|
||||
model: models.includes(config.model) ? config.model : modelChannel.defaultModel,
|
||||
imageModel: models.includes(config.imageModel) ? config.imageModel : modelChannel.defaultImageModel || modelChannel.defaultModel,
|
||||
videoModel: models.includes(config.videoModel) ? config.videoModel : "sora-2",
|
||||
textModel: models.includes(config.textModel) ? config.textModel : modelChannel.defaultTextModel || modelChannel.defaultModel,
|
||||
systemPrompt: modelChannel.systemPrompt,
|
||||
};
|
||||
@@ -104,7 +107,7 @@ export const useConfigStore = create<ConfigStore>()(
|
||||
partialize: (state) => ({ config: state.config }),
|
||||
merge: (persisted, current) => {
|
||||
const config = { ...defaultConfig, ...((persisted as Partial<ConfigStore>).config || {}) };
|
||||
return { ...current, config: { ...config, channelMode: config.channelMode || "remote", imageModel: config.imageModel || config.model, textModel: config.textModel || config.model } };
|
||||
return { ...current, config: { ...config, channelMode: config.channelMode || "remote", imageModel: config.imageModel || config.model, videoModel: config.videoModel || "sora-2", textModel: config.textModel || config.model } };
|
||||
},
|
||||
},
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user