feat: 匹配素材改为针对单个镜头匹配

- 新增 matchSingleMaterial 函数,调用单条匹配 API
- 点击'匹配素材'只匹配当前镜头,不影响其他镜头
This commit is contained in:
小鱼开发
2026-05-21 21:24:57 +08:00
parent e52513f452
commit d6fe43b7c3
2 changed files with 35 additions and 4 deletions
@@ -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);