|
|
|
@ -5,13 +5,15 @@ |
|
|
|
|
|
|
|
import type { GenerateVideoNodeData } from "@/types"; |
|
|
|
import { createPopiserverDefaultVideoModel } from "@/store/utils/defaultImageModel"; |
|
|
|
import { isValidVideoDurationSeconds } from "@/utils/videoGenerationSettings"; |
|
|
|
import { buildRuntimeGenerationParameters, readVideoGenerationConfig } from "@/utils/generationConfig"; |
|
|
|
import { |
|
|
|
buildRuntimeExtraTaskParams, |
|
|
|
buildRuntimeModelParameters, |
|
|
|
readVideoGenerationConfig, |
|
|
|
} from "@/utils/generationConfig"; |
|
|
|
import { isHttpMediaUrl } from "@/utils/mediaResolver"; |
|
|
|
import type { NodeExecutionContext } from "./types"; |
|
|
|
import { buildPromptFromConnectedTextItems } from "./textInputPrompt"; |
|
|
|
import { |
|
|
|
assertPopiMediaModel, |
|
|
|
executePopiMediaGeneration, |
|
|
|
mediaGenerationErrorMessage, |
|
|
|
} from "./popiMediaGenerationExecutor"; |
|
|
|
@ -28,10 +30,6 @@ function getGeneratedImageUrl(value: unknown): string | undefined { |
|
|
|
return typeof record.url === "string" && record.url.length > 0 ? record.url : undefined; |
|
|
|
} |
|
|
|
|
|
|
|
function readVideoDurationSeconds(parameters: Record<string, unknown>): unknown { |
|
|
|
return parameters.duration ?? parameters.duration_seconds ?? parameters.durationSeconds; |
|
|
|
} |
|
|
|
|
|
|
|
export async function executeGenerateVideo( |
|
|
|
ctx: NodeExecutionContext, |
|
|
|
options: GenerateVideoOptions = {} |
|
|
|
@ -51,19 +49,8 @@ export async function executeGenerateVideo( |
|
|
|
const nodeConfig = readVideoGenerationConfig(nodeData, createPopiserverDefaultVideoModel()); |
|
|
|
const images = useStoredFallback && connectedImages.length === 0 ? nodeConfig.inputImages : connectedImages; |
|
|
|
const prompt = buildPromptFromConnectedTextItems(connectedTextItems, connectedText, nodeConfig.prompt); |
|
|
|
const hasPrompt = Boolean(prompt); |
|
|
|
const hasAudio = connectedAudio.length > 0; |
|
|
|
const hasVideo = connectedVideos.length > 0; |
|
|
|
|
|
|
|
try { |
|
|
|
if (!isValidVideoDurationSeconds(readVideoDurationSeconds(nodeConfig.parameters))) { |
|
|
|
throw new Error("Video duration must be at least 4 seconds"); |
|
|
|
} |
|
|
|
if (!hasPrompt && images.length === 0 && !hasVideo && !hasAudio) { |
|
|
|
throw new Error("Missing required inputs"); |
|
|
|
} |
|
|
|
const model = assertPopiMediaModel(nodeConfig.selectedModel); |
|
|
|
|
|
|
|
updateNodeData(node.id, { |
|
|
|
inputImages: images, |
|
|
|
inputPrompt: nodeConfig.prompt, |
|
|
|
@ -74,12 +61,13 @@ export async function executeGenerateVideo( |
|
|
|
const result = await executePopiMediaGeneration({ |
|
|
|
ctx, |
|
|
|
mediaType: "video", |
|
|
|
model, |
|
|
|
model: nodeConfig.selectedModel, |
|
|
|
prompt: prompt || "", |
|
|
|
images, |
|
|
|
videos: connectedVideos, |
|
|
|
voices: connectedAudio, |
|
|
|
parameters: buildRuntimeGenerationParameters({ ...nodeConfig, prompt: prompt || "" }), |
|
|
|
parameters: buildRuntimeModelParameters({ ...nodeConfig, prompt: prompt || "" }), |
|
|
|
extraTaskParams: buildRuntimeExtraTaskParams({ ...nodeConfig, prompt: prompt || "" }), |
|
|
|
subType: nodeConfig.subType, |
|
|
|
referenceSubjectList: nodeConfig.referenceSubjectList, |
|
|
|
}); |
|
|
|
@ -98,9 +86,9 @@ export async function executeGenerateVideo( |
|
|
|
video: outputContent, |
|
|
|
timestamp, |
|
|
|
prompt: prompt || "", |
|
|
|
model: model.modelId, |
|
|
|
modelDisplayName: model.displayName || model.modelId, |
|
|
|
modelProvider: model.provider, |
|
|
|
model: nodeConfig.selectedModel.modelId, |
|
|
|
modelDisplayName: nodeConfig.selectedModel.displayName || nodeConfig.selectedModel.modelId, |
|
|
|
modelProvider: nodeConfig.selectedModel.provider, |
|
|
|
}; |
|
|
|
const isRemoteVideo = Boolean(videoData && outputContent && isHttpMediaUrl(outputContent)); |
|
|
|
|
|
|
|
@ -113,7 +101,7 @@ export async function executeGenerateVideo( |
|
|
|
error: null, |
|
|
|
videoHistory: [newHistoryItem, ...(nodeData.videoHistory || [])].slice(0, 50), |
|
|
|
selectedVideoHistoryIndex: 0, |
|
|
|
lastUsedModel: model, |
|
|
|
lastUsedModel: nodeConfig.selectedModel, |
|
|
|
}); |
|
|
|
} catch (error) { |
|
|
|
if (error instanceof DOMException && error.name === "AbortError") { |
|
|
|
|