/**============因协同任务开发流程没有明确管理,导致的必要的适配=================**/ import { VideoSegmentEntity } from "../domain/Entities"; import { LensType, ContentItem } from "../domain/valueObject"; /** * @description 视频片段后端结构 */ export class VideoSegmentEntityAdapter { /** 原始文本 */ original_text: string = ""; /** 任务状态 */ task_status: string = ""; /** 任务结果 */ task_result: Array<{ /** 叙事目标 */ narrative_goal: string; /** 镜头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; /** 视频列表 */ videos: Array<{ /** 视频地址 */ video_url: string; }>; }> = []; /** * @description 解析shotContent,分离镜头描述和对话内容 * @param shotContent 原始shot内容 * @returns {description: string, dialogues: ContentItem[]} 解析后的描述和对话内容 */ static parseShotContent(shotContent: string): { description: string; dialogues: ContentItem[] } { const lines = shotContent.split('\n').map(line => line.trim()).filter(line => line.length > 0); const dialogues: ContentItem[] = []; let descriptionLines: string[] = []; for (const line of lines) { // 检查是否是对话行,格式:人物名称[CH-XX]: 对话内容 const dialogueMatch = line.match(/^(.+?)\s*\[CH-\d+\]:\s*(.+)$/); if (dialogueMatch) { const roleName = dialogueMatch[1].trim(); const content = dialogueMatch[2].trim(); dialogues.push({ roleName, content }); } else { // 如果不是对话行,则认为是描述内容 descriptionLines.push(line); } } const description = descriptionLines.join('\n'); return { description, dialogues }; } /** * @description 将后端数据结构转换为VideoSegmentEntity数组 * @param data 后端数据结构 * @returns VideoSegmentEntity[] 视频片段实体数组 */ static toVideoSegmentEntity(data: VideoSegmentEntityAdapter): VideoSegmentEntity[] { const entities: VideoSegmentEntity[] = []; if (data.task_result && data.task_result.length > 0) { // 遍历task_result中的每一项 data.task_result.forEach((result, index) => { // 从task_result中提取镜头信息 const lens: LensType[] = []; // 处理镜头1到镜头10 for (let i = 1; i <= 10; i++) { const shotKey = `shot_${i}` as keyof typeof result; const shotContent = (result as any)[shotKey] as string; if (shotContent && shotContent.trim()) { // 解析shotContent,分离镜头描述和对话内容 const { description, dialogues } = this.parseShotContent(shotContent); // 创建镜头项,包含描述和对话内容 const lensItem = new LensType(`shot_${i}`, description, dialogues); lens.push(lensItem); } } // 如果没有任何镜头但有narrative_goal,将其作为镜头1 if (lens.length === 0 && result.narrative_goal) { const narrativeLens = new LensType("镜头1", result.narrative_goal, []); lens.push(narrativeLens); } // 提取视频URL列表 const videoUrls: string[] = []; if (result.videos && result.videos.length > 0) { videoUrls.push(...result.videos.map(video => video.video_url)); } // 根据task_status确定状态 let status: 0 | 1 | 2 = 1; // 默认为已完成状态 if (data.task_status === "INIT" || data.task_status === "IN_PROGRESS") { status = 0; // 视频加载中(INIT和IN_PROGRESS都当成进行中) } else if (data.task_status === "COMPLETED") { status = 1; // 任务已完成 } else if (data.task_status === "FAILED") { status = 2; // 任务失败 } // 创建VideoSegmentEntity const entity: VideoSegmentEntity = { id: `video_mock_${index}`, // 生成临时ID,包含索引 updatedAt: Date.now(), loadingProgress: status === 1 ? 100 : status === 0 ? 50 : 0, // 已完成100%,进行中50%,失败0% disableEdit: false, name: `视频片段_${index}`, // 生成临时名称,包含索引 sketchUrl: "", // 后端数据中没有sketchUrl,设为空字符串 videoUrl: videoUrls, status: status, lens: lens }; entities.push(entity); }); } return entities; } /** * @description 将VideoSegmentEntity数组转换为后端数据结构 * @param entities 视频片段实体数组 * @returns VideoSegmentEntityAdapter 后端数据结构 */ static fromVideoSegmentEntity(entities: VideoSegmentEntity[]): VideoSegmentEntityAdapter { const taskResults: Array<{ narrative_goal: string; shot_1: string; shot_2: string; shot_3: string; shot_4: string; shot_5: string; shot_6: string; shot_7: string; shot_8: string; shot_9: string; shot_10: string; videos: Array<{ video_url: string }>; }> = []; // 遍历每个实体,转换为task_result项 entities.forEach(entity => { // 从lens中提取镜头描述(支持镜头1到镜头10) const shots: { [key: string]: string } = {}; for (let i = 1; i <= 10; i++) { const lensItem = entity.lens.find(lens => lens.name === `shot_${i}`); if (lensItem) { // 重新组合镜头描述和对话内容 let fullContent = lensItem.script; // 如果有对话内容,添加到镜头描述后面 if (lensItem.content && lensItem.content.length > 0) { const dialogueLines = lensItem.content.map(dialogue => `${dialogue.roleName} [CH-01]: ${dialogue.content}` ); fullContent += '\n' + dialogueLines.join('\n'); } shots[`shot_${i}`] = fullContent; } else { shots[`shot_${i}`] = ""; } } // 如果有更多镜头,可以合并到narrative_goal中 let narrative_goal = ""; const additionalLenses = entity.lens .filter(lens => !lens.name.match(/^shot_[1-9]$|^shot_10$/)) .map(lens => `${lens.name}: ${lens.script}`) .join("; "); if (additionalLenses) { narrative_goal = additionalLenses; } // 构建videos数组 const videos = entity.videoUrl.map(url => ({ video_url: url })); taskResults.push({ narrative_goal: narrative_goal, 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 || "", videos: videos }); }); // 根据第一个实体的status确定task_status(如果数组为空,默认为COMPLETED) let task_status: string = "COMPLETED"; if (entities.length > 0) { const firstEntity = entities[0]; if (firstEntity.status === 0) { task_status = "IN_PROGRESS"; // 视频加载中映射为IN_PROGRESS } else if (firstEntity.status === 1) { task_status = "COMPLETED"; // 任务已完成 } else if (firstEntity.status === 2) { task_status = "FAILED"; // 任务失败 } } // 创建VideoSegmentEntityAdapter const adapter = new VideoSegmentEntityAdapter(); adapter.original_text = ""; // 实体中没有original_text,设为空字符串 adapter.task_status = task_status; adapter.task_result = taskResults; return adapter; } } /**视频片段基础数据 */ export interface TaskSketch { url: string; video_id: string; }