video-flow-b/api/video_flow.ts

342 lines
8.9 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 { post } from './request';
import { ProjectTypeEnum } from '@/app/model/enums';
import { ApiResponse } from '@/api/common';
import { BASE_URL } from './constants'
import { AITextEntity, RoleEntity, SceneEntity, ShotEntity, TagEntity } from '@/app/service/domain/Entities';
// 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 {
category: 'sketch' | 'character' | 'video' | 'music' | 'final_video';
message: string;
data: any;
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 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<分镜列表>>
*/
export const getRoleShots = async (request: {
/** 角色ID */
roleId: string;
}): Promise<ApiResponse<{
/** 分镜列表 */
shots: ShotEntity[];
/** 已应用的分镜ID列表 */
appliedShotIds: string[];
}>> => {
return post<ApiResponse<any>>('/movie/get_role_shots', request);
};
/**
* 获取场景应用到的分镜列表
* @param request - 获取场景分镜列表请求参数
* @returns Promise<ApiResponse<分镜列表>>
*/
export const getSceneShots = async (request: {
/** 场景ID */
sceneId: string;
}): Promise<ApiResponse<{
/** 分镜列表 */
shots: ShotEntity[];
/** 已应用的分镜ID列表 */
appliedShotIds: string[];
}>> => {
return post<ApiResponse<any>>('/movie/get_scene_shots', request);
};