feat: 匹配素材改为针对单个镜头匹配
- 新增 matchSingleMaterial 函数,调用单条匹配 API - 点击'匹配素材'只匹配当前镜头,不影响其他镜头
This commit is contained in:
@@ -10,6 +10,7 @@ export interface UseEmptyShotMaterialsResult {
|
||||
materialMatchMap: Record<string, { url: string; duration: number } | null>;
|
||||
userUploadedMaterials: Record<string, { path: string; duration: number }>;
|
||||
matchMaterials: () => Promise<void>;
|
||||
matchSingleMaterial: (shotId: string) => Promise<void>;
|
||||
switchMaterial: (shotId: string) => Promise<{ url: string; duration: number } | null>;
|
||||
uploadMaterial: (shotId: string) => Promise<{ path: string; duration: number } | null>;
|
||||
setMaterialMatchMap: React.Dispatch<
|
||||
@@ -93,6 +94,35 @@ export function useEmptyShotMaterials(
|
||||
// 匹配结果仅作为组件本地状态,视频生成成功后再统一持久化到 segments.json
|
||||
};
|
||||
|
||||
/**
|
||||
* 单个镜头素材匹配
|
||||
*/
|
||||
const matchSingleMaterial = async (shotId: string) => {
|
||||
const shot = shots.find((s) => String(s.id) === shotId);
|
||||
if (!shot || shot.type !== 'empty_shot' || !shot.scene) {
|
||||
return;
|
||||
}
|
||||
|
||||
const assignedMap = computeAssignedIntervals(shots);
|
||||
const assigned = assignedMap[shot.id];
|
||||
const requiredDuration = (assigned.assignedEnd - assigned.assignedStart) / 1000;
|
||||
|
||||
try {
|
||||
const result = await matchMaterial(shot.scene || '', requiredDuration, projectId || undefined);
|
||||
setMaterialMatchMap((prev) => ({
|
||||
...prev,
|
||||
[shotId]: result || null,
|
||||
}));
|
||||
if (!result) {
|
||||
toast.warning('暂无可用素材');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[VideoGeneration] 素材匹配失败:', err);
|
||||
toast.error(err instanceof Error ? err.message : '素材匹配失败');
|
||||
setMaterialMatchMap((prev) => ({ ...prev, [shotId]: null }));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 切换空镜素材(换一个)
|
||||
* 返回新素材信息,由调用方决定是否刷新预览
|
||||
@@ -187,6 +217,7 @@ export function useEmptyShotMaterials(
|
||||
materialMatchMap,
|
||||
userUploadedMaterials,
|
||||
matchMaterials,
|
||||
matchSingleMaterial,
|
||||
switchMaterial,
|
||||
uploadMaterial,
|
||||
setMaterialMatchMap,
|
||||
|
||||
@@ -143,7 +143,7 @@ export default function VideoGeneration() {
|
||||
const {
|
||||
materialMatchMap,
|
||||
userUploadedMaterials,
|
||||
matchMaterials,
|
||||
matchSingleMaterial,
|
||||
switchMaterial,
|
||||
uploadMaterial,
|
||||
setMaterialMatchMap,
|
||||
@@ -320,9 +320,9 @@ export default function VideoGeneration() {
|
||||
await uploadMaterial(shotId);
|
||||
};
|
||||
|
||||
// 处理素材匹配(手动触发批量匹配)
|
||||
const handleMatchMaterial = async (_shotId: string) => {
|
||||
await matchMaterials();
|
||||
// 处理素材匹配(单个镜头触发匹配)
|
||||
const handleMatchMaterial = async (shotId: string) => {
|
||||
await matchSingleMaterial(shotId);
|
||||
};
|
||||
|
||||
const activeShot = shots.find((s) => Number(s.id) === activeScene);
|
||||
|
||||
Reference in New Issue
Block a user