Browse Source
- 智能擦除改为进入编辑态(videoSmartErase):覆盖'AI一键去字幕'提示工具条, 点击生成才派生 207 节点,不再点击即建 - 视频节点读取 activeNodeTool,进入任一擦除态时隐藏 NodeActionCapsule, 与图片节点裁剪/擦除的互斥一致 - ActiveVideoEditHost 分发智能/框选两种擦除会话 - 新增 MediaVideoSmartEraseToolbar Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>feature/video-erase
6 changed files with 136 additions and 60 deletions
@ -0,0 +1,60 @@ |
|||
"use client"; |
|||
|
|||
import { useCallback, useRef } from "react"; |
|||
import type { ProviderModel } from "@/lib/providers/types"; |
|||
import { useWorkflowStore } from "@/store/workflowStore"; |
|||
import { MediaVideoSmartEraseToolbar } from "@/components/media/MediaVideoEraseToolbar"; |
|||
import { |
|||
chooseVideoSmartEraseModel, |
|||
createVideoSmartEraseNode, |
|||
} from "@/utils/videoEraseNodes"; |
|||
import { defaultNodeDimensions } from "@/constants/nodeDimensions"; |
|||
|
|||
interface VideoSmartEraseSessionProps { |
|||
nodeId: string; |
|||
dimensions?: { width: number; height: number } | null; |
|||
models: ProviderModel[]; |
|||
onClose: () => void; |
|||
} |
|||
|
|||
function getNodeWidth(node: { style?: { width?: unknown } | undefined }) { |
|||
if (typeof node.style?.width === "number") return node.style.width; |
|||
return defaultNodeDimensions.videoInput.width; |
|||
} |
|||
|
|||
/** |
|||
* 智能擦除编辑会话:进入编辑态后覆盖一层"AI一键去字幕"提示,点击生成才派生 |
|||
* 207 智能擦除节点并立即运行。与图片编辑一致 —— 不隐藏视频、无选区、只有生成。 |
|||
*/ |
|||
export function VideoSmartEraseSession({ nodeId, dimensions, models, onClose }: VideoSmartEraseSessionProps) { |
|||
const busyRef = useRef(false); |
|||
const addNode = useWorkflowStore((state) => state.addNode); |
|||
const onConnect = useWorkflowStore((state) => state.onConnect); |
|||
const getNodeById = useWorkflowStore((state) => state.getNodeById); |
|||
const selectSingleNode = useWorkflowStore((state) => state.selectSingleNode); |
|||
const regenerateNode = useWorkflowStore((state) => state.regenerateNode); |
|||
|
|||
const handleConfirm = useCallback(() => { |
|||
if (busyRef.current) return; |
|||
const sourceNode = getNodeById(nodeId); |
|||
if (!sourceNode) return; |
|||
busyRef.current = true; |
|||
const currentPosition = sourceNode.position ?? { x: 0, y: 0 }; |
|||
createVideoSmartEraseNode({ |
|||
sourceNodeId: nodeId, |
|||
position: { |
|||
x: currentPosition.x + getNodeWidth(sourceNode) + 220, |
|||
y: currentPosition.y, |
|||
}, |
|||
dimensions: dimensions ?? null, |
|||
selectedModel: chooseVideoSmartEraseModel(models), |
|||
addNode, |
|||
onConnect, |
|||
selectSingleNode, |
|||
regenerateNode, |
|||
}); |
|||
onClose(); |
|||
}, [addNode, dimensions, getNodeById, models, nodeId, onConnect, onClose, regenerateNode, selectSingleNode]); |
|||
|
|||
return <MediaVideoSmartEraseToolbar onCancel={onClose} onConfirm={handleConfirm} />; |
|||
} |
|||
Loading…
Reference in new issue