forked from 77media/video-flow
211 lines
6.1 KiB
TypeScript
211 lines
6.1 KiB
TypeScript
import { useState, useCallback } from "react";
|
||
import { VideoSegmentEditUseCase } from "../usecase/ShotEditUsecase";
|
||
import { VideoSegmentEntity } from "../domain/Entities";
|
||
import { ContentItem, LensType } from "../domain/valueObject";
|
||
|
||
/**
|
||
* 视频片段服务Hook接口
|
||
* 定义视频片段服务Hook的所有状态和操作方法
|
||
*/
|
||
export interface UseShotService {
|
||
// 响应式状态
|
||
/** 加载状态 */
|
||
loading: boolean;
|
||
/** 视频片段列表 */
|
||
videoSegments: VideoSegmentEntity[];
|
||
/** 当前选中的视频片段 */
|
||
selectedSegment: VideoSegmentEntity | null;
|
||
/** 错误信息 */
|
||
error: string | null;
|
||
|
||
// 操作方法
|
||
/** 获取视频片段列表 */
|
||
getVideoSegmentList: (projectId: string) => Promise<void>;
|
||
/** 重新生成视频片段 */
|
||
regenerateVideoSegment: (
|
||
shotPrompt: LensType[],
|
||
shotId?: string,
|
||
roleReplaceParams?: { oldId: string; newId: string }[],
|
||
sceneReplaceParams?: { oldId: string; newId: string }[]
|
||
) => Promise<VideoSegmentEntity>;
|
||
/** AI优化视频内容 */
|
||
optimizeVideoContent: (
|
||
shotId: string,
|
||
userRequirement: string,
|
||
lensData: LensType[]
|
||
) => Promise<LensType[]>;
|
||
/** 中断当前操作 */
|
||
abortOperation: () => void;
|
||
/** 设置选中的视频片段 */
|
||
setSelectedSegment: (segment: VideoSegmentEntity | null) => void;
|
||
/** 清除错误信息 */
|
||
clearError: () => void;
|
||
}
|
||
|
||
/**
|
||
* 视频片段服务Hook
|
||
* 提供视频片段相关的所有状态管理和操作方法
|
||
* 包括获取视频列表、重新生成视频、AI优化等功能
|
||
*/
|
||
export const useShotService = (): UseShotService => {
|
||
// 响应式状态
|
||
const [loading, setLoading] = useState<boolean>(false);
|
||
const [videoSegments, setVideoSegments] = useState<VideoSegmentEntity[]>([]);
|
||
const [selectedSegment, setSelectedSegment] = useState<VideoSegmentEntity | null>(null);
|
||
const [error, setError] = useState<string | null>(null);
|
||
|
||
// UseCase实例
|
||
const [shotEditUseCase] = useState<VideoSegmentEditUseCase>(
|
||
new VideoSegmentEditUseCase()
|
||
);
|
||
|
||
/**
|
||
* 获取视频片段列表
|
||
* @param projectId 项目ID
|
||
*/
|
||
const getVideoSegmentList = useCallback(
|
||
async (projectId: string): Promise<void> => {
|
||
try {
|
||
setLoading(true);
|
||
setError(null);
|
||
|
||
const segments = await shotEditUseCase.getVideoSegmentList(projectId);
|
||
setVideoSegments(segments);
|
||
} catch (error) {
|
||
const errorMessage = error instanceof Error ? error.message : "获取视频片段列表失败";
|
||
setError(errorMessage);
|
||
console.error("获取视频片段列表失败:", error);
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
},
|
||
[shotEditUseCase]
|
||
);
|
||
|
||
/**
|
||
* 重新生成视频片段
|
||
* @param shotPrompt 镜头描述数据
|
||
* @param shotId 视频片段ID(可选)
|
||
* @param roleReplaceParams 角色替换参数(可选)
|
||
* @param sceneReplaceParams 场景替换参数(可选)
|
||
* @returns Promise<VideoSegmentEntity> 重新生成的视频片段
|
||
*/
|
||
const regenerateVideoSegment = useCallback(
|
||
async (
|
||
shotPrompt: LensType[],
|
||
shotId?: string,
|
||
roleReplaceParams?: { oldId: string; newId: string }[],
|
||
sceneReplaceParams?: { oldId: string; newId: string }[]
|
||
): Promise<VideoSegmentEntity> => {
|
||
try {
|
||
setLoading(true);
|
||
setError(null);
|
||
|
||
const regeneratedSegment = await shotEditUseCase.regenerateVideoSegment(
|
||
shotPrompt,
|
||
shotId,
|
||
roleReplaceParams,
|
||
sceneReplaceParams
|
||
);
|
||
|
||
// 如果重新生成的是现有片段,更新列表中的对应项
|
||
if (shotId) {
|
||
setVideoSegments(prev =>
|
||
prev.map(segment =>
|
||
segment.id === shotId ? regeneratedSegment : segment
|
||
)
|
||
);
|
||
} else {
|
||
// 如果是新生成的片段,添加到列表中
|
||
setVideoSegments(prev => [...prev, regeneratedSegment]);
|
||
}
|
||
|
||
return regeneratedSegment;
|
||
} catch (error) {
|
||
const errorMessage = error instanceof Error ? error.message : "重新生成视频片段失败";
|
||
setError(errorMessage);
|
||
console.error("重新生成视频片段失败:", error);
|
||
throw error;
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
},
|
||
[shotEditUseCase]
|
||
);
|
||
|
||
/**
|
||
* AI优化视频内容
|
||
* @param shotId 视频片段ID
|
||
* @param userRequirement 用户优化需求
|
||
* @param lensData 镜头数据数组
|
||
* @returns Promise<LensType[]> 优化后的镜头数据
|
||
*/
|
||
const optimizeVideoContent = useCallback(
|
||
async (
|
||
shotId: string,
|
||
userRequirement: string,
|
||
lensData: LensType[]
|
||
): Promise<LensType[]> => {
|
||
try {
|
||
setLoading(true);
|
||
setError(null);
|
||
|
||
const optimizedLensData = await shotEditUseCase.optimizeVideoContent(
|
||
shotId,
|
||
userRequirement,
|
||
lensData
|
||
);
|
||
|
||
// 注意:这里不再更新videoSegments状态,因为返回的是LensType[]而不是VideoSegmentEntity
|
||
// 调用者需要自己处理优化后的镜头数据
|
||
|
||
return optimizedLensData;
|
||
} catch (error) {
|
||
const errorMessage = error instanceof Error ? error.message : "AI优化视频内容失败";
|
||
setError(errorMessage);
|
||
console.error("AI优化视频内容失败:", error);
|
||
throw error;
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
},
|
||
[shotEditUseCase]
|
||
);
|
||
/**
|
||
* 中断当前操作
|
||
*/
|
||
const abortOperation = useCallback((): void => {
|
||
shotEditUseCase.abortOperation();
|
||
setLoading(false);
|
||
}, [shotEditUseCase]);
|
||
|
||
/**
|
||
* 设置选中的视频片段
|
||
*/
|
||
const setSelectedSegmentHandler = useCallback((segment: VideoSegmentEntity | null): void => {
|
||
setSelectedSegment(segment);
|
||
}, []);
|
||
|
||
/**
|
||
* 清除错误信息
|
||
*/
|
||
const clearError = useCallback((): void => {
|
||
setError(null);
|
||
}, []);
|
||
|
||
return {
|
||
// 响应式状态
|
||
loading,
|
||
videoSegments,
|
||
selectedSegment,
|
||
error,
|
||
// 操作方法
|
||
getVideoSegmentList,
|
||
regenerateVideoSegment,
|
||
optimizeVideoContent,
|
||
abortOperation,
|
||
setSelectedSegment: setSelectedSegmentHandler,
|
||
clearError,
|
||
};
|
||
};
|