forked from 77media/video-flow
新增视频流程项目相关的TypeScript类型定义,包含角色、场景、服装、音乐等数据结构。更新视频流接口以支持新类型,重构相关服务以提高一致性和可读性。
This commit is contained in:
parent
f89b5cc75c
commit
7d5bc5115c
503
api/allMovieType.ts
Normal file
503
api/allMovieType.ts
Normal file
@ -0,0 +1,503 @@
|
||||
/**
|
||||
* 视频流程项目相关的TypeScript类型定义
|
||||
* 包含角色、场景、服装、音乐等完整的数据结构
|
||||
*/
|
||||
|
||||
/**
|
||||
* 角色性别枚举
|
||||
*/
|
||||
export enum Gender {
|
||||
MALE = 'male',
|
||||
FEMALE = 'female'
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色种族枚举
|
||||
*/
|
||||
export enum Race {
|
||||
WESTERN = 'Western',
|
||||
ASIAN = 'Asian',
|
||||
AFRICAN = 'African',
|
||||
LATINO = 'Latino',
|
||||
MIDDLE_EASTERN = 'Middle Eastern',
|
||||
MIXED = 'Mixed'
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色类型枚举
|
||||
*/
|
||||
export enum RoleType {
|
||||
PROTAGONIST = 'Protagonist',
|
||||
ANTAGONIST = 'Antagonist',
|
||||
SUPPORTING = 'Supporting',
|
||||
BACKGROUND = 'Background'
|
||||
}
|
||||
|
||||
/**
|
||||
* 项目状态枚举
|
||||
*/
|
||||
export enum ProjectStatus {
|
||||
COMPLETED = 'COMPLETED',
|
||||
IN_PROGRESS = 'IN_PROGRESS',
|
||||
PENDING = 'PENDING',
|
||||
FAILED = 'FAILED'
|
||||
}
|
||||
|
||||
/**
|
||||
* 项目步骤枚举
|
||||
*/
|
||||
export enum ProjectStep {
|
||||
INIT = 'INIT',
|
||||
SKETCH = 'SKETCH',
|
||||
CHARACTER = 'CHARACTER',
|
||||
SHOT_SKETCH = 'SHOT_SKETCH',
|
||||
VIDEO = 'VIDEO',
|
||||
FINAL = 'FINAL'
|
||||
}
|
||||
|
||||
/**
|
||||
* 项目模式枚举
|
||||
*/
|
||||
export enum ProjectMode {
|
||||
AUTOMATIC = 'automatic',
|
||||
MANUAL = 'manual',
|
||||
HYBRID = 'hybrid'
|
||||
}
|
||||
|
||||
/**
|
||||
* 分辨率枚举
|
||||
*/
|
||||
export enum Resolution {
|
||||
P720 = '720p',
|
||||
P1080 = '1080p',
|
||||
P4K = '4K'
|
||||
}
|
||||
|
||||
/**
|
||||
* 语言枚举
|
||||
*/
|
||||
export enum Language {
|
||||
EN = 'en',
|
||||
ZH = 'zh',
|
||||
JA = 'ja',
|
||||
KO = 'ko'
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色信息接口
|
||||
*/
|
||||
export interface Character {
|
||||
/** 角色唯一标识符 */
|
||||
id: string;
|
||||
/** 角色名称 */
|
||||
name: string;
|
||||
/** 角色描述,包含外貌、性格等详细信息 */
|
||||
description: string;
|
||||
/** 角色类型 */
|
||||
role: RoleType;
|
||||
/** 角色年龄 */
|
||||
age: number;
|
||||
/** 角色性别 */
|
||||
gender: Gender;
|
||||
/** 角色种族 */
|
||||
race: Race;
|
||||
/** 角色简介 */
|
||||
brief?: string;
|
||||
/** 角色体型描述 */
|
||||
physique?: string;
|
||||
/** 角色发型描述 */
|
||||
hairstyle?: string;
|
||||
/** 角色默认举止描述 */
|
||||
default_demeanor?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 服装信息接口
|
||||
*/
|
||||
export interface Wardrobe {
|
||||
/** 服装所属角色ID */
|
||||
belongs_to: string;
|
||||
/** 服装详细描述 */
|
||||
description: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 场景信息接口
|
||||
*/
|
||||
export interface Scene {
|
||||
/** 场景名称 */
|
||||
name: string;
|
||||
/** 场景详细描述 */
|
||||
description: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 项目风格信息接口
|
||||
*/
|
||||
export interface ProjectStyle {
|
||||
/** 地理设置和种族信息 */
|
||||
geographic_setting_ethnicity: string;
|
||||
/** 格式要求 */
|
||||
format: string;
|
||||
/** 美学风格描述 */
|
||||
aesthetics: string;
|
||||
/** 技术蓝图 */
|
||||
technical_blueprint: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 提示JSON结构接口
|
||||
*/
|
||||
export interface PromptJson {
|
||||
/** 导演指令 */
|
||||
directors_directive: string;
|
||||
/** 叙事提示 */
|
||||
narrative_prompt: string;
|
||||
/** 对话语言 */
|
||||
dialogue_language: string;
|
||||
/** 整体项目风格 */
|
||||
overall_project_style: string;
|
||||
/** 主要角色列表 */
|
||||
master_character_list: MasterCharacter[];
|
||||
/** 主要服装列表 */
|
||||
master_wardrobe_list: MasterWardrobe[];
|
||||
/** 主要场景列表 */
|
||||
master_scene_list: MasterScene[];
|
||||
/** 核心氛围 */
|
||||
core_atmosphere: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 场景草图项
|
||||
*/
|
||||
export interface SketchItem {
|
||||
/** 草图名称 */
|
||||
sketch_name: string;
|
||||
/** 图片ID */
|
||||
image_id: string;
|
||||
/** 提示词 */
|
||||
prompt: string;
|
||||
/** 提示词JSON */
|
||||
prompt_json: PromptJson;
|
||||
/** 草图名称前缀 */
|
||||
sketch_name_prefix: string;
|
||||
/** 图片URL列表 */
|
||||
urls: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 镜头草图项
|
||||
*/
|
||||
export interface ShotSketchItem {
|
||||
/** 镜头草图名称 */
|
||||
shot_sketch_name: string;
|
||||
/** 图片ID */
|
||||
image_id: string;
|
||||
/** 提示词 */
|
||||
prompt: string;
|
||||
/** 提示词JSON */
|
||||
prompt_json: PromptJson;
|
||||
/** 镜头草图名称前缀 */
|
||||
shot_sketch_name_prefix: string;
|
||||
/** 图片URL列表 */
|
||||
urls: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 视频项
|
||||
*/
|
||||
export interface VideoItem {
|
||||
/** 视频ID */
|
||||
video_id: string;
|
||||
/** 描述 */
|
||||
description: string;
|
||||
/** 提示词JSON */
|
||||
prompt_json: PromptJson;
|
||||
/** 视频名称前缀 */
|
||||
video_name_prefix: string;
|
||||
/** 视频URL列表 */
|
||||
urls: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 主要角色
|
||||
*/
|
||||
export interface MasterCharacter {
|
||||
/** 角色ID */
|
||||
id: string;
|
||||
/** 角色名称 */
|
||||
name: string;
|
||||
/** 角色描述 */
|
||||
description: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 主要服装
|
||||
*/
|
||||
export interface MasterWardrobe {
|
||||
/** 所属角色 */
|
||||
belongs_to: string;
|
||||
/** 服装描述 */
|
||||
description: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 主要场景
|
||||
*/
|
||||
export interface MasterScene {
|
||||
/** 场景名称 */
|
||||
name: string;
|
||||
/** 场景描述 */
|
||||
description: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 视频数据
|
||||
*/
|
||||
export interface VideoData {
|
||||
/** 视频列表 */
|
||||
data: VideoItem[];
|
||||
/** 总数 */
|
||||
total_count: number;
|
||||
/** 全局ID */
|
||||
guid: string;
|
||||
/** 项目ID */
|
||||
project_id: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 音乐数据
|
||||
*/
|
||||
export interface MusicData {
|
||||
[key: string]: any;
|
||||
}
|
||||
/**
|
||||
* 视频信息接口
|
||||
*/
|
||||
export interface Video {
|
||||
/** 视频唯一标识符 */
|
||||
video_id: string;
|
||||
/** 视频描述 */
|
||||
description: string;
|
||||
/** 提示JSON数据 */
|
||||
prompt_json: PromptJson;
|
||||
/** 视频名称前缀 */
|
||||
video_name_prefix: string;
|
||||
/** 视频URL列表 */
|
||||
urls: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 音乐信息接口
|
||||
*/
|
||||
export interface Music {
|
||||
/** 音乐相关数据,当前为空对象 */
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* 最终视频信息接口
|
||||
*/
|
||||
export interface FinalVideo {
|
||||
/** 最终视频URL */
|
||||
video: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 多语言视频信息接口
|
||||
*/
|
||||
export interface MultilingualVideo {
|
||||
/** 多语言视频相关数据,当前为空对象 */
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* 项目设置接口
|
||||
*/
|
||||
export interface ProjectSettings {
|
||||
/** 视频质量设置 */
|
||||
quality: string;
|
||||
/** 帧率设置 */
|
||||
frame_rate: string;
|
||||
/** 分辨率设置 */
|
||||
resolution: string;
|
||||
/** 音频设置 */
|
||||
audio: {
|
||||
/** 音频质量 */
|
||||
quality: string;
|
||||
/** 音频格式 */
|
||||
format: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 项目统计信息接口
|
||||
*/
|
||||
export interface ProjectStatistics {
|
||||
/** 总视频数 */
|
||||
total_videos: number;
|
||||
/** 总角色数 */
|
||||
total_characters: number;
|
||||
/** 总场景数 */
|
||||
total_scenes: number;
|
||||
/** 总服装数 */
|
||||
total_wardrobes: number;
|
||||
/** 总音乐数 */
|
||||
total_music: number;
|
||||
/** 总时长 */
|
||||
total_duration: number;
|
||||
/** 总大小 */
|
||||
total_size: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 项目元数据接口
|
||||
*/
|
||||
export interface ProjectMetadata {
|
||||
/** 项目版本 */
|
||||
version: string;
|
||||
/** 项目语言 */
|
||||
language: string;
|
||||
/** 项目分类 */
|
||||
category: string;
|
||||
/** 项目难度 */
|
||||
difficulty: string;
|
||||
/** 项目时长 */
|
||||
duration: string;
|
||||
/** 项目预算 */
|
||||
budget: string;
|
||||
/** 项目团队 */
|
||||
team: string[];
|
||||
/** 项目设备 */
|
||||
equipment: string[];
|
||||
/** 项目软件 */
|
||||
software: string[];
|
||||
/** 项目许可证 */
|
||||
license: string;
|
||||
/** 项目版权 */
|
||||
copyright: string;
|
||||
/** 项目评分 */
|
||||
rating: number;
|
||||
/** 项目评论数 */
|
||||
review_count: number;
|
||||
/** 项目下载数 */
|
||||
download_count: number;
|
||||
/** 项目分享数 */
|
||||
share_count: number;
|
||||
/** 项目收藏数 */
|
||||
favorite_count: number;
|
||||
/** 项目观看数 */
|
||||
view_count: number;
|
||||
/** 项目完成度 */
|
||||
completion_rate: number;
|
||||
/** 项目进度 */
|
||||
progress: number;
|
||||
/** 项目阶段 */
|
||||
stage: string;
|
||||
/** 项目里程碑 */
|
||||
milestones: string[];
|
||||
/** 项目任务 */
|
||||
tasks: string[];
|
||||
/** 项目文件 */
|
||||
files: string[];
|
||||
/** 项目链接 */
|
||||
links: string[];
|
||||
/** 项目备注 */
|
||||
notes: string;
|
||||
/** 项目历史 */
|
||||
history: string[];
|
||||
/** 项目日志 */
|
||||
logs: string[];
|
||||
/** 项目统计 */
|
||||
statistics: ProjectStatistics;
|
||||
}
|
||||
|
||||
/**
|
||||
* 项目内容接口
|
||||
*/
|
||||
export interface ProjectContent {
|
||||
/** 草图数据 */
|
||||
sketch: SketchItem[];
|
||||
/** 角色数据 */
|
||||
character: Character[];
|
||||
/** 镜头草图数据 */
|
||||
shot_sketch: ShotSketchItem[];
|
||||
/** 视频数据 */
|
||||
video: VideoData;
|
||||
/** 音乐数据 */
|
||||
music: MusicData;
|
||||
/** 最终视频 */
|
||||
final_video: FinalVideo;
|
||||
/** 多语言视频 */
|
||||
multilingual_video: MultilingualVideo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 视频流程项目接口
|
||||
*/
|
||||
export interface VideoFlowProject {
|
||||
/** 项目名称 */
|
||||
name: string;
|
||||
/** 项目描述 */
|
||||
description: string;
|
||||
/** 项目类型 */
|
||||
type: string;
|
||||
/** 项目状态 */
|
||||
status: string;
|
||||
/** 项目创建时间 */
|
||||
created_at: string;
|
||||
/** 项目更新时间 */
|
||||
updated_at: string;
|
||||
/** 项目所有者ID */
|
||||
owner_id: string;
|
||||
/** 项目标签列表 */
|
||||
tags: string[];
|
||||
/** 项目设置 */
|
||||
settings: ProjectSettings;
|
||||
/** 项目元数据 */
|
||||
metadata: ProjectMetadata;
|
||||
/** 项目内容 */
|
||||
content: ProjectContent;
|
||||
/** 音乐信息 */
|
||||
music: Music;
|
||||
/** 最终视频 */
|
||||
final_video: FinalVideo;
|
||||
/** 多语言视频 */
|
||||
multilingual_video: MultilingualVideo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 视频流程项目 - 完整的接口返回值类型
|
||||
*/
|
||||
export interface VideoFlowProjectResponse {
|
||||
/** 项目名称 */
|
||||
name: string;
|
||||
/** 项目ID */
|
||||
project_id: string;
|
||||
/** 项目模式 */
|
||||
mode: ProjectMode;
|
||||
/** 分辨率 */
|
||||
resolution: Resolution;
|
||||
/** 语言 */
|
||||
language: Language;
|
||||
/** 原始文本 */
|
||||
original_text: string;
|
||||
/** 生成的脚本 */
|
||||
generated_script: string;
|
||||
/** 项目状态 */
|
||||
status: ProjectStatus;
|
||||
/** 项目标题 */
|
||||
title: string;
|
||||
/** 项目类型 */
|
||||
genre: string;
|
||||
/** 项目标签 */
|
||||
tags: string[];
|
||||
/** 项目步骤 */
|
||||
step: ProjectStep;
|
||||
/** 最后消息 */
|
||||
last_message: string;
|
||||
/** 项目内容 */
|
||||
data: ProjectContent;
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,8 @@ import {
|
||||
LensType,
|
||||
ScriptSlice,
|
||||
} from "@/app/service/domain/valueObject";
|
||||
import { VideoSegmentEntityAdapter } from "@/app/service/adapter/oldErrAdapter";
|
||||
import { task_item, VideoSegmentEntityAdapter } from "@/app/service/adapter/oldErrAdapter";
|
||||
import { VideoFlowProjectResponse } from "./allMovieType";
|
||||
|
||||
// API 响应类型
|
||||
interface BaseApiResponse<T> {
|
||||
@ -199,8 +200,8 @@ export const convertVideoToScene = async (
|
||||
// 新-获取剧集详情
|
||||
export const detailScriptEpisodeNew = async (data: {
|
||||
project_id: string;
|
||||
}): Promise<ApiResponse<any>> => {
|
||||
return post<ApiResponse<any>>("/movie/get_movie_project_detail", data);
|
||||
}): Promise<ApiResponse<VideoFlowProjectResponse>> => {
|
||||
return post("/movie/get_movie_project_detail", data);
|
||||
};
|
||||
|
||||
// 获取 title 接口
|
||||
@ -511,11 +512,11 @@ export const regenerateShot = async (request: {
|
||||
/** 分镜ID */
|
||||
shot_id?: string;
|
||||
/** 镜头描述 */
|
||||
shot_descriptions?: LensType[];
|
||||
/** 角色ID替换参数,格式为{oldId:string,newId:string}[] */
|
||||
roleReplaceParams?: { oldId: string; newId: string }[];
|
||||
/** 场景ID替换参数,格式为{oldId:string,newId:string}[] */
|
||||
sceneReplaceParams?: { oldId: string; newId: string }[];
|
||||
shot_descriptions?: task_item;
|
||||
// /** 角色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_video", request);
|
||||
};
|
||||
@ -810,7 +811,7 @@ export const updateShotPrompt = async (request: {
|
||||
/** 分镜ID */
|
||||
shot_id: string;
|
||||
/** 镜头描述 */
|
||||
shot_descriptions: LensType[];
|
||||
shot_descriptions: task_item;
|
||||
}): Promise<ApiResponse<any>> => {
|
||||
return post("/movie/update_shot_prompt", request);
|
||||
};
|
||||
|
||||
@ -22,8 +22,8 @@ export interface UseShotService {
|
||||
getVideoSegmentList: (projectId: string) => Promise<void>;
|
||||
/** 重新生成视频片段 */
|
||||
regenerateVideoSegment: (
|
||||
roleReplaceParams?: { oldId: string; newId: string }[],
|
||||
sceneReplaceParams?: { oldId: string; newId: string }[]
|
||||
// roleReplaceParams?: { oldId: string; newId: string }[],
|
||||
// sceneReplaceParams?: { oldId: string; newId: string }[]
|
||||
) => Promise<VideoSegmentEntity>;
|
||||
/** AI优化视频内容 */
|
||||
optimizeVideoContent: (
|
||||
@ -95,8 +95,8 @@ export const useShotService = (): UseShotService => {
|
||||
*/
|
||||
const regenerateVideoSegment = useCallback(
|
||||
async (
|
||||
roleReplaceParams?: { oldId: string; newId: string }[],
|
||||
sceneReplaceParams?: { oldId: string; newId: string }[]
|
||||
// roleReplaceParams?: { oldId: string; newId: string }[],
|
||||
// sceneReplaceParams?: { oldId: string; newId: string }[]
|
||||
): Promise<VideoSegmentEntity> => {
|
||||
try {
|
||||
setLoading(true);
|
||||
@ -105,8 +105,8 @@ export const useShotService = (): UseShotService => {
|
||||
projectId,
|
||||
selectedSegment!.lens,
|
||||
selectedSegment!.id,
|
||||
roleReplaceParams,
|
||||
sceneReplaceParams
|
||||
// roleReplaceParams,
|
||||
// sceneReplaceParams
|
||||
);
|
||||
|
||||
// 如果重新生成的是现有片段,更新列表中的对应项
|
||||
|
||||
@ -4,6 +4,29 @@
|
||||
import { VideoSegmentEntity } from "../domain/Entities";
|
||||
import { LensType, ContentItem } from "../domain/valueObject";
|
||||
|
||||
|
||||
export type task_item = {
|
||||
/** 镜头1描述 */
|
||||
shot_1: string;
|
||||
/** 镜头2描述 */
|
||||
shot_2: string;
|
||||
/** 镜头3描述 */
|
||||
shot_3: string;
|
||||
/** 镜头4描述 */
|
||||
shot_4: string;
|
||||
/** 镜头5描述 */
|
||||
shot_5: string;
|
||||
/** 镜头6描述 */
|
||||
shot_6: string;
|
||||
/** 镜头7描述 */
|
||||
shot_7: string;
|
||||
/** 镜头8描述 */
|
||||
shot_8: string;
|
||||
/** 镜头9描述 */
|
||||
shot_9: string;
|
||||
/** 镜头10描述 */
|
||||
shot_10: string;
|
||||
}
|
||||
/**
|
||||
* @description 视频片段后端结构
|
||||
*/
|
||||
@ -241,6 +264,63 @@ export class VideoSegmentEntityAdapter {
|
||||
|
||||
return adapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 将LensType数组转换为task_item类型
|
||||
* @param lensTypes 镜头类型数组
|
||||
* @returns task_item 任务项
|
||||
*/
|
||||
static lensTypeToTaskItem(lensTypes: LensType[]): task_item {
|
||||
// 初始化镜头对象,所有字段设为空字符串
|
||||
const shots: { [key: string]: string } = {
|
||||
shot_1: "",
|
||||
shot_2: "",
|
||||
shot_3: "",
|
||||
shot_4: "",
|
||||
shot_5: "",
|
||||
shot_6: "",
|
||||
shot_7: "",
|
||||
shot_8: "",
|
||||
shot_9: "",
|
||||
shot_10: ""
|
||||
};
|
||||
|
||||
// 遍历所有LensType,处理镜头1到镜头10
|
||||
lensTypes.forEach(lensType => {
|
||||
const shotMatch = lensType.name.match(/^shot_(\d+)$/);
|
||||
if (shotMatch) {
|
||||
const shotNumber = shotMatch[1];
|
||||
const shotKey = `shot_${shotNumber}` as keyof typeof shots;
|
||||
|
||||
// 重新组合镜头描述和对话内容
|
||||
let fullContent = lensType.script;
|
||||
|
||||
// 如果有对话内容,添加到镜头描述后面
|
||||
if (lensType.content && lensType.content.length > 0) {
|
||||
const dialogueLines = lensType.content.map(dialogue =>
|
||||
`${dialogue.roleName} [CH-01]: ${dialogue.content}`
|
||||
);
|
||||
fullContent += '\n' + dialogueLines.join('\n');
|
||||
}
|
||||
|
||||
shots[shotKey] = fullContent;
|
||||
}
|
||||
});
|
||||
|
||||
// 返回完整的task_item对象
|
||||
return {
|
||||
shot_1: shots.shot_1,
|
||||
shot_2: shots.shot_2,
|
||||
shot_3: shots.shot_3,
|
||||
shot_4: shots.shot_4,
|
||||
shot_5: shots.shot_5,
|
||||
shot_6: shots.shot_6,
|
||||
shot_7: shots.shot_7,
|
||||
shot_8: shots.shot_8,
|
||||
shot_9: shots.shot_9,
|
||||
shot_10: shots.shot_10
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**视频片段基础数据 */
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { VideoSegmentEntityAdapter } from "../adapter/oldErrAdapter";
|
||||
import { VideoFlowProjectResponse } from "@/api/allMovieType";
|
||||
import { task_item, VideoSegmentEntityAdapter } from "../adapter/oldErrAdapter";
|
||||
import { VideoSegmentEntity } from "../domain/Entities";
|
||||
import { LensType } from "../domain/valueObject";
|
||||
import {
|
||||
@ -6,6 +7,7 @@ import {
|
||||
regenerateShot,
|
||||
optimizeShotContent,
|
||||
updateShotPrompt,
|
||||
detailScriptEpisodeNew,
|
||||
} from "@/api/video_flow";
|
||||
|
||||
/**
|
||||
@ -30,7 +32,13 @@ export class VideoSegmentEditUseCase {
|
||||
throw new Error(response.message || "获取视频片段列表失败");
|
||||
}
|
||||
|
||||
return VideoSegmentEntityAdapter.toVideoSegmentEntity(response.data) || [];
|
||||
const Segments = VideoSegmentEntityAdapter.toVideoSegmentEntity(response.data) || [];
|
||||
const detail = await detailScriptEpisodeNew({ project_id: projectId });
|
||||
if (!detail.successful || !detail.data) {
|
||||
throw new Error(detail.message || "获取视频片段列表失败");
|
||||
}
|
||||
// 匹配视频片段ID
|
||||
return this.matchVideoSegmentsWithIds(Segments, detail.data);
|
||||
} catch (error) {
|
||||
console.error("获取视频片段列表失败:", error);
|
||||
throw error;
|
||||
@ -39,6 +47,74 @@ export class VideoSegmentEditUseCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 为视频片段匹配对应的video_id
|
||||
* @param segments 视频片段列表
|
||||
* @param detail 项目详情数据
|
||||
* @returns VideoSegmentEntity[] 匹配后的视频片段列表
|
||||
* @throws Error 当有视频片段未匹配到video_id时
|
||||
*/
|
||||
private matchVideoSegmentsWithIds(
|
||||
segments: VideoSegmentEntity[],
|
||||
detail: VideoFlowProjectResponse
|
||||
): VideoSegmentEntity[] {
|
||||
|
||||
|
||||
const projectData = detail.data as any;
|
||||
const videoData = projectData?.data?.video?.data;
|
||||
|
||||
if (!videoData || !Array.isArray(videoData)) {
|
||||
return segments;
|
||||
}
|
||||
|
||||
// 建立URL到VideoItem的映射表,提高查找效率
|
||||
const urlToVideoMap = new Map<string, any>();
|
||||
videoData.forEach(videoItem => {
|
||||
if (videoItem.urls && Array.isArray(videoItem.urls)) {
|
||||
videoItem.urls.forEach((url: string) => {
|
||||
urlToVideoMap.set(url, videoItem);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 为每个视频片段匹配video_id并重新创建实体
|
||||
const updatedSegments: VideoSegmentEntity[] = [];
|
||||
|
||||
segments.forEach(segment => {
|
||||
if (segment.videoUrl && Array.isArray(segment.videoUrl)) {
|
||||
// 查找匹配的视频项
|
||||
const matchedVideo = segment.videoUrl.find(url => urlToVideoMap.has(url));
|
||||
const videoItem = matchedVideo ? urlToVideoMap.get(matchedVideo) : null;
|
||||
|
||||
if (videoItem) {
|
||||
// 创建新的实体实例,设置正确的id
|
||||
const updatedSegment: VideoSegmentEntity = {
|
||||
...segment,
|
||||
id: videoItem.video_id
|
||||
};
|
||||
updatedSegments.push(updatedSegment);
|
||||
} else {
|
||||
// 如果没有匹配到,保持原样
|
||||
updatedSegments.push(segment);
|
||||
}
|
||||
} else {
|
||||
updatedSegments.push(segment);
|
||||
}
|
||||
});
|
||||
|
||||
// 检查是否所有视频片段都匹配上了id
|
||||
const unmatchedSegments = updatedSegments.filter(segment =>
|
||||
segment.id.startsWith('video_mock_') || !segment.id
|
||||
);
|
||||
|
||||
if (unmatchedSegments.length > 0) {
|
||||
console.warn('以下视频片段未匹配到video_id:', unmatchedSegments.map(s => ({ name: s.name, videoUrl: s.videoUrl })));
|
||||
throw new Error(`有 ${unmatchedSegments.length} 个视频片段未匹配到对应的video_id`);
|
||||
}
|
||||
|
||||
return updatedSegments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 保存分镜提示词数据
|
||||
* @param project_id 项目ID
|
||||
@ -49,7 +125,7 @@ export class VideoSegmentEditUseCase {
|
||||
async saveShotPrompt(
|
||||
project_id: string,
|
||||
shot_id: string,
|
||||
shot_descriptions: LensType[]
|
||||
shot_descriptions: task_item
|
||||
): Promise<any> {
|
||||
try {
|
||||
this.loading = true;
|
||||
@ -76,22 +152,20 @@ export class VideoSegmentEditUseCase {
|
||||
/**
|
||||
* @description 通过视频镜头描述数据重新生成视频
|
||||
* @param project_id 项目ID
|
||||
* @param shot_descriptions 镜头描述数据
|
||||
* @param shot_Lens 镜头描述数据
|
||||
* @param shot_id 视频片段ID(可选,如果重新生成现有片段)
|
||||
* @param roleReplaceParams 角色替换参数(可选)
|
||||
* @param sceneReplaceParams 场景替换参数(可选)
|
||||
* @returns Promise<VideoSegmentEntity> 重新生成的视频片段
|
||||
*/
|
||||
async regenerateVideoSegment(
|
||||
project_id: string,
|
||||
shot_descriptions: LensType[],
|
||||
shot_Lens: LensType[],
|
||||
shot_id?: string,
|
||||
roleReplaceParams?: { oldId: string; newId: string }[],
|
||||
sceneReplaceParams?: { oldId: string; newId: string }[]
|
||||
// roleReplaceParams?: { oldId: string; newId: string }[],
|
||||
// sceneReplaceParams?: { oldId: string; newId: string }[]
|
||||
): Promise<VideoSegmentEntity> {
|
||||
try {
|
||||
this.loading = true;
|
||||
|
||||
const shot_descriptions = VideoSegmentEntityAdapter.lensTypeToTaskItem(shot_Lens);
|
||||
// 如果有shot_id,先保存分镜数据
|
||||
if (shot_id) {
|
||||
await this.saveShotPrompt(project_id, shot_id, shot_descriptions);
|
||||
@ -101,8 +175,8 @@ export class VideoSegmentEditUseCase {
|
||||
project_id,
|
||||
shot_id,
|
||||
shot_descriptions,
|
||||
roleReplaceParams,
|
||||
sceneReplaceParams,
|
||||
// roleReplaceParams,
|
||||
// sceneReplaceParams,
|
||||
});
|
||||
|
||||
if (!response.successful) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user