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

256 lines
6.2 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,
enhanceScriptStream,
} from "@/api/video_flow";
export type ScriptEditKey = 'synopsis' | 'categories' | 'protagonist' | 'incitingIncident' | 'problem' | 'conflict' | 'stakes' | 'characterArc';
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 scriptData 剧本数据
* @param stream_callback 流式数据回调函数
* @returns Promise<void>
*/
async enhanceScript(
newScript: string|string[],
key: ScriptEditKey,
aiOptimizing: string,
stream_callback?: (data: any) => void
): Promise<void> {
try {
this.loading = true;
// 创建新的中断控制器
this.abortController = new AbortController();
// 获取当前剧本文本
const originalScript = this.scriptValueObject.toString();
// 清空当前剧本
this.scriptValueObject = new ScriptValueObject("");
// 使用API接口增强剧本
await enhanceScriptStream(
{
original_script: originalScript,
[key]: newScript,
aiOptimizing,
},
(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: 创建项目
* @param prompt 用户提示词
* @param userId 用户ID
* @param mode automatic | manual
* @param resolution 分辨率720p | 1080p | 4k
* @returns Promise<string> 返回项目ID
*/
async createProject(
prompt: string,
userId: string ,
mode: "automatic" | "manual" = "automatic",
resolution: "720p" | "1080p" | "4k" = "720p",
language: string
) {
try {
// 调用创建项目API
const response = await createMovieProjectV1({
script: prompt,
user_id: userId,
mode,
resolution,
language,
});
if (!response.successful) {
throw new Error(response.message || "创建项目失败");
}
return response.data;
} catch (error) {
console.error("创建项目失败:", error);
throw error;
}
}
/**
* @description: 保存剧本
* @param projectId 项目ID
* @param scriptData 剧本数据
* @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,
});
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 StoryDetails
*/
getStoryDetails() {
return this.scriptValueObject.storyDetails.toObject();
}
/**
* @description: 更新剧本
* @param scriptText 新的剧本文本
*/
updateScript(scriptText: string): void {
this.scriptValueObject = new ScriptValueObject(scriptText);
}
/**
* @description: 更新故事详情字段
* @param field 字段名
* @param value 字段值
*/
updateStoryField(field: ScriptEditKey, value: string | string[]): void {
const storyDetails = this.scriptValueObject.storyDetails;
if(field === 'categories'){
storyDetails.categories = value as string[];
}else{
storyDetails[field] = value as string;
}
}
/**
* @description: 获取加载状态
* @returns boolean
*/
isLoading(): boolean {
return this.loading;
}
/**
* @description: 将当前剧本片段转换为字符串
* @returns string
*/
toString(): string {
return this.scriptValueObject.toString();
}
}