feat(canvas): 视频画面提取 - 支持批量取帧并将片段截取与生成解耦
This commit is contained in:
1 parent
6202b6e762
commit
86019cccea
18 files changed
+586
-155
No files matched your search
@@ -39,6 +39,7 @@ import { resolveProjectCanvasStyle } from "@/components/canvas/canvas-style-pick
|
||||
import { createStyleProfileSnapshot, resolveStyleProfile, serializeStyleProfile } from "@/lib/canvas/style-profile";
|
||||
import { CanvasNodeToolbar, CanvasNodeInfoModal } from "@/components/canvas/canvas-node-toolbar";
|
||||
import { CanvasSubtitleDialog } from "@/components/canvas/canvas-subtitle-dialog";
|
||||
import { CanvasVideoFrameDialog } from "@/components/canvas/canvas-video-frame-dialog";
|
||||
import { CanvasVideoSegmentDialog } from "@/components/canvas/canvas-video-segment-dialog";
|
||||
import { CanvasTimelineDialog } from "@/components/canvas/canvas-timeline-dialog";
|
||||
import { syncNodeSubtitlesToTimeline } from "@/lib/timeline/timeline-build";
|
||||
@@ -801,10 +802,12 @@ function InfiniteCanvasPage() {
|
||||
openPortraitTextureEditor,
|
||||
cropImageNode,
|
||||
cropNodeId,
|
||||
closeFrameDialog,
|
||||
closeSegmentDialog,
|
||||
extractAudioFromVideo,
|
||||
extractVideoLastFrame,
|
||||
extractingVideoFrameNodeId,
|
||||
extractVideoFrames,
|
||||
extractingVideoFramesNodeId,
|
||||
frameDialogNodeId,
|
||||
generateAngleNode,
|
||||
generateEmotionNode,
|
||||
handleSegmentConfirm,
|
||||
@@ -817,6 +820,7 @@ function InfiniteCanvasPage() {
|
||||
segmentDialogMode,
|
||||
segmentDialogNodeId,
|
||||
segmentRunningMode,
|
||||
setFrameDialogNodeId,
|
||||
setSegmentDialogNodeId,
|
||||
setAngleNodeId,
|
||||
setEmotionNodeId,
|
||||
@@ -827,7 +831,8 @@ function InfiniteCanvasPage() {
|
||||
setUpscaleNodeId,
|
||||
splitImageNode,
|
||||
splitNodeId,
|
||||
trimVideoAndRegenerate,
|
||||
openVideoFrameExtractor,
|
||||
openVideoSegmentExtractor,
|
||||
upscaleImageNode,
|
||||
upscaleNodeId,
|
||||
} = useCanvasMediaTools({
|
||||
@@ -849,7 +854,6 @@ function InfiniteCanvasPage() {
|
||||
startGenerationRequest,
|
||||
finishGenerationRequest,
|
||||
bindGenerationTask,
|
||||
onGenerateVideoNode: (nodeId, mode, prompt) => generateNodeRef.current?.(nodeId, mode, prompt),
|
||||
});
|
||||
|
||||
const handleNodesDeleted = useCallback(
|
||||
@@ -863,6 +867,7 @@ function InfiniteCanvasPage() {
|
||||
setDrawingNodeId(clearDeletedId);
|
||||
setInfoNodeId(clearDeletedId);
|
||||
setSubtitleNodeId(clearDeletedId);
|
||||
setFrameDialogNodeId(clearDeletedId);
|
||||
setSegmentDialogNodeId(clearDeletedId);
|
||||
setCropNodeId(clearDeletedId);
|
||||
setMaskEditNodeId(clearDeletedId);
|
||||
@@ -886,7 +891,7 @@ function InfiniteCanvasPage() {
|
||||
}
|
||||
cleanupCanvasFiles({ projectId, nodes: nextNodes, chatSessions });
|
||||
},
|
||||
[chatSessions, cleanupCanvasFiles, message, projectId, setAngleNodeId, setAnnotationNodeId, setCropNodeId, setEmotionNodeId, setMaskEditNodeId, setSegmentDialogNodeId, setSplitNodeId, setUpscaleNodeId, setRunningNodeId],
|
||||
[chatSessions, cleanupCanvasFiles, message, projectId, setAngleNodeId, setAnnotationNodeId, setCropNodeId, setEmotionNodeId, setFrameDialogNodeId, setMaskEditNodeId, setSegmentDialogNodeId, setSplitNodeId, setUpscaleNodeId, setRunningNodeId],
|
||||
);
|
||||
|
||||
const {
|
||||
@@ -1254,6 +1259,7 @@ function InfiniteCanvasPage() {
|
||||
const dialogNode = dialogNodeId ? nodeById.get(dialogNodeId) || null : null;
|
||||
const subtitleNode = subtitleNodeId ? nodeById.get(subtitleNodeId) || null : null;
|
||||
const timelineNode = timelineNodeId ? nodeById.get(timelineNodeId) || null : null;
|
||||
const frameNode = frameDialogNodeId ? nodeById.get(frameDialogNodeId) || null : null;
|
||||
const segmentNode = segmentDialogNodeId ? nodeById.get(segmentDialogNodeId) || null : null;
|
||||
const textEditorNode = textEditorNodeId ? nodeById.get(textEditorNodeId) || null : null;
|
||||
const characterReferenceNode = characterReferenceNodeId ? nodeById.get(characterReferenceNodeId) || null : null;
|
||||
@@ -2392,12 +2398,12 @@ function InfiniteCanvasPage() {
|
||||
setAngleNodeId((current) => (current === node.id ? null : node.id));
|
||||
}}
|
||||
onViewImage={(node) => setPreviewNodeId(node.id)}
|
||||
onExtractVideoLastFrame={(node) => void extractVideoLastFrame(node)}
|
||||
onExtractVideoFrames={openVideoFrameExtractor}
|
||||
onExtractAudioFromVideo={(node) => void extractAudioFromVideo(node)}
|
||||
onTrimVideoRegenerate={(node) => void trimVideoAndRegenerate(node)}
|
||||
onTrimVideoSegments={openVideoSegmentExtractor}
|
||||
onSubtitles={(node) => setSubtitleNodeId(node.id)}
|
||||
onTimeline={(node) => setTimelineNodeId(node.id)}
|
||||
extractingVideoFrame={toolbarNode?.id === extractingVideoFrameNodeId}
|
||||
extractingVideoFrames={toolbarNode?.id === extractingVideoFramesNodeId}
|
||||
extractingAudio={segmentRunningMode === "audio"}
|
||||
trimmingVideo={segmentRunningMode === "video"}
|
||||
onReversePrompt={createImageReversePromptNodes}
|
||||
@@ -2505,6 +2511,15 @@ function InfiniteCanvasPage() {
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{frameNode ? (
|
||||
<CanvasVideoFrameDialog
|
||||
node={frameNode}
|
||||
open={Boolean(frameNode)}
|
||||
onClose={closeFrameDialog}
|
||||
onConfirm={(params) => void extractVideoFrames(frameNode, params)}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{segmentNode && segmentDialogMode ? (
|
||||
<CanvasVideoSegmentDialog
|
||||
node={segmentNode}
|
||||
|
||||
Reference in new issue
Block a user