forked from 77media/video-flow
722 lines
27 KiB
TypeScript
722 lines
27 KiB
TypeScript
'use client';
|
|
|
|
import { useState, useEffect, useCallback } from 'react';
|
|
import { useSearchParams } from 'next/navigation';
|
|
import { detailScriptEpisodeNew, getScriptTitle, getRunningStreamData, pauseMovieProjectPlan, resumeMovieProjectPlan } from '@/api/video_flow';
|
|
import { useAppDispatch, useAppSelector } from '@/lib/store/hooks';
|
|
import { setSketchCount, setVideoCount } from '@/lib/store/workflowSlice';
|
|
import { useScriptService } from "@/app/service/Interaction/ScriptService";
|
|
import { useUpdateEffect } from '@/app/hooks/useUpdateEffect';
|
|
|
|
// 步骤映射
|
|
const STEP_MAP = {
|
|
'initializing': '0',
|
|
'sketch': '1',
|
|
'character': '2',
|
|
'video': '3',
|
|
'music': '4',
|
|
'final_video': '6'
|
|
} as const;
|
|
// 执行loading文字映射
|
|
const LOADING_TEXT_MAP = {
|
|
initializing: 'initializing...',
|
|
script: 'Generating script...',
|
|
getSketchStatus: 'Getting sketch status...',
|
|
sketch: (count: number, total: number) => `Generating sketch ${count + 1 > total ? total : count + 1}/${total}...`,
|
|
sketchComplete: 'Sketch generation complete',
|
|
character: 'Drawing characters...',
|
|
newCharacter: (count: number, total: number) => `Drawing character ${count + 1 > total ? total : count + 1}/${total}...`,
|
|
getShotSketchStatus: 'Getting shot sketch status...',
|
|
shotSketch: (count: number, total: number) => `Generating shot sketch ${count + 1 > total ? total : count + 1}/${total}...`,
|
|
getVideoStatus: 'Getting video status...',
|
|
video: (count: number, total: number) => `Generating video ${count + 1 > total ? total : count + 1}/${total}...`,
|
|
videoComplete: 'Video generation complete',
|
|
audio: 'Generating background audio...',
|
|
postProduction: (step: string) => `Post-production: ${step}...`,
|
|
final: 'Generating final product...',
|
|
complete: 'Task completed'
|
|
} as const;
|
|
|
|
type ApiStep = keyof typeof STEP_MAP;
|
|
|
|
// 添加 TaskObject 接口
|
|
interface TaskObject {
|
|
taskStatus: string;
|
|
title: string;
|
|
currentLoadingText: string;
|
|
sketchCount?: number;
|
|
totalSketchCount?: number;
|
|
isGeneratingSketch?: boolean;
|
|
isGeneratingVideo?: boolean;
|
|
roles?: any[];
|
|
music?: any[];
|
|
final?: any;
|
|
tags?: any[];
|
|
}
|
|
|
|
export function useWorkflowData() {
|
|
console.log('98877766777777888888990')
|
|
|
|
const searchParams = useSearchParams();
|
|
const episodeId = searchParams.get('episodeId') || '';
|
|
|
|
// 更新 taskObject 的类型
|
|
const [taskObject, setTaskObject] = useState<TaskObject | null>(null);
|
|
const [originalText, setOriginalText] = useState<string>('');
|
|
const [scriptData, setScriptData] = useState<any>(null);
|
|
const [taskSketch, setTaskSketch] = useState<any[]>([]);
|
|
const [taskScenes, setTaskScenes] = useState<any[]>([]);
|
|
const [taskShotSketch, setTaskShotSketch] = useState<any[]>([]);
|
|
const [taskVideos, setTaskVideos] = useState<any[]>([]);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
const [currentStep, setCurrentStep] = useState('0');
|
|
const [currentSketchIndex, setCurrentSketchIndex] = useState(0);
|
|
const [isGeneratingSketch, setIsGeneratingSketch] = useState(false);
|
|
const [isGeneratingVideo, setIsGeneratingVideo] = useState(false);
|
|
const [currentLoadingText, setCurrentLoadingText] = useState('loading project info...');
|
|
const [totalSketchCount, setTotalSketchCount] = useState(0);
|
|
const [roles, setRoles] = useState<any[]>([]);
|
|
const [music, setMusic] = useState<any[]>([]);
|
|
const [final, setFinal] = useState<any>(null);
|
|
const [dataLoadError, setDataLoadError] = useState<string | null>(null);
|
|
const [needStreamData, setNeedStreamData] = useState(false);
|
|
const [isPauseWorkFlow, setIsPauseWorkFlow] = useState(false);
|
|
const [mode, setMode] = useState<'automatic' | 'manual' | 'auto'>('automatic');
|
|
|
|
let taskData: any = {
|
|
sketch: { data: [], total_count: -1 },
|
|
character: { data: [], total_count: -1 },
|
|
shot_sketch: { data: [], total_count: -1 },
|
|
video: { data: [], total_count: -1 },
|
|
status: '0'
|
|
};
|
|
let loadingText: any = LOADING_TEXT_MAP.initializing;
|
|
|
|
const dispatch = useAppDispatch();
|
|
const { sketchCount, videoCount } = useAppSelector((state) => state.workflow);
|
|
|
|
const {
|
|
scriptBlocksMemo, // 渲染剧本数据
|
|
initializeFromProject,
|
|
setAnyAttribute,
|
|
applyScript
|
|
} = useScriptService();
|
|
// 初始化剧本
|
|
useUpdateEffect(() => {
|
|
console.log('开始初始化剧本', originalText,episodeId);
|
|
// TODO 为什么一开始没项目id
|
|
originalText && initializeFromProject(episodeId, originalText).then(() => {
|
|
console.log('应用剧本');
|
|
// 自动模式下 应用剧本;手动模式 需要点击 下一步 触发
|
|
mode.includes('auto') && applyScript();
|
|
});
|
|
}, [originalText], {mode: 'none'});
|
|
// 监听剧本加载完毕
|
|
useEffect(() => {
|
|
if (scriptBlocksMemo.length > 0) {
|
|
console.log('scriptBlocksMemo 更新:', scriptBlocksMemo);
|
|
setScriptData(scriptBlocksMemo);
|
|
setCurrentLoadingText(LOADING_TEXT_MAP.script);
|
|
}
|
|
}, [scriptBlocksMemo]);
|
|
// 监听继续 请求更新数据
|
|
useUpdateEffect(() => {
|
|
if (currentStep === '6') {
|
|
return;
|
|
}
|
|
if (isPauseWorkFlow) {
|
|
pauseMovieProjectPlan({ project_id: episodeId });
|
|
} else {
|
|
resumeMovieProjectPlan({ project_id: episodeId });
|
|
}
|
|
}, [isPauseWorkFlow], { mode: "debounce", delay: 1000 });
|
|
|
|
// 自动开始播放一轮
|
|
const autoPlaySketch = useCallback(() => {
|
|
return new Promise<void>((resolve) => {
|
|
let currentIndex = 0;
|
|
const interval = 2000; // 每个草图显示2秒
|
|
|
|
const playNext = () => {
|
|
if (currentIndex < taskSketch.length) {
|
|
setCurrentSketchIndex(currentIndex);
|
|
currentIndex++;
|
|
setTimeout(playNext, interval);
|
|
} else {
|
|
// 播放完成后重置到第一个
|
|
setTimeout(() => {
|
|
setCurrentSketchIndex(0);
|
|
resolve();
|
|
}, 500); // 短暂延迟后重置
|
|
}
|
|
};
|
|
|
|
// 开始播放
|
|
playNext();
|
|
});
|
|
}, [taskSketch.length]);
|
|
|
|
// 草图生成完毕后自动播放一轮
|
|
useEffect(() => {
|
|
const handleAutoPlay = async () => {
|
|
if (!isGeneratingSketch && taskSketch.length > 0 && sketchCount === totalSketchCount && currentStep === '3' && !taskVideos.length) {
|
|
await autoPlaySketch();
|
|
}
|
|
};
|
|
|
|
handleAutoPlay();
|
|
}, [sketchCount, totalSketchCount, isGeneratingSketch, autoPlaySketch]);
|
|
|
|
// 更新 setSketchCount
|
|
const updateSketchCount = useCallback((count: number) => {
|
|
dispatch(setSketchCount(count));
|
|
}, [dispatch]);
|
|
|
|
// 更新 setVideoCount
|
|
const updateVideoCount = useCallback((count: number) => {
|
|
dispatch(setVideoCount(count));
|
|
}, [dispatch]);
|
|
|
|
// 替换原有的 setSketchCount 和 setVideoCount 调用
|
|
useEffect(() => {
|
|
console.log('sketchCount 已更新:', sketchCount);
|
|
currentStep !== '3' && setCurrentSketchIndex(sketchCount - 1);
|
|
}, [sketchCount]);
|
|
|
|
useEffect(() => {
|
|
console.log('videoCount 已更新:', videoCount);
|
|
setCurrentSketchIndex(videoCount - 1);
|
|
}, [videoCount]);
|
|
|
|
// 将 sketchCount 和 videoCount 放到 redux 中 每一次变化也要更新
|
|
|
|
// 添加手动播放控制
|
|
const handleManualPlay = useCallback(async () => {
|
|
if (!isGeneratingSketch && taskSketch.length > 0) {
|
|
await autoPlaySketch();
|
|
}
|
|
}, [isGeneratingSketch, taskSketch.length, autoPlaySketch]);
|
|
|
|
// 获取流式数据
|
|
const fetchStreamData = useCallback(async () => {
|
|
if (!episodeId || !needStreamData) return;
|
|
|
|
try {
|
|
const response = await getRunningStreamData({ project_id: episodeId });
|
|
if (!response.successful) {
|
|
throw new Error(response.message);
|
|
}
|
|
|
|
let sketchCount = 0;
|
|
const all_task_data = response.data;
|
|
// all_task_data 下标0 和 下标1 换位置
|
|
const temp = all_task_data[0];
|
|
all_task_data[0] = all_task_data[1];
|
|
all_task_data[1] = temp;
|
|
|
|
console.log('---look-all_task_data', all_task_data);
|
|
console.log('---look-taskData', taskData);
|
|
|
|
// 收集所有需要更新的状态
|
|
let stateUpdates: {
|
|
taskSketch?: any[];
|
|
taskScenes?: any[];
|
|
taskShotSketch?: any[];
|
|
roles?: any[];
|
|
taskVideos?: any[];
|
|
isGeneratingSketch?: boolean;
|
|
isGeneratingVideo?: boolean;
|
|
currentStep?: string;
|
|
currentLoadingText?: string;
|
|
final?: any;
|
|
needStreamData?: boolean;
|
|
totalSketchCount?: number;
|
|
} = {};
|
|
|
|
for (const task of all_task_data) {
|
|
// 如果有已完成的数据,同步到状态
|
|
if (task.task_name === 'generate_sketch' && (task.task_status !== 'COMPLETED' || taskData.sketch.total_count !== taskData.sketch.data.length)) {
|
|
taskData.status = '1';
|
|
const realSketchResultData = task.task_result.data.filter((item: any) => item.image_path);
|
|
if (realSketchResultData.length >= 0) {
|
|
// 正在生成草图中 替换 sketch 数据
|
|
const sketchList = [];
|
|
for (const sketch of realSketchResultData) {
|
|
sketchList.push({
|
|
url: sketch.image_path,
|
|
script: sketch.sketch_name
|
|
});
|
|
}
|
|
taskData.sketch.data = sketchList;
|
|
stateUpdates.taskSketch = sketchList;
|
|
stateUpdates.taskScenes = sketchList;
|
|
stateUpdates.isGeneratingSketch = true;
|
|
stateUpdates.totalSketchCount = task.task_result.total_count;
|
|
loadingText = LOADING_TEXT_MAP.sketch(sketchList.length, task.task_result.total_count);
|
|
}
|
|
if (task.task_status === 'COMPLETED') {
|
|
// 草图生成完成
|
|
taskData.sketch.total_count = taskData.sketch.data.length;
|
|
stateUpdates.isGeneratingSketch = false;
|
|
sketchCount = task.task_result.total_count;
|
|
loadingText = LOADING_TEXT_MAP.sketchComplete;
|
|
taskData.status = '2';
|
|
}
|
|
stateUpdates.currentStep = taskData.status;
|
|
break;
|
|
}
|
|
|
|
if (task.task_name === 'generate_character' && (task.task_status !== 'COMPLETED' || taskData.character.total_count !== taskData.character.data.length)) {
|
|
if (task.task_result.data.length >= 0 && roles.length !== task.task_result.data.length) {
|
|
// 正在生成角色中 替换角色数据
|
|
const characterList = [];
|
|
for (const character of task.task_result.data) {
|
|
characterList.push({
|
|
name: character.character_name,
|
|
url: character.image_path,
|
|
sound: null,
|
|
soundDescription: '',
|
|
roleDescription: character.character_description
|
|
});
|
|
}
|
|
taskData.character.data = characterList;
|
|
stateUpdates.roles = characterList;
|
|
loadingText = LOADING_TEXT_MAP.newCharacter(characterList.length, task.task_result.total_count);
|
|
}
|
|
if (task.task_status === 'COMPLETED') {
|
|
console.log('----------角色生成完成,有几个分镜', sketchCount);
|
|
// 角色生成完成
|
|
taskData.character.total_count = taskData.character.data.length;
|
|
taskData.status = '3';
|
|
loadingText = LOADING_TEXT_MAP.getShotSketchStatus;
|
|
}
|
|
stateUpdates.currentStep = taskData.status;
|
|
break;
|
|
}
|
|
|
|
if (task.task_name === 'generate_shot_sketch' && (task.task_status !== 'COMPLETED' || taskData.shot_sketch.total_count !== taskData.shot_sketch.data.length)) {
|
|
const realShotResultData = task.task_result.data.filter((item: any) => item.url);
|
|
if (realShotResultData.length >= 0) {
|
|
taskData.status = '1';
|
|
console.log('----------正在生成草图中 替换 sketch 数据', taskShotSketch.length, realShotResultData.length);
|
|
// 正在生成草图中 替换 sketch 数据
|
|
const sketchList = [];
|
|
for (const sketch of realShotResultData) {
|
|
sketchList.push({
|
|
url: sketch.url,
|
|
script: sketch.description
|
|
});
|
|
}
|
|
taskData.shot_sketch.data = sketchList;
|
|
stateUpdates.taskSketch = sketchList;
|
|
stateUpdates.taskShotSketch = sketchList;
|
|
stateUpdates.isGeneratingSketch = true;
|
|
stateUpdates.totalSketchCount = task.task_result.total_count;
|
|
loadingText = LOADING_TEXT_MAP.shotSketch(sketchList.length, task.task_result.total_count);
|
|
}
|
|
if (task.task_status === 'COMPLETED') {
|
|
// 草图生成完成
|
|
taskData.shot_sketch.total_count = taskData.shot_sketch.data.length;
|
|
stateUpdates.isGeneratingSketch = false;
|
|
stateUpdates.isGeneratingVideo = true;
|
|
sketchCount = task.task_result.total_count;
|
|
console.log('----------草图生成完成', sketchCount);
|
|
loadingText = LOADING_TEXT_MAP.getVideoStatus;
|
|
taskData.status = '3';
|
|
}
|
|
stateUpdates.currentStep = taskData.status;
|
|
break;
|
|
}
|
|
|
|
if (task.task_name === 'generate_videos' && (task.task_status !== 'COMPLETED' || taskData.video.total_count !== taskData.video.data.length)) {
|
|
const realTaskResultData = task.task_result.data.filter((item: any) => item.urls && item.urls.length > 0);
|
|
if (realTaskResultData.length >= 0) {
|
|
console.log('----------正在生成视频中', realTaskResultData.length);
|
|
// 正在生成视频中 替换视频数据
|
|
const videoList = [];
|
|
for (const video of realTaskResultData) {
|
|
// 每一项 video 有多个视频 先默认取第一个
|
|
videoList.push({
|
|
url: video.urls && video.urls.length > 0 ? video.urls.find((url: string) => url) : null,
|
|
script: video.description,
|
|
audio: null,
|
|
video_id: video.video_id,
|
|
});
|
|
}
|
|
taskData.video.data = videoList;
|
|
stateUpdates.taskVideos = videoList;
|
|
stateUpdates.isGeneratingVideo = true;
|
|
loadingText = LOADING_TEXT_MAP.video(videoList.length, task.task_result.total_count);
|
|
}
|
|
if (task.task_status === 'COMPLETED') {
|
|
console.log('----------视频生成完成');
|
|
// 视频生成完成
|
|
taskData.video.total_count = taskData.video.data.length;
|
|
stateUpdates.isGeneratingVideo = false;
|
|
taskData.status = '4';
|
|
|
|
// 暂时没有音频生成 直接跳过
|
|
taskData.status = '5';
|
|
loadingText = LOADING_TEXT_MAP.postProduction('generating rough cut video...');
|
|
}
|
|
stateUpdates.currentStep = taskData.status;
|
|
break;
|
|
}
|
|
|
|
// 粗剪
|
|
if (task.task_name === 'generate_final_simple_video') {
|
|
if (task.task_result && task.task_result.video) {
|
|
stateUpdates.final = {
|
|
url: task.task_result.video,
|
|
};
|
|
taskData.status = '5.5';
|
|
loadingText = LOADING_TEXT_MAP.postProduction('generating fine-grained video clips...');
|
|
}
|
|
}
|
|
|
|
// 最终剪辑
|
|
if (task.task_name === 'generate_final_video') {
|
|
if (task.task_result && task.task_result.video) {
|
|
stateUpdates.final = {
|
|
url: task.task_result.video,
|
|
};
|
|
taskData.status = '6';
|
|
loadingText = LOADING_TEXT_MAP.complete;
|
|
|
|
// 停止轮询
|
|
stateUpdates.needStreamData = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log('-----look-finalStep-----', taskData.status);
|
|
|
|
// 设置最终的状态更新
|
|
stateUpdates.currentStep = taskData.status;
|
|
stateUpdates.currentLoadingText = loadingText;
|
|
|
|
// 批量更新所有状态 因为上面的循环 会执行很多次更新 影响性能
|
|
if (stateUpdates.taskSketch) setTaskSketch(stateUpdates.taskSketch);
|
|
if (stateUpdates.taskScenes) setTaskScenes(stateUpdates.taskScenes);
|
|
if (stateUpdates.taskShotSketch) setTaskShotSketch(stateUpdates.taskShotSketch);
|
|
if (stateUpdates.roles) setRoles(stateUpdates.roles);
|
|
if (stateUpdates.taskVideos) setTaskVideos(stateUpdates.taskVideos);
|
|
if (stateUpdates.isGeneratingSketch !== undefined) setIsGeneratingSketch(stateUpdates.isGeneratingSketch);
|
|
if (stateUpdates.isGeneratingVideo !== undefined) setIsGeneratingVideo(stateUpdates.isGeneratingVideo);
|
|
if (stateUpdates.currentStep) setCurrentStep(stateUpdates.currentStep);
|
|
if (stateUpdates.currentLoadingText) setCurrentLoadingText(stateUpdates.currentLoadingText);
|
|
if (stateUpdates.final) setFinal(stateUpdates.final);
|
|
if (stateUpdates.needStreamData !== undefined) setNeedStreamData(stateUpdates.needStreamData);
|
|
if (stateUpdates.totalSketchCount) setTotalSketchCount(stateUpdates.totalSketchCount);
|
|
|
|
// Redux 更新放在最后,避免触发额外的 useEffect
|
|
if (stateUpdates.taskSketch) updateSketchCount(stateUpdates.taskSketch.length);
|
|
if (stateUpdates.taskVideos) updateVideoCount(stateUpdates.taskVideos.length);
|
|
|
|
// 更新 taskObject
|
|
if (stateUpdates.currentStep) {
|
|
setTaskObject(prev => {
|
|
if (!prev) return null;
|
|
return {
|
|
...prev,
|
|
taskStatus: stateUpdates.currentStep!
|
|
};
|
|
});
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('获取数据失败:', error);
|
|
}
|
|
}, [episodeId, needStreamData, roles.length, taskShotSketch.length]);
|
|
|
|
// 轮询获取流式数据
|
|
useEffect(() => {
|
|
let interval: NodeJS.Timeout;
|
|
|
|
if (needStreamData) {
|
|
interval = setInterval(fetchStreamData, 10000);
|
|
fetchStreamData(); // 立即执行一次
|
|
}
|
|
|
|
return () => {
|
|
if (interval) {
|
|
clearInterval(interval);
|
|
}
|
|
};
|
|
}, [needStreamData, fetchStreamData]);
|
|
|
|
// 初始化数据
|
|
const initializeWorkflow = async () => {
|
|
if (!episodeId) {
|
|
setDataLoadError('缺少必要的参数');
|
|
setIsLoading(false);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
setIsLoading(true);
|
|
setCurrentLoadingText('loading project info...');
|
|
|
|
// 获取剧集详情
|
|
const response = await detailScriptEpisodeNew({ project_id: episodeId });
|
|
if (!response.successful) {
|
|
throw new Error(response.message);
|
|
}
|
|
|
|
const { name, status, data, tags, mode, original_text } = response.data;
|
|
setMode(mode as 'automatic' | 'manual' | 'auto');
|
|
setOriginalText(original_text);
|
|
setIsLoading(false);
|
|
|
|
// 设置初始数据
|
|
setTaskObject({
|
|
taskStatus: '0',
|
|
title: name || 'generating...',
|
|
currentLoadingText: status === 'COMPLETED' ? LOADING_TEXT_MAP.complete : LOADING_TEXT_MAP.initializing,
|
|
tags: tags || []
|
|
});
|
|
|
|
// 设置标题
|
|
if (!name) {
|
|
// 如果没有标题,轮询获取
|
|
const titleResponse = await getScriptTitle({ project_id: episodeId });
|
|
console.log('titleResponse', titleResponse);
|
|
if (titleResponse.successful) {
|
|
setTaskObject((prev: TaskObject | null) => ({
|
|
...(prev || {}),
|
|
title: titleResponse.data.title,
|
|
tags: titleResponse.data.tags || []
|
|
} as TaskObject));
|
|
}
|
|
}
|
|
|
|
if (status === 'COMPLETED') {
|
|
loadingText = LOADING_TEXT_MAP.complete;
|
|
taskData.status = '6';
|
|
}
|
|
|
|
// 如果有已完成的数据,同步到状态
|
|
if (data) {
|
|
if (data.sketch && data.sketch.data) {
|
|
taskData.status = '1';
|
|
const realSketchResultData = data.sketch.data.filter((item: any) => item.image_path);
|
|
const sketchList = [];
|
|
for (const sketch of realSketchResultData) {
|
|
sketchList.push({
|
|
url: sketch.image_path,
|
|
script: sketch.sketch_name,
|
|
});
|
|
}
|
|
taskData.sketch.data = sketchList;
|
|
taskData.sketch.total_count = data.sketch.total_count;
|
|
setTaskSketch(sketchList);
|
|
setTaskScenes(sketchList);
|
|
updateSketchCount(sketchList.length);
|
|
// 设置为最后一个草图
|
|
if (data.sketch.total_count > realSketchResultData.length) {
|
|
setIsGeneratingSketch(true);
|
|
loadingText = LOADING_TEXT_MAP.sketch(realSketchResultData.length, data.sketch.total_count);
|
|
} else {
|
|
taskData.status = '2';
|
|
if (!data.character || !data.character.data || !data.character.data.length) {
|
|
loadingText = LOADING_TEXT_MAP.newCharacter(0, data.character.total_count);
|
|
}
|
|
}
|
|
}
|
|
if (data.character && data.character.data && data.character.data.length > 0) {
|
|
const characterList = [];
|
|
for (const character of data.character.data) {
|
|
characterList.push({
|
|
name: character.character_name,
|
|
url: character.image_path,
|
|
sound: null,
|
|
soundDescription: '',
|
|
roleDescription: character.character_description
|
|
});
|
|
}
|
|
taskData.character.data = characterList;
|
|
taskData.character.total_count = data.character.total_count;
|
|
setRoles(characterList);
|
|
if (data.character.total_count > data.character.data.length) {
|
|
loadingText = LOADING_TEXT_MAP.newCharacter(data.character.data.length, data.character.total_count);
|
|
} else {
|
|
taskData.status = '3';
|
|
if (!data.video || !data.video.data || !data.video.data.length) {
|
|
loadingText = LOADING_TEXT_MAP.getShotSketchStatus;
|
|
}
|
|
}
|
|
}
|
|
if (data.shot_sketch && data.shot_sketch.data) {
|
|
const realShotResultData = data.shot_sketch.data.filter((item: any) => item.url);
|
|
const sketchList = [];
|
|
for (const sketch of realShotResultData) {
|
|
sketchList.push({
|
|
url: sketch.url,
|
|
script: sketch.description,
|
|
});
|
|
}
|
|
taskData.shot_sketch.data = sketchList;
|
|
taskData.shot_sketch.total_count = data.shot_sketch.total_count;
|
|
setTaskSketch(sketchList);
|
|
setTaskShotSketch(sketchList);
|
|
updateSketchCount(sketchList.length);
|
|
// 设置为最后一个草图
|
|
if (data.shot_sketch.total_count > realShotResultData.length) {
|
|
setIsGeneratingSketch(true);
|
|
loadingText = LOADING_TEXT_MAP.shotSketch(realShotResultData.length, data.shot_sketch.total_count);
|
|
} else {
|
|
taskData.status = '3';
|
|
setIsGeneratingVideo(true);
|
|
if (!data.character || !data.character.data || !data.character.data.length) {
|
|
loadingText = LOADING_TEXT_MAP.getVideoStatus;
|
|
}
|
|
}
|
|
}
|
|
if (data.video.data) {
|
|
const realDataVideoData = data.video.data.filter((item: any) => item.urls && item.urls.length > 0);
|
|
if (realDataVideoData.length === 0 && taskData.status === '3') {
|
|
loadingText = LOADING_TEXT_MAP.video(0, data.video.total_count);
|
|
}
|
|
if (realDataVideoData.length > 0) {
|
|
const videoList = [];
|
|
console.log('----------data.video.data', data.video.data);
|
|
for (const video of realDataVideoData) {
|
|
// 每一项 video 有多个视频 默认取存在的项
|
|
videoList.push({
|
|
url: video.urls && video.urls.length > 0 ? video.urls.find((url: string) => url) : null,
|
|
script: video.description,
|
|
audio: null,
|
|
video_id: video.video_id,
|
|
});
|
|
}
|
|
taskData.video.data = videoList;
|
|
taskData.video.total_count = data.video.total_count;
|
|
setTaskVideos(videoList);
|
|
updateVideoCount(videoList.length);
|
|
// 如果在视频步骤,设置为最后一个视频
|
|
if (data.video.total_count > realDataVideoData.length) {
|
|
setIsGeneratingVideo(true);
|
|
loadingText = LOADING_TEXT_MAP.video(realDataVideoData.length, data.video.total_count);
|
|
} else {
|
|
taskData.status = '4';
|
|
loadingText = LOADING_TEXT_MAP.audio;
|
|
|
|
// 暂时没有音频生成 直接跳过
|
|
taskData.status = '5';
|
|
loadingText = LOADING_TEXT_MAP.postProduction('generating rough cut video...');
|
|
}
|
|
}
|
|
}
|
|
|
|
// 粗剪
|
|
if ((data as any).final_simple_video && (data as any).final_simple_video.video) {
|
|
setFinal({
|
|
url: (data as any).final_simple_video.video
|
|
});
|
|
taskData.status = '5.5';
|
|
loadingText = LOADING_TEXT_MAP.postProduction('generating fine-grained video clips...');
|
|
}
|
|
|
|
if (data.final_video && data.final_video.video) {
|
|
setFinal({
|
|
url: data.final_video.video
|
|
});
|
|
taskData.status = '6';
|
|
loadingText = LOADING_TEXT_MAP.complete;
|
|
}
|
|
}
|
|
|
|
console.log('---look-taskData', taskData);
|
|
|
|
// 设置步骤
|
|
setCurrentStep(taskData.status);
|
|
setTaskObject(prev => {
|
|
if (!prev) return null;
|
|
return {
|
|
...prev,
|
|
taskStatus: taskData.status
|
|
};
|
|
});
|
|
console.log('---------loadingText', loadingText);
|
|
setCurrentLoadingText(loadingText);
|
|
|
|
// 设置是否需要获取流式数据
|
|
setNeedStreamData(status !== 'COMPLETED' && taskData.status !== '6');
|
|
|
|
} catch (error) {
|
|
console.error('初始化失败:', error);
|
|
setDataLoadError('加载失败,请重试');
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
// 回退到 指定状态 重新获取数据
|
|
const fallbackToStep = (step: string) => {
|
|
console.log('fallbackToStep', step);
|
|
setCurrentStep(step);
|
|
setNeedStreamData(true);
|
|
taskData = {
|
|
sketch: { data: [], total_count: -1 },
|
|
character: { data: [], total_count: -1 },
|
|
shot_sketch: { data: [], total_count: -1 },
|
|
video: { data: [], total_count: -1 },
|
|
status: step
|
|
};
|
|
// loadingText = LOADING_TEXT_MAP.initializing;
|
|
}
|
|
|
|
// 重试加载数据
|
|
const retryLoadData = () => {
|
|
setDataLoadError(null);
|
|
// 重置所有状态
|
|
setTaskSketch([]);
|
|
setTaskScenes([]);
|
|
setTaskVideos([]);
|
|
updateSketchCount(0);
|
|
updateVideoCount(0);
|
|
setRoles([]);
|
|
setMusic([]);
|
|
setFinal(null);
|
|
setCurrentSketchIndex(0);
|
|
setCurrentStep('0');
|
|
// 重新初始化
|
|
initializeWorkflow();
|
|
};
|
|
|
|
// 初始化
|
|
useEffect(() => {
|
|
initializeWorkflow();
|
|
}, [episodeId]);
|
|
|
|
return {
|
|
taskObject,
|
|
scriptData,
|
|
taskSketch,
|
|
taskScenes,
|
|
taskShotSketch,
|
|
taskVideos,
|
|
sketchCount,
|
|
isLoading,
|
|
currentStep,
|
|
currentSketchIndex,
|
|
isGeneratingSketch,
|
|
isGeneratingVideo,
|
|
currentLoadingText,
|
|
totalSketchCount,
|
|
roles,
|
|
music,
|
|
final,
|
|
dataLoadError,
|
|
setCurrentSketchIndex,
|
|
retryLoadData,
|
|
handleManualPlay,
|
|
isPauseWorkFlow,
|
|
mode,
|
|
setIsPauseWorkFlow,
|
|
setAnyAttribute,
|
|
applyScript,
|
|
fallbackToStep,
|
|
originalText
|
|
};
|
|
}
|