forked from 77media/video-flow
190 lines
4.8 KiB
TypeScript
190 lines
4.8 KiB
TypeScript
import { ScriptSlice, ScriptValueObject } from "../domain/valueObject";
|
||
import { generateScriptStream, applyScriptToShot, createMovieProjectV1, saveScript } from "@/api/video_flow";
|
||
|
||
export class ScriptEditUseCase {
|
||
loading: boolean = false;
|
||
private scriptValueObject: ScriptValueObject;
|
||
private abortController: AbortController | null = null;
|
||
|
||
constructor(script: string) {
|
||
this.scriptValueObject = new ScriptValueObject(script);
|
||
}
|
||
|
||
/**
|
||
* @description: AI生成剧本方法
|
||
* @param prompt 剧本提示词
|
||
* @param stream_callback 流式数据回调函数
|
||
* @returns Promise<void>
|
||
*/
|
||
async generateScript(prompt: string, stream_callback?: (data: any) => void): Promise<void> {
|
||
try {
|
||
this.loading = true;
|
||
|
||
// 创建新的中断控制器
|
||
this.abortController = new AbortController();
|
||
|
||
// 使用API接口生成剧本
|
||
await generateScriptStream({
|
||
text: prompt,
|
||
},(content)=>{
|
||
stream_callback?.(content)
|
||
this.scriptValueObject.parseFromString(content)
|
||
});
|
||
|
||
|
||
} catch (error) {
|
||
if (this.abortController?.signal.aborted) {
|
||
console.log("剧本生成被中断");
|
||
return;
|
||
}
|
||
console.error("AI生成剧本出错:", error);
|
||
throw error;
|
||
} finally {
|
||
this.loading = false;
|
||
this.abortController = null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @description: 中断剧本生成
|
||
*/
|
||
abortGenerateScript(): void {
|
||
if (this.abortController) {
|
||
this.abortController.abort();
|
||
this.loading = false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @description: 创建项目
|
||
* @param prompt 用户提示词
|
||
* @param userId 用户ID
|
||
* @param mode 模式:auto | manual
|
||
* @param resolution 分辨率:720p | 1080p | 4k
|
||
* @returns Promise<string> 返回项目ID
|
||
*/
|
||
async createProject(
|
||
prompt: string,
|
||
userId: string = "user123",
|
||
mode: "auto" | "manual" = "auto",
|
||
resolution: "720p" | "1080p" | "4k" = "720p"
|
||
) {
|
||
try {
|
||
// 调用创建项目API
|
||
const response = await createMovieProjectV1({
|
||
script: prompt,
|
||
user_id: userId,
|
||
mode,
|
||
resolution
|
||
});
|
||
|
||
if (!response.successful) {
|
||
throw new Error(response.message || "创建项目失败");
|
||
}
|
||
return response.data;
|
||
} catch (error) {
|
||
console.error("创建项目失败:", error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @description: 保存剧本
|
||
* @param projectId 项目ID
|
||
* @returns Promise<void>
|
||
*/
|
||
async saveScript(projectId: string): Promise<void> {
|
||
try {
|
||
this.loading = true;
|
||
|
||
// 获取当前剧本文本
|
||
const scriptText = this.scriptValueObject.toString();
|
||
|
||
// 调用保存剧本API
|
||
const response = await saveScript({
|
||
project_id: projectId,
|
||
generated_script: scriptText,
|
||
synopsis: this.scriptValueObject.storyDetails.synopsis,
|
||
categories: this.scriptValueObject.storyDetails.categories,
|
||
protagonist: this.scriptValueObject.storyDetails.protagonist,
|
||
framework: this.scriptValueObject.storyDetails.mergeframework()
|
||
});
|
||
|
||
if (!response.successful) {
|
||
throw new Error(response.message || "保存剧本失败");
|
||
}
|
||
return response.data;
|
||
} catch (error) {
|
||
console.error("保存剧本失败:", error);
|
||
throw error;
|
||
} finally {
|
||
this.loading = false;
|
||
}
|
||
}
|
||
/**
|
||
* @description: 应用剧本方法
|
||
* @returns Promise<void>
|
||
*/
|
||
async applyScript(projectId: string,planId: string): Promise<void> {
|
||
try {
|
||
this.loading = true;
|
||
|
||
// 调用应用剧本接口
|
||
const response = await applyScriptToShot({
|
||
project_id: projectId,
|
||
plan_id: planId
|
||
});
|
||
|
||
if (!response.successful) {
|
||
throw new Error(response.message || "应用剧本失败");
|
||
}
|
||
|
||
console.log("剧本应用成功");
|
||
} catch (error) {
|
||
console.error("应用剧本失败:", error);
|
||
throw error;
|
||
} finally {
|
||
this.loading = false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @description: 获取当前剧本片段列表
|
||
* @returns ScriptSlice[]
|
||
*/
|
||
getScriptSlices(): ScriptSlice[] {
|
||
return [...this.scriptValueObject.scriptSlices];
|
||
}
|
||
/**
|
||
* @description: 获取当前剧本故事详情
|
||
* @returns StoryDetails
|
||
*/
|
||
getStoryDetails() {
|
||
return this.scriptValueObject.storyDetails.toObject();
|
||
}
|
||
/**
|
||
* @description: 获取加载状态
|
||
* @returns boolean
|
||
*/
|
||
isLoading(): boolean {
|
||
return this.loading;
|
||
}
|
||
|
||
/**
|
||
* @description: 更新剧本
|
||
* @param scriptText 剧本文本字符串
|
||
*/
|
||
updateScript(scriptText: string): void {
|
||
this.scriptValueObject = new ScriptValueObject(scriptText);
|
||
}
|
||
|
||
/**
|
||
* @description: 将当前剧本片段转换为字符串
|
||
* @returns string
|
||
*/
|
||
toString(): string {
|
||
return this.scriptValueObject.toString();
|
||
}
|
||
|
||
}
|