forked from 77media/video-flow
优化文本解析适配器,增强对话内容处理逻辑,确保角色名称的正确记录。更新分镜编辑器以支持内容变化的回调,改进分镜描述和对话内容的动态加载。修复视频段生成逻辑,确保视频编辑数据的准确性。
This commit is contained in:
parent
9bdc45812c
commit
5e6ead0f00
@ -190,18 +190,25 @@ export class TextToShotAdapter {
|
|||||||
shotData.shotDialogsContent.forEach(paragraph => {
|
shotData.shotDialogsContent.forEach(paragraph => {
|
||||||
let dialogRoleName = '';
|
let dialogRoleName = '';
|
||||||
let dialogContent = '';
|
let dialogContent = '';
|
||||||
|
let firstFindRole = false;
|
||||||
|
|
||||||
// 遍历段落内容
|
// 遍历段落内容
|
||||||
paragraph.content.forEach((node, index) => {
|
if (paragraph.content) {
|
||||||
if (node.type === 'characterToken') {
|
paragraph.content.forEach((node, index) => {
|
||||||
// 记录说话角色的名称
|
if (node.type === 'characterToken') {
|
||||||
index === 0 && (dialogRoleName = node.attrs.name);
|
// 记录说话角色的名称
|
||||||
index !== 0 && (dialogContent += node.attrs.name);
|
if (!firstFindRole) {
|
||||||
} else if (node.type === 'text') {
|
dialogRoleName = node.attrs.name;
|
||||||
// 累积对话内容
|
firstFindRole = true;
|
||||||
dialogContent += node.text;
|
} else {
|
||||||
}
|
dialogContent += node.attrs.name;
|
||||||
});
|
}
|
||||||
|
} else if (node.type === 'text') {
|
||||||
|
// 累积对话内容
|
||||||
|
dialogContent += node.text;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 如果有角色名和对话内容,添加到结果中
|
// 如果有角色名和对话内容,添加到结果中
|
||||||
if (dialogRoleName && dialogContent) {
|
if (dialogRoleName && dialogContent) {
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import React, { useState, useCallback, useEffect } from 'react';
|
import React, { useState, useCallback, useEffect } from 'react';
|
||||||
|
import { flushSync } from 'react-dom';
|
||||||
import { EditorContent, useEditor } from '@tiptap/react';
|
import { EditorContent, useEditor } from '@tiptap/react';
|
||||||
import StarterKit from '@tiptap/starter-kit';
|
import StarterKit from '@tiptap/starter-kit';
|
||||||
import Placeholder from '@tiptap/extension-placeholder'
|
import Placeholder from '@tiptap/extension-placeholder'
|
||||||
@ -12,6 +13,7 @@ interface ShotEditorProps {
|
|||||||
roles?: any[];
|
roles?: any[];
|
||||||
onCharacterClick?: (attrs: any) => void;
|
onCharacterClick?: (attrs: any) => void;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
|
onChangeContent?: (content: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '@tiptap/core' {
|
declare module '@tiptap/core' {
|
||||||
@ -36,14 +38,17 @@ interface EditorRef {
|
|||||||
editor: any;
|
editor: any;
|
||||||
insertCharacter: (character: CharacterToken) => void;
|
insertCharacter: (character: CharacterToken) => void;
|
||||||
insertContent: (content: any) => void;
|
insertContent: (content: any) => void;
|
||||||
getContent: () => any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShotEditor = React.forwardRef<EditorRef, ShotEditorProps>(
|
const ShotEditor = React.forwardRef<EditorRef, ShotEditorProps>(
|
||||||
function ShotEditor({ content, onCharacterClick, roles, placeholder }, ref) {
|
function ShotEditor({ content, onCharacterClick, roles, placeholder, onChangeContent }, ref) {
|
||||||
const [segments, setSegments] = useState(content);
|
const [segments, setSegments] = useState(content);
|
||||||
const [isOptimizing, setIsOptimizing] = useState(false);
|
const [isOptimizing, setIsOptimizing] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
onChangeContent?.(segments);
|
||||||
|
}, [segments]);
|
||||||
|
|
||||||
const handleSmartPolish = () => {
|
const handleSmartPolish = () => {
|
||||||
setIsOptimizing(true);
|
setIsOptimizing(true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -60,9 +65,11 @@ const ShotEditor = React.forwardRef<EditorRef, ShotEditorProps>(
|
|||||||
ShotTitle,
|
ShotTitle,
|
||||||
ReadonlyText,
|
ReadonlyText,
|
||||||
Placeholder.configure({
|
Placeholder.configure({
|
||||||
placeholder: placeholder || 'Add shot description here...',
|
placeholder: ({ node }) => {
|
||||||
showOnlyWhenEditable: true,
|
console.log('-==========placeholder node===========-', segments);
|
||||||
showOnlyCurrent: false,
|
|
||||||
|
return placeholder || 'Add shot description here...';
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
content: { type: 'doc', content: segments },
|
content: { type: 'doc', content: segments },
|
||||||
@ -76,9 +83,10 @@ const ShotEditor = React.forwardRef<EditorRef, ShotEditorProps>(
|
|||||||
editor.setOptions({ editable: true })
|
editor.setOptions({ editable: true })
|
||||||
},
|
},
|
||||||
onUpdate: ({ editor }) => {
|
onUpdate: ({ editor }) => {
|
||||||
const json = editor.getJSON()
|
const json = editor.getJSON();
|
||||||
console.log('-==========json===========-', json);
|
flushSync(() => {
|
||||||
setSegments(json.content);
|
setSegments(json.content);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -94,9 +102,6 @@ const ShotEditor = React.forwardRef<EditorRef, ShotEditorProps>(
|
|||||||
},
|
},
|
||||||
insertContent: (content: any) => {
|
insertContent: (content: any) => {
|
||||||
editor?.commands.insertContent(content);
|
editor?.commands.insertContent(content);
|
||||||
},
|
|
||||||
getContent: () => {
|
|
||||||
return segments;
|
|
||||||
}
|
}
|
||||||
}), [editor]) // 依赖 editor,确保更新
|
}), [editor]) // 依赖 editor,确保更新
|
||||||
|
|
||||||
|
|||||||
@ -23,8 +23,20 @@ interface CharacterToken {
|
|||||||
|
|
||||||
const createEmptyShot = (): Shot => ({
|
const createEmptyShot = (): Shot => ({
|
||||||
name: `shot${Date.now()}`,
|
name: `shot${Date.now()}`,
|
||||||
shotDescContent: [],
|
shotDescContent: [{
|
||||||
shotDialogsContent: []
|
type: 'paragraph',
|
||||||
|
content: [{
|
||||||
|
type: 'text',
|
||||||
|
text: 'Add shot description here...'
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
shotDialogsContent: [{
|
||||||
|
type: 'paragraph',
|
||||||
|
content: [{
|
||||||
|
type: 'text',
|
||||||
|
text: 'Add shot dialogue here...'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
});
|
});
|
||||||
|
|
||||||
interface ShotsEditorProps {
|
interface ShotsEditorProps {
|
||||||
@ -50,32 +62,31 @@ export const ShotsEditor = forwardRef<any, ShotsEditorProps>(({ roles, shotInfo,
|
|||||||
}
|
}
|
||||||
}, [shotInfo]);
|
}, [shotInfo]);
|
||||||
|
|
||||||
// 更新当前分镜内容
|
const handleDescContentChange = (content: any) => {
|
||||||
const updateShot = () => {
|
|
||||||
const shot = shots[currentShotIndex];
|
const shot = shots[currentShotIndex];
|
||||||
if (descEditorRef.current) {
|
shot.shotDescContent = content;
|
||||||
const content = descEditorRef.current.getContent();
|
setShots(prevShots =>
|
||||||
console.log('-==========descEditorcontent===========-', content);
|
prevShots.map((item, index) =>
|
||||||
shot.shotDescContent = content;
|
index === currentShotIndex ? shot : item
|
||||||
}
|
)
|
||||||
if (dialogEditorRef.current) {
|
);
|
||||||
const content = dialogEditorRef.current.getContent();
|
}
|
||||||
console.log('-==========dialogEditorcontent===========-', content);
|
const handleDialogContentChange = (content: any) => {
|
||||||
shot.shotDialogsContent = content;
|
const shot = shots[currentShotIndex];
|
||||||
}
|
shot.shotDialogsContent = content;
|
||||||
setShots([...shots]);
|
setShots(prevShots =>
|
||||||
|
prevShots.map((item, index) =>
|
||||||
|
index === currentShotIndex ? shot : item
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleShotTabClick = (index: number) => {
|
const handleShotTabClick = (index: number) => {
|
||||||
// 切换前更新当前分镜内容
|
|
||||||
updateShot();
|
|
||||||
setCurrentShotIndex(index);
|
setCurrentShotIndex(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
const getShotInfo = () => {
|
const getShotInfo = () => {
|
||||||
// 生成前 更新当前分镜内容
|
console.log('-==========getShotInfo shots===========-', shots);
|
||||||
updateShot();
|
|
||||||
console.log('-==========shots===========-', shots);
|
|
||||||
const shotInfo = shots.map((shot) => {
|
const shotInfo = shots.map((shot) => {
|
||||||
return TextToShotAdapter.toLensType(shot);
|
return TextToShotAdapter.toLensType(shot);
|
||||||
});
|
});
|
||||||
@ -93,7 +104,6 @@ export const ShotsEditor = forwardRef<any, ShotsEditorProps>(({ roles, shotInfo,
|
|||||||
}
|
}
|
||||||
const newShot = createEmptyShot();
|
const newShot = createEmptyShot();
|
||||||
setShots([...shots, newShot]);
|
setShots([...shots, newShot]);
|
||||||
// onShotsChange([...shots, newShot]);
|
|
||||||
// 自动切换到新创建的分镜
|
// 自动切换到新创建的分镜
|
||||||
setCurrentShotIndex(shots.length);
|
setCurrentShotIndex(shots.length);
|
||||||
};
|
};
|
||||||
@ -250,6 +260,7 @@ export const ShotsEditor = forwardRef<any, ShotsEditorProps>(({ roles, shotInfo,
|
|||||||
onCharacterClick={() => {}}
|
onCharacterClick={() => {}}
|
||||||
roles={roles}
|
roles={roles}
|
||||||
placeholder="Add shot description here..."
|
placeholder="Add shot description here..."
|
||||||
|
onChangeContent={(content) => {handleDescContentChange(content)}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -281,6 +292,7 @@ export const ShotsEditor = forwardRef<any, ShotsEditorProps>(({ roles, shotInfo,
|
|||||||
onCharacterClick={() => {}}
|
onCharacterClick={() => {}}
|
||||||
roles={roles}
|
roles={roles}
|
||||||
placeholder="Add shot dialogue here..."
|
placeholder="Add shot dialogue here..."
|
||||||
|
onChangeContent={(content) => {handleDialogContentChange(content)}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -113,7 +113,7 @@ export function ShotTabContent({
|
|||||||
...shotData[selectedIndex],
|
...shotData[selectedIndex],
|
||||||
lens: shotInfo
|
lens: shotInfo
|
||||||
});
|
});
|
||||||
// regenerateVideoSegment();
|
regenerateVideoSegment();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 新增分镜
|
// 新增分镜
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user