video-flow-b/app/service/usecase/ScriptEditUseCase.ts

190 lines
4.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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();
}
}