You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

106 lines
3.3 KiB

import type { Connection, XYPosition } from "@xyflow/react";
import type { ProviderModel } from "@/lib/providers/types";
import type { SelectedModel, SmartVideoNodeData } from "@/types";
import { POPI_VIDEO_SUBTYPE_ENHANCE } from "@/constants/generationTask";
import { SINGLE_INPUT_HANDLE_ID, SINGLE_OUTPUT_HANDLE_ID } from "@/utils/nodeHandles";
import { toSelectedModel } from "@/utils/selectedModel";
export const HIGH_DEFINITION_VIDEO_BATCH_SIZE = 1;
export const HIGH_DEFINITION_VIDEO_FALLBACK_MODEL: SelectedModel = {
provider: "popiserver",
modelId: "",
displayName: "画质增强",
capabilities: ["image-to-video"],
isSupportVideos: true,
type: 2,
subType: POPI_VIDEO_SUBTYPE_ENHANCE,
subTypes: [POPI_VIDEO_SUBTYPE_ENHANCE],
};
function modelSubTypes(model: ProviderModel): number[] {
const subTypes = model.metadata?.subTypes;
if (Array.isArray(subTypes)) {
return subTypes.map((item) => Number(item)).filter((item) => Number.isFinite(item));
}
const subType = Number(model.metadata?.subType);
return Number.isFinite(subType) ? [subType] : [];
}
export function isHighDefinitionVideoModel(model: ProviderModel): boolean {
return modelSubTypes(model).includes(POPI_VIDEO_SUBTYPE_ENHANCE);
}
export function chooseHighDefinitionVideoModel(models: ProviderModel[]): SelectedModel {
const model = models.find(isHighDefinitionVideoModel);
return model ? toSelectedModel(model) : HIGH_DEFINITION_VIDEO_FALLBACK_MODEL;
}
export function isHighDefinitionDerivedVideoNode(data: unknown): boolean {
const record = data && typeof data === "object" ? data as { derivedVideo?: unknown } : {};
const derivedVideo = record.derivedVideo && typeof record.derivedVideo === "object"
? record.derivedVideo as { operation?: unknown }
: null;
return derivedVideo?.operation === "highDefinition";
}
export interface CreateHighDefinitionVideoNodeOptions {
sourceNodeId: string;
position: XYPosition;
dimensions?: { width: number; height: number } | null;
selectedModel: SelectedModel;
addNode: (type: "smartVideo", position: XYPosition, initialData?: Partial<SmartVideoNodeData>) => string;
onConnect: (connection: Connection) => void;
selectSingleNode?: (nodeId: string) => void;
}
export function createHighDefinitionVideoNode({
sourceNodeId,
position,
dimensions = null,
selectedModel,
addNode,
onConnect,
selectSingleNode,
}: CreateHighDefinitionVideoNodeOptions): string {
const nodeId = addNode("smartVideo", position, {
video: null,
videoRef: undefined,
assetId: undefined,
previewVideoPoster: undefined,
filename: `high-definition-${Date.now()}.mp4`,
duration: null,
dimensions,
format: null,
inputImages: [],
inputPrompt: "",
outputVideo: null,
outputVideoCover: undefined,
outputVideoRef: undefined,
selectedModel,
batchSize: HIGH_DEFINITION_VIDEO_BATCH_SIZE,
referenceSubjectList: [],
parameters: {},
extraTaskParams: {},
subType: POPI_VIDEO_SUBTYPE_ENHANCE,
customTitle: "高清",
derivedVideo: {
sourceNodeId,
operation: "highDefinition",
},
status: "idle",
error: null,
videoHistory: [],
selectedVideoHistoryIndex: 0,
});
onConnect({
source: sourceNodeId,
sourceHandle: SINGLE_OUTPUT_HANDLE_ID,
target: nodeId,
targetHandle: SINGLE_INPUT_HANDLE_ID,
});
selectSingleNode?.(nodeId);
return nodeId;
}