@@ -111,12 +111,15 @@ export function CanvasVideoSegmentDialog({ node, nodes, connections, open, mode,
|
||||
const durationSec = durationMs > 0 ? durationMs / 1000 : 0;
|
||||
const hasTimelineVideoClips = Boolean(timeline?.clips.some((clip) => clip.kind === "video"));
|
||||
const hasPrompt = Boolean(prompt.trim());
|
||||
const modelRequirements = useMemo<ModelRequirements>(() => ({
|
||||
capability: "video",
|
||||
input: { textCount: hasPrompt ? 1 : 0, imageCount: 0, videoCount: 1, audioCount: 0, characterCount: 0 },
|
||||
videoOperation: operation,
|
||||
videoSeconds: config.videoSeconds,
|
||||
}), [config.videoSeconds, hasPrompt, operation]);
|
||||
const modelRequirements = useMemo<ModelRequirements>(
|
||||
() => ({
|
||||
capability: "video",
|
||||
input: { textCount: hasPrompt ? 1 : 0, imageCount: 0, videoCount: 1, audioCount: 0, characterCount: 0 },
|
||||
videoOperation: operation,
|
||||
videoSeconds: config.videoSeconds,
|
||||
}),
|
||||
[config.videoSeconds, hasPrompt, operation],
|
||||
);
|
||||
const resolvedModel = resolveCompatibleModel(config, model, modelRequirements) || model;
|
||||
const videoProfile = useMemo(() => (resolvedModel ? modelCapabilityConfigFor(config, resolvedModel).video : undefined), [config, resolvedModel]);
|
||||
const defaultModel = config.videoModel || config.model || "";
|
||||
|
||||
@@ -45,7 +45,10 @@ export function ModelPicker({ config, value, onChange, capability, className, fu
|
||||
key: channel.id,
|
||||
label: channel.name || "未命名渠道",
|
||||
scope: channel.scope === "system" ? "系统渠道" : "自定义渠道",
|
||||
models: groupModelsByDisplayName(config, options.filter((model) => resolveModelChannel(config, model).id === channel.id)),
|
||||
models: groupModelsByDisplayName(
|
||||
config,
|
||||
options.filter((model) => resolveModelChannel(config, model).id === channel.id),
|
||||
),
|
||||
}))
|
||||
.filter((group) => group.models.length);
|
||||
const groupedModels = new Set(channelGroups.flatMap((group) => group.models.flatMap((modelGroup) => modelGroup.models)));
|
||||
|
||||
@@ -113,18 +113,21 @@ export function modelGroupReferenceLimits(config: AiConfig, selected: string, ca
|
||||
if (!groupModels.length) return undefined;
|
||||
const compatibleModels = requirements ? groupModels.filter((model) => !modelCompatibilityError(config, model, requirements)) : groupModels;
|
||||
const models = compatibleModels.length ? compatibleModels : groupModels;
|
||||
return models.reduce<ModelReferenceLimits>((limits, model) => {
|
||||
const profile = modelCapabilityConfigFor(config, model);
|
||||
if (capability === "image") {
|
||||
return { ...limits, maxImages: Math.max(limits.maxImages, profile.image!.references.maxImages) };
|
||||
}
|
||||
const references = profile.video!.references;
|
||||
return {
|
||||
maxImages: Math.max(limits.maxImages, references.maxImages),
|
||||
maxVideos: Math.max(limits.maxVideos, references.maxVideos),
|
||||
maxAudios: Math.max(limits.maxAudios, references.maxAudios),
|
||||
};
|
||||
}, { maxImages: 0, maxVideos: 0, maxAudios: 0 });
|
||||
return models.reduce<ModelReferenceLimits>(
|
||||
(limits, model) => {
|
||||
const profile = modelCapabilityConfigFor(config, model);
|
||||
if (capability === "image") {
|
||||
return { ...limits, maxImages: Math.max(limits.maxImages, profile.image!.references.maxImages) };
|
||||
}
|
||||
const references = profile.video!.references;
|
||||
return {
|
||||
maxImages: Math.max(limits.maxImages, references.maxImages),
|
||||
maxVideos: Math.max(limits.maxVideos, references.maxVideos),
|
||||
maxAudios: Math.max(limits.maxAudios, references.maxAudios),
|
||||
};
|
||||
},
|
||||
{ maxImages: 0, maxVideos: 0, maxAudios: 0 },
|
||||
);
|
||||
}
|
||||
|
||||
export function inferVideoOperation(input: ModelInputSummary) {
|
||||
|
||||
@@ -705,24 +705,35 @@ function InfiniteCanvasPage() {
|
||||
onNodesDeleted: handleNodesDeleted,
|
||||
});
|
||||
|
||||
const { cancelPendingConnectionCreate, closeConnectionCreateMenu, connectionTargetAnchorRatio, connectionTargetNodeId, connectingParams, createConnectedNode, getConnectionCreateDisabledReason, handleConnectStart, mouseWorld, pendingConnectionCreate, setConnecting } =
|
||||
useCanvasConnectionController({
|
||||
projectId,
|
||||
config: effectiveConfig,
|
||||
defaultDrawingEngine,
|
||||
nodesRef,
|
||||
connectionsRef,
|
||||
viewportRef,
|
||||
scriptScrollTopById,
|
||||
screenToCanvas,
|
||||
setNodes,
|
||||
setConnections,
|
||||
setSelectedNodeIds,
|
||||
setSelectedConnectionId,
|
||||
setContextMenu,
|
||||
setDialogNodeId,
|
||||
setDrawingNodeId,
|
||||
});
|
||||
const {
|
||||
cancelPendingConnectionCreate,
|
||||
closeConnectionCreateMenu,
|
||||
connectionTargetAnchorRatio,
|
||||
connectionTargetNodeId,
|
||||
connectingParams,
|
||||
createConnectedNode,
|
||||
getConnectionCreateDisabledReason,
|
||||
handleConnectStart,
|
||||
mouseWorld,
|
||||
pendingConnectionCreate,
|
||||
setConnecting,
|
||||
} = useCanvasConnectionController({
|
||||
projectId,
|
||||
config: effectiveConfig,
|
||||
defaultDrawingEngine,
|
||||
nodesRef,
|
||||
connectionsRef,
|
||||
viewportRef,
|
||||
scriptScrollTopById,
|
||||
screenToCanvas,
|
||||
setNodes,
|
||||
setConnections,
|
||||
setSelectedNodeIds,
|
||||
setSelectedConnectionId,
|
||||
setContextMenu,
|
||||
setDialogNodeId,
|
||||
setDrawingNodeId,
|
||||
});
|
||||
|
||||
const handleCanvasSelectionStart = useCallback(() => {
|
||||
setContextMenu(null);
|
||||
|
||||
Reference in New Issue
Block a user