forked from 77media/video-flow
766 lines
19 KiB
TypeScript
766 lines
19 KiB
TypeScript
import { post, streamJsonPost } from "./request";
|
||
import { ProjectTypeEnum } from "@/app/model/enums";
|
||
import { ApiResponse } from "@/api/common";
|
||
import { BASE_URL } from "./constants";
|
||
import {
|
||
AITextEntity,
|
||
RoleEntity,
|
||
SceneEntity,
|
||
VideoSegmentEntity,
|
||
TagEntity,
|
||
} from "@/app/service/domain/Entities";
|
||
import {
|
||
ContentItem,
|
||
LensType,
|
||
ScriptSlice,
|
||
} from "@/app/service/domain/valueObject";
|
||
|
||
// API 响应类型
|
||
interface BaseApiResponse<T> {
|
||
code: number;
|
||
successful: boolean;
|
||
message: string;
|
||
data: T;
|
||
}
|
||
|
||
// 剧集详情数据类型
|
||
interface EpisodeDetail {
|
||
project_id: string;
|
||
name: string;
|
||
status: "running" | "completed";
|
||
step: "sketch" | "character" | "video" | "music" | "final_video";
|
||
last_message: string;
|
||
data: TaskData | null;
|
||
mode: "auto" | "manual";
|
||
resolution: "1080p" | "4k";
|
||
}
|
||
|
||
// 任务数据类型
|
||
interface TaskData {
|
||
sketch?: Array<{
|
||
url: string;
|
||
script: string;
|
||
bg_rgb: string[];
|
||
}>;
|
||
roles?: Array<{
|
||
name: string;
|
||
url: string;
|
||
sound: string;
|
||
soundDescription: string;
|
||
roleDescription: string;
|
||
}>;
|
||
videos?: Array<{
|
||
url: string;
|
||
script: string;
|
||
audio: string;
|
||
}>;
|
||
music?: Array<{
|
||
url: string;
|
||
script: string;
|
||
name: string;
|
||
duration: string;
|
||
totalDuration: string;
|
||
isLooped: boolean;
|
||
}>;
|
||
final?: {
|
||
url: string;
|
||
};
|
||
}
|
||
|
||
// 流式数据类型
|
||
export interface StreamData<T = any> {
|
||
category: "sketch" | "character" | "video" | "music" | "final_video";
|
||
message: string;
|
||
data: T;
|
||
status: "running" | "completed";
|
||
total?: number;
|
||
completed?: number;
|
||
all_completed?: boolean;
|
||
}
|
||
|
||
// 场景/分镜头数据结构
|
||
export interface Scene {
|
||
id: string;
|
||
name: string;
|
||
description: string;
|
||
plot: string;
|
||
dialogue: string;
|
||
narration: string;
|
||
imageUrl?: string;
|
||
}
|
||
|
||
// 角色数据结构
|
||
export interface Character {
|
||
name: string;
|
||
desc: string;
|
||
}
|
||
|
||
// 剧本到分镜头提示词模型
|
||
export interface ScenePrompts {
|
||
scenes: Scene[]; // 分场景列表
|
||
characters?: Character[]; // 角色列表
|
||
summary?: string; // 剧情概要
|
||
scene?: string; // 场景描述
|
||
atmosphere?: string; // 氛围描述
|
||
episode_id?: number; // 剧集ID
|
||
total_shots?: string; // 总镜头数
|
||
}
|
||
|
||
// 剧本转分镜头请求接口
|
||
export interface ScriptToSceneRequest {
|
||
script: string;
|
||
episode_id: number;
|
||
script_id: number;
|
||
project_type: ProjectTypeEnum.SCRIPT_TO_VIDEO;
|
||
}
|
||
|
||
// 视频转分镜头请求接口
|
||
export interface VideoToSceneRequest {
|
||
video_url: string;
|
||
episode_id: number;
|
||
script_id: number;
|
||
project_type: ProjectTypeEnum.VIDEO_TO_VIDEO;
|
||
}
|
||
|
||
// 转换分镜头请求类型
|
||
export type ConvertScenePromptRequest =
|
||
| ScriptToSceneRequest
|
||
| VideoToSceneRequest;
|
||
|
||
// 转换分镜头响应接口
|
||
export type ConvertScenePromptResponse = BaseApiResponse<ScenePrompts>;
|
||
|
||
/**
|
||
* 将剧本或视频转换为分镜头提示词
|
||
* @param request - 请求参数,根据 project_type 自动判断是剧本还是视频模式
|
||
* @returns Promise<ConvertScenePromptResponse>
|
||
*/
|
||
export const convertScenePrompt = async (
|
||
request: ConvertScenePromptRequest
|
||
): Promise<ConvertScenePromptResponse> => {
|
||
// return post<ConvertScenePromptResponse>('/video_flow/convert-scene-prompts', request);
|
||
return new Promise((resolve) => {
|
||
setTimeout(() => {
|
||
resolve({
|
||
code: 0,
|
||
message: "success",
|
||
data: {
|
||
scenes: [],
|
||
characters: [],
|
||
summary: "",
|
||
scene: "",
|
||
atmosphere: "",
|
||
episode_id: 0,
|
||
total_shots: "",
|
||
},
|
||
successful: true,
|
||
});
|
||
}, 0);
|
||
});
|
||
};
|
||
|
||
/**
|
||
* 剧本转分镜头提示词
|
||
* @param script - 剧本内容
|
||
* @returns Promise<ConvertScenePromptResponse>
|
||
*/
|
||
export const convertScriptToScene = async (
|
||
script: string,
|
||
episode_id: number,
|
||
script_id: number
|
||
): Promise<ConvertScenePromptResponse> => {
|
||
return convertScenePrompt({
|
||
script,
|
||
episode_id,
|
||
script_id,
|
||
project_type: ProjectTypeEnum.SCRIPT_TO_VIDEO,
|
||
});
|
||
};
|
||
|
||
/**
|
||
* 视频转分镜头提示词
|
||
* @param video_url - 视频链接
|
||
* @returns Promise<ConvertScenePromptResponse>
|
||
*/
|
||
export const convertVideoToScene = async (
|
||
video_url: string,
|
||
episode_id: number,
|
||
script_id: number
|
||
): Promise<ConvertScenePromptResponse> => {
|
||
return convertScenePrompt({
|
||
video_url,
|
||
episode_id,
|
||
script_id,
|
||
project_type: ProjectTypeEnum.VIDEO_TO_VIDEO,
|
||
});
|
||
};
|
||
|
||
// 新-获取剧集详情
|
||
export const detailScriptEpisodeNew = async (data: {
|
||
project_id: string;
|
||
}): Promise<ApiResponse<any>> => {
|
||
return post<ApiResponse<any>>("/movie/get_movie_project_detail", data);
|
||
};
|
||
|
||
// 获取 title 接口
|
||
export const getScriptTitle = async (data: {
|
||
project_id: string;
|
||
}): Promise<ApiResponse<any>> => {
|
||
return post<ApiResponse<any>>("/movie/get_movie_project_description", data);
|
||
};
|
||
|
||
// 获取 数据 全量(需轮询)
|
||
export const getRunningStreamData = async (data: {
|
||
project_id: string;
|
||
}): Promise<ApiResponse<any>> => {
|
||
return post<ApiResponse<any>>("/movie/get_status", data);
|
||
};
|
||
|
||
// 获取 脚本 接口
|
||
export const getScriptTags = async (data: {
|
||
project_id: string;
|
||
}): Promise<any> => {
|
||
return post<any>("/movie/text_to_script_tags", data);
|
||
};
|
||
|
||
// 获取 loading-场景 接口
|
||
export const getSceneJson = async (data: {
|
||
project_id: string;
|
||
}): Promise<ApiResponse<any>> => {
|
||
return post<any>("/movie/scene_json", data);
|
||
};
|
||
|
||
// 获取 loading-分镜 接口
|
||
export const getShotSketchJson = async (data: {
|
||
project_id: string;
|
||
}): Promise<ApiResponse<any>> => {
|
||
return post<any>("/movie/shot_sketch_json", data);
|
||
};
|
||
|
||
// 获取 loading-视频 接口
|
||
export const getVideoJson = async (data: {
|
||
project_id: string;
|
||
}): Promise<ApiResponse<any>> => {
|
||
return post<any>("/movie/video_json", data);
|
||
};
|
||
|
||
/**
|
||
* 重新生成角色
|
||
* @param request - 重新生成角色请求参数
|
||
* @returns Promise<ApiResponse<RoleEntity>>
|
||
*/
|
||
export const regenerateRole = async (request: {
|
||
/** 角色提示词 */
|
||
prompt: string;
|
||
/** 标签类型列表 */
|
||
tagTypes: (number | string)[];
|
||
/** 角色ID(可选,如果重新生成现有角色) */
|
||
roleId?: string;
|
||
}): Promise<ApiResponse<RoleEntity>> => {
|
||
return post<ApiResponse<any>>("/movie/regenerate_role", request);
|
||
};
|
||
|
||
/**
|
||
* 应用角色到分镜
|
||
* @param request - 应用角色请求参数
|
||
* @returns Promise<ApiResponse<应用结果>>
|
||
*/
|
||
export const applyRoleToShots = async (request: {
|
||
/** 角色ID */
|
||
roleId: string;
|
||
/** 分镜ID列表 */
|
||
shotIds: string[];
|
||
}): Promise<ApiResponse<any>> => {
|
||
return post<ApiResponse<any>>("/movie/apply_role_to_shots", request);
|
||
};
|
||
|
||
/**
|
||
* 获取角色应用到的分镜列表
|
||
* @param request - 获取角色分镜列表请求参数
|
||
* @returns Promise<ApiResponse<分镜列表>>
|
||
*/
|
||
export const getRoleShots = async (request: {
|
||
/** 角色ID */
|
||
roleId: string;
|
||
}): Promise<
|
||
ApiResponse<{
|
||
/** 分镜列表 */
|
||
shots: VideoSegmentEntity[];
|
||
/** 已应用的分镜ID列表 */
|
||
appliedShotIds: string[];
|
||
}>
|
||
> => {
|
||
return post<ApiResponse<any>>("/movie/get_role_shots", request);
|
||
};
|
||
|
||
/**
|
||
* 获取角色列表
|
||
* @param request - 获取角色列表请求参数
|
||
* @returns Promise<ApiResponse<角色实体列表>>
|
||
*/
|
||
export const getRoleList = async (request: {
|
||
/** 项目ID */
|
||
projectId: string;
|
||
}): Promise<ApiResponse<RoleEntity[]>> => {
|
||
return post<ApiResponse<any>>("/movie/get_role_list", request);
|
||
};
|
||
|
||
/**
|
||
* 获取角色数据
|
||
* @param request - 获取角色数据请求参数
|
||
* @returns Promise<ApiResponse<{ AI文本数据, 标签列表 }>>
|
||
*/
|
||
export const getRoleData = async (request: {
|
||
/** 角色ID */
|
||
roleId: string;
|
||
}): Promise<
|
||
ApiResponse<{
|
||
/** AI文本数据 */
|
||
text: AITextEntity;
|
||
/** 标签列表 */
|
||
tags: TagEntity[];
|
||
}>
|
||
> => {
|
||
return post<ApiResponse<any>>("/movie/get_role_data", request);
|
||
};
|
||
|
||
/**
|
||
* 获取用户角色库
|
||
* @returns Promise<ApiResponse<角色实体列表>>
|
||
*/
|
||
export const getUserRoleLibrary = async (): Promise<
|
||
ApiResponse<RoleEntity[]>
|
||
> => {
|
||
return post<ApiResponse<any>>("/movie/get_user_role_library", {});
|
||
};
|
||
|
||
/**
|
||
* 替换角色
|
||
* @param request - 替换角色请求参数
|
||
* @returns Promise<ApiResponse<替换结果>>
|
||
*/
|
||
export const replaceRole = async (request: {
|
||
/** 当前角色ID */
|
||
currentRoleId: string;
|
||
/** 替换的角色ID */
|
||
replaceRoleId: string;
|
||
}): Promise<ApiResponse<any>> => {
|
||
return post<ApiResponse<any>>("/movie/replace_role", request);
|
||
};
|
||
|
||
/**
|
||
* 修改标签
|
||
* @param request - 修改标签请求参数
|
||
* @returns Promise<ApiResponse<修改后的标签>>
|
||
*/
|
||
export const updateTag = async (request: {
|
||
/** 标签ID */
|
||
tagId: string;
|
||
/** 新的标签内容 */
|
||
content: string | number;
|
||
}): Promise<ApiResponse<TagEntity>> => {
|
||
return post<ApiResponse<any>>("/movie/update_tag", request);
|
||
};
|
||
|
||
/**
|
||
* 修改文案
|
||
* @param request - 修改文案请求参数
|
||
* @returns Promise<ApiResponse<修改后的文案>>
|
||
*/
|
||
export const updateText = async (request: {
|
||
/** 文案ID */
|
||
textId: string;
|
||
/** 新的文案内容 */
|
||
content: string;
|
||
}): Promise<ApiResponse<AITextEntity>> => {
|
||
return post<ApiResponse<any>>("/movie/update_text", request);
|
||
};
|
||
|
||
/**
|
||
* 重新生成场景
|
||
* @param request - 重新生成场景请求参数
|
||
* @returns Promise<ApiResponse<重新生成的场景>>
|
||
*/
|
||
export const regenerateScene = async (request: {
|
||
/** 场景提示词 */
|
||
prompt: string;
|
||
/** 标签类型列表 */
|
||
tagTypes: (number | string)[];
|
||
/** 场景ID(可选,如果重新生成现有场景) */
|
||
sceneId?: string;
|
||
}): Promise<ApiResponse<SceneEntity>> => {
|
||
return post<ApiResponse<any>>("/movie/regenerate_scene", request);
|
||
};
|
||
|
||
/**
|
||
* 应用场景到分镜
|
||
* @param request - 应用场景请求参数
|
||
* @returns Promise<ApiResponse<应用结果>>
|
||
*/
|
||
export const applySceneToShots = async (request: {
|
||
/** 场景ID */
|
||
sceneId: string;
|
||
/** 分镜ID列表 */
|
||
shotIds: string[];
|
||
}): Promise<ApiResponse<any>> => {
|
||
return post<ApiResponse<any>>("/movie/apply_scene_to_shots", request);
|
||
};
|
||
|
||
/**
|
||
* 获取场景数据
|
||
* @param request - 获取场景数据请求参数
|
||
* @returns Promise<ApiResponse<{ AI文本数据, 标签列表 }>>
|
||
*/
|
||
export const getSceneData = async (request: {
|
||
/** 场景ID */
|
||
sceneId: string;
|
||
}): Promise<
|
||
ApiResponse<{
|
||
/** AI文本数据 */
|
||
text: AITextEntity;
|
||
/** 标签列表 */
|
||
tags: TagEntity[];
|
||
}>
|
||
> => {
|
||
return post<ApiResponse<any>>("/movie/get_scene_data", request);
|
||
};
|
||
|
||
/**
|
||
* 获取场景列表
|
||
* @param request - 获取场景列表请求参数
|
||
* @returns Promise<ApiResponse<场景实体列表>>
|
||
*/
|
||
export const getSceneList = async (request: {
|
||
/** 项目ID */
|
||
projectId: string;
|
||
}): Promise<ApiResponse<SceneEntity[]>> => {
|
||
return post<ApiResponse<any>>("/movie/get_scene_list", request);
|
||
};
|
||
|
||
/**
|
||
* 获取场景应用到的分镜列表
|
||
* @param request - 获取场景分镜列表请求参数
|
||
* @returns Promise<ApiResponse<分镜列表>>
|
||
*/
|
||
export const getSceneShots = async (request: {
|
||
/** 场景ID */
|
||
sceneId: string;
|
||
}): Promise<
|
||
ApiResponse<{
|
||
/** 分镜列表 */
|
||
shots: VideoSegmentEntity[];
|
||
/** 已应用的分镜ID列表 */
|
||
appliedShotIds: string[];
|
||
}>
|
||
> => {
|
||
return post<ApiResponse<any>>("/movie/get_scene_shots", request);
|
||
};
|
||
|
||
/**
|
||
* 获取分镜关联的角色信息列表
|
||
* @param request - 获取分镜角色信息请求参数
|
||
* @returns Promise<ApiResponse<角色实体列表>>
|
||
*/
|
||
export const getShotRoles = async (request: {
|
||
/** 分镜ID */
|
||
shotId: string;
|
||
}): Promise<ApiResponse<RoleEntity[]>> => {
|
||
return post<ApiResponse<any>>("/movie/get_shot_roles", request);
|
||
};
|
||
|
||
/**
|
||
* 获取分镜关联的场景信息列表
|
||
* @param request - 获取分镜场景信息请求参数
|
||
* @returns Promise<ApiResponse<场景实体列表>>
|
||
*/
|
||
export const getShotScenes = async (request: {
|
||
/** 分镜ID */
|
||
shotId: string;
|
||
}): Promise<ApiResponse<SceneEntity[]>> => {
|
||
return post<ApiResponse<any>>("/movie/get_shot_scenes", request);
|
||
};
|
||
|
||
/**
|
||
* 获取分镜详细数据
|
||
* @param request - 获取分镜数据请求参数
|
||
* @returns Promise<ApiResponse<{ AI文本数据, 标签列表 }>>
|
||
*/
|
||
export const getShotData = async (request: {
|
||
/** 分镜ID */
|
||
shotId: string;
|
||
}): Promise<
|
||
ApiResponse<{
|
||
/** AI文本数据 */
|
||
text: AITextEntity;
|
||
/** 标签列表 */
|
||
tags: TagEntity[];
|
||
}>
|
||
> => {
|
||
return post<ApiResponse<any>>("/movie/get_shot_data", request);
|
||
};
|
||
|
||
/**
|
||
* 重新生成分镜
|
||
* @param request - 重新生成分镜请求参数
|
||
* @returns Promise<ApiResponse<重新生成的分镜>>
|
||
*/
|
||
export const regenerateShot = async (request: {
|
||
/** 分镜ID */
|
||
shotId?: string;
|
||
/** 镜头描述 */
|
||
shotPrompt?: LensType[];
|
||
/** 对话内容 */
|
||
dialogueContent?: ContentItem[];
|
||
/** 角色ID替换参数,格式为{oldId:string,newId:string}[] */
|
||
roleReplaceParams?: { oldId: string; newId: string }[];
|
||
/** 场景ID替换参数,格式为{oldId:string,newId:string}[] */
|
||
sceneReplaceParams?: { oldId: string; newId: string }[];
|
||
}): Promise<ApiResponse<VideoSegmentEntity>> => {
|
||
return post<ApiResponse<any>>("/movie/regenerate_shot", request);
|
||
};
|
||
|
||
/**
|
||
* 修改分镜对话内容
|
||
* @param request - 修改分镜对话内容请求参数
|
||
* @returns Promise<ApiResponse<修改后的分镜>>
|
||
*/
|
||
export const updateShotContent = async (request: {
|
||
/** 分镜ID */
|
||
shotId: string;
|
||
/** 新的对话内容,ContentItem数量和ID顺序不能变,只能修改content字段 */
|
||
content: Array<{
|
||
/** 角色ID */
|
||
roleId: string;
|
||
/** 对话内容 */
|
||
content: string;
|
||
}>;
|
||
}): Promise<ApiResponse<VideoSegmentEntity>> => {
|
||
return post<ApiResponse<any>>("/movie/update_shot_content", request);
|
||
};
|
||
|
||
/**
|
||
* 获取分镜列表
|
||
* @param request - 获取分镜列表请求参数
|
||
* @returns Promise<ApiResponse<分镜实体列表>>
|
||
*/
|
||
export const getShotList = async (request: {
|
||
/** 项目ID */
|
||
projectId: string;
|
||
}): Promise<ApiResponse<VideoSegmentEntity[]>> => {
|
||
return post<ApiResponse<any>>("/movie/get_shot_list", request);
|
||
};
|
||
|
||
/**
|
||
* 替换分镜角色
|
||
* @param request - 替换分镜角色请求参数
|
||
* @returns Promise<ApiResponse<替换结果>>
|
||
*/
|
||
export const replaceShotRole = async (request: {
|
||
/** 分镜ID */
|
||
shotId: string;
|
||
/** 旧角色ID */
|
||
oldRoleId: string;
|
||
/** 新角色ID */
|
||
newRoleId: string;
|
||
}): Promise<ApiResponse<any>> => {
|
||
return post<ApiResponse<any>>("/movie/replace_shot_role", request);
|
||
};
|
||
|
||
/**
|
||
* 获取分镜视频剧本内容
|
||
* @param request - 获取分镜视频剧本请求参数
|
||
* @returns Promise<ApiResponse<剧本片段列表>>
|
||
*/
|
||
export const getShotVideoScript = async (request: {
|
||
/** 分镜ID */
|
||
shotId: string;
|
||
}): Promise<ApiResponse<string>> => {
|
||
return post<ApiResponse<any>>("/movie/get_shot_video_script", request);
|
||
};
|
||
|
||
/**
|
||
* AI生成剧本流式接口
|
||
* @param request - AI生成剧本请求参数
|
||
* @returns Promise<ApiResponse<流式数据>>
|
||
*/
|
||
export const generateScriptStream = (
|
||
request: {
|
||
/** 剧本提示词 */
|
||
text: string;
|
||
},
|
||
onData: (data: any) => void
|
||
): Promise<void> => {
|
||
return new Promise((resolve, reject) => {
|
||
streamJsonPost("/text_to_script/stream", request, (data) => {
|
||
switch(data.status) {
|
||
case 'streaming':
|
||
onData(data.content);
|
||
break;
|
||
|
||
case 'completed':
|
||
console.log('生成完成:', data.message);
|
||
resolve()
|
||
return;
|
||
|
||
case 'error':
|
||
console.error('生成失败:', data.message);
|
||
reject(data.message)
|
||
return;
|
||
}
|
||
})
|
||
})
|
||
};
|
||
|
||
/**
|
||
* 应用剧本
|
||
* @param request - 应用剧本请求参数
|
||
* @returns Promise<ApiResponse<应用结果>>
|
||
*/
|
||
export const applyScriptToShot = async (request: {
|
||
/** 项目ID */
|
||
project_id: string;
|
||
/** 计划Id*/
|
||
plan_id: string;
|
||
})=> {
|
||
return post<ApiResponse<any>>("/movie/create_movie_project_plan_v1", request);
|
||
};
|
||
|
||
/**
|
||
* 获取项目剧本数据
|
||
* @param request 请求参数
|
||
*/
|
||
export const getProjectScript = async (request: {
|
||
/** 项目ID */
|
||
project_id: string;
|
||
})=> {
|
||
return post<
|
||
ApiResponse<{
|
||
/** 项目id */
|
||
project_id: string;
|
||
/** 生成的剧本文本 */
|
||
generated_script: string;
|
||
}>
|
||
>("/movie/get_generated_script_by_project_id", request);
|
||
};
|
||
|
||
/**
|
||
* 保存剧本
|
||
* @param request 保存剧本请求参数
|
||
* @returns Promise<ApiResponse<保存结果>>
|
||
*/
|
||
export const saveScript = async (request: {
|
||
/** 项目ID */
|
||
project_id: string;
|
||
/** 剧本文本 */
|
||
generated_script: string;
|
||
}): Promise<ApiResponse<any>> => {
|
||
return post<ApiResponse<any>>("/movie/update_generated_script", request);
|
||
};
|
||
|
||
|
||
/**
|
||
* 创建电影项目V1版本
|
||
* @param request 创建电影项目请求参数
|
||
* @returns Promise<ApiResponse<{ projectId: string }>>
|
||
*/
|
||
export const abortVideoTask = async (request: {
|
||
/** 项目ID */
|
||
project_id: string;
|
||
/** 计划ID */
|
||
plan_id: string;
|
||
}): Promise<ApiResponse<any>> => {
|
||
return post("/api/v1/video/abort", request);
|
||
};
|
||
|
||
export const pausePlanFlow = async (request: {
|
||
/** 项目ID */
|
||
project_id: string;
|
||
/** 计划ID */
|
||
plan_id: string;
|
||
}): Promise<ApiResponse<any>> => {
|
||
return post("/api/v1/video/pause", request);
|
||
};
|
||
|
||
export const resumePlanFlow = async (request: {
|
||
/** 项目ID */
|
||
project_id: string;
|
||
/** 计划ID */
|
||
plan_id: string;
|
||
}): Promise<ApiResponse<any>> => {
|
||
return post("/api/v1/video/resume", request);
|
||
};
|
||
|
||
export const createMovieProjectV1 = async (request: {
|
||
/** 剧本内容 */
|
||
script: string;
|
||
/** 用户ID */
|
||
user_id: string;
|
||
/** 模式:auto | manual */
|
||
mode: "auto" | "manual";
|
||
/** 分辨率:720p | 1080p | 4k */
|
||
resolution: "720p" | "1080p" | "4k";
|
||
}) => {
|
||
return post<ApiResponse<{
|
||
/** 项目ID */
|
||
project_id: string;
|
||
/** 计划ID */
|
||
plan_id: string;
|
||
/** 项目名称 */
|
||
name: string;
|
||
/** 项目状态 */
|
||
status: string;
|
||
}>>("/movie/create_movie_project_v1", request);
|
||
};
|
||
|
||
/**
|
||
* 增强剧本流式接口
|
||
* @param request - 增强剧本请求参数
|
||
* @param onData - 流式数据回调
|
||
* @returns Promise<void>
|
||
*/
|
||
export const enhanceScriptStream = (
|
||
request: {
|
||
/** 原始剧本文本 */
|
||
original_script: string;
|
||
/** 故事梗概 */
|
||
synopsis?: string;
|
||
/** 故事分类 */
|
||
categories?: string[];
|
||
/** 主角名称 */
|
||
protagonist?: string;
|
||
/** 激励事件 */
|
||
incitingIncident?: string;
|
||
/** 问题与新目标 */
|
||
problem?: string;
|
||
/** 冲突与障碍 */
|
||
conflict?: string;
|
||
/** 赌注 */
|
||
stakes?: string;
|
||
/** 人物弧线完成 */
|
||
characterArc?: string;
|
||
/** AI优化要求 */
|
||
aiOptimizing: string;
|
||
},
|
||
onData: (data: any) => void
|
||
): Promise<void> => {
|
||
return new Promise((resolve, reject) => {
|
||
streamJsonPost("/movie/enhance_script", request, (data) => {
|
||
switch(data.status) {
|
||
case 'streaming':
|
||
onData(data.content);
|
||
break;
|
||
|
||
case 'completed':
|
||
console.log('剧本增强完成:', data.message);
|
||
resolve()
|
||
return;
|
||
|
||
case 'error':
|
||
console.error('剧本增强失败:', data.message);
|
||
reject(data.message)
|
||
return;
|
||
}
|
||
})
|
||
})
|
||
};
|