forked from 77media/video-flow
建立新project,对接完成
This commit is contained in:
parent
23e161d297
commit
dc06c708ba
@ -14,12 +14,16 @@ export interface CharacterRegion {
|
|||||||
|
|
||||||
/** 角色分析信息 */
|
/** 角色分析信息 */
|
||||||
export interface CharacterAnalysis {
|
export interface CharacterAnalysis {
|
||||||
|
/** 角色头像URL */
|
||||||
|
crop_url: string;
|
||||||
/** 角色ID */
|
/** 角色ID */
|
||||||
id: string;
|
id: string;
|
||||||
/** 角色名称 */
|
/** 角色名称 */
|
||||||
role_name: string;
|
role_name: string;
|
||||||
/** 角色区域 */
|
/** 角色区域 */
|
||||||
region: CharacterRegion|null;
|
region: CharacterRegion|null;
|
||||||
|
/** 角色描述 */
|
||||||
|
whisk_caption: string;
|
||||||
/** 角色头像URL(可选,用于存储裁剪后的头像) */
|
/** 角色头像URL(可选,用于存储裁剪后的头像) */
|
||||||
avatarUrl?: string;
|
avatarUrl?: string;
|
||||||
}
|
}
|
||||||
@ -41,3 +45,108 @@ export interface MovieStartDTO {
|
|||||||
/** 错误信息 */
|
/** 错误信息 */
|
||||||
error: string | null;
|
error: string | null;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 创建电影项目V2请求参数
|
||||||
|
*/
|
||||||
|
export interface CreateMovieProjectV2Request {
|
||||||
|
/** 剧本内容 */
|
||||||
|
script: string;
|
||||||
|
/** 用户ID */
|
||||||
|
user_id: string;
|
||||||
|
/** 模式:auto | manual */
|
||||||
|
mode: "auto" | "manual";
|
||||||
|
/** 分辨率:720p | 1080p | 4k */
|
||||||
|
resolution: "720p" | "1080p" | "4k";
|
||||||
|
/** 类型 */
|
||||||
|
genre: string;
|
||||||
|
/** 角色简介数组 */
|
||||||
|
character_briefs: string[];
|
||||||
|
/** 语言 */
|
||||||
|
language: string;
|
||||||
|
/** 图片URL */
|
||||||
|
image_url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建电影项目V2响应数据
|
||||||
|
*/
|
||||||
|
export interface CreateMovieProjectV2Response {
|
||||||
|
/** 原始文本 */
|
||||||
|
original_text: string;
|
||||||
|
/** 项目ID */
|
||||||
|
project_id: string;
|
||||||
|
/** 视频数据 */
|
||||||
|
video: Record<string, any>;
|
||||||
|
/** 扩展数据2 */
|
||||||
|
ext2: Record<string, any>;
|
||||||
|
/** 多语言视频 */
|
||||||
|
multilingual_video: Record<string, any>;
|
||||||
|
/** 制作手册 */
|
||||||
|
production_bible: string;
|
||||||
|
/** 项目名称 */
|
||||||
|
name: string;
|
||||||
|
/** 音乐数据 */
|
||||||
|
music: Record<string, any>;
|
||||||
|
/** 扩展数据3 */
|
||||||
|
ext3: Record<string, any>;
|
||||||
|
/** 语言 */
|
||||||
|
language: string;
|
||||||
|
/** 分镜头 */
|
||||||
|
storyboard: string;
|
||||||
|
/** 状态 */
|
||||||
|
status: string;
|
||||||
|
/** 最终视频 */
|
||||||
|
final_video: Record<string, any>;
|
||||||
|
/** 扩展数据4 */
|
||||||
|
ext4: string;
|
||||||
|
/** 产品代码 */
|
||||||
|
pcode: string;
|
||||||
|
/** 制作手册JSON */
|
||||||
|
production_bible_json: Record<string, any>;
|
||||||
|
/** 步骤 */
|
||||||
|
step: string;
|
||||||
|
/** 最终简单视频 */
|
||||||
|
final_simple_video: Record<string, any>;
|
||||||
|
/** 扩展数据5 */
|
||||||
|
ext5: string;
|
||||||
|
/** 产品代码版本 */
|
||||||
|
pcode_version: string;
|
||||||
|
/** 分辨率 */
|
||||||
|
resolution: string;
|
||||||
|
/** 剧本分镜头 */
|
||||||
|
script_shots: string;
|
||||||
|
/** 最后消息 */
|
||||||
|
last_message: string;
|
||||||
|
/** 扩展数据 */
|
||||||
|
ext: Record<string, any>;
|
||||||
|
/** 角色草稿 */
|
||||||
|
character_draft: any;
|
||||||
|
/** 模式 */
|
||||||
|
mode: string;
|
||||||
|
/** 提示词 */
|
||||||
|
prompts: string;
|
||||||
|
/** 草图 */
|
||||||
|
sketch: Record<string, any>;
|
||||||
|
/** 当前任务ID */
|
||||||
|
current_task_id: string;
|
||||||
|
/** 创建时间 */
|
||||||
|
created_at: string;
|
||||||
|
/** ID */
|
||||||
|
id: number;
|
||||||
|
/** 描述 */
|
||||||
|
description: string;
|
||||||
|
/** 镜头草图 */
|
||||||
|
shot_sketch: Record<string, any>;
|
||||||
|
/** 扩展数据1 */
|
||||||
|
ext1: Record<string, any>;
|
||||||
|
/** 当前计划ID */
|
||||||
|
current_plan_id: string;
|
||||||
|
/** 用户ID */
|
||||||
|
user_id: string;
|
||||||
|
/** 生成的剧本 */
|
||||||
|
generated_script: string;
|
||||||
|
/** 角色数据 */
|
||||||
|
character: Record<string, any>;
|
||||||
|
/** 更新时间 */
|
||||||
|
updated_at: string;
|
||||||
|
}
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import { task_item, VideoSegmentEntityAdapter } from "@/app/service/adapter/oldE
|
|||||||
import { VideoFlowProjectResponse, NewCharacterItem, NewCharacterListResponse, CharacterListByProjectWithHighlightResponse, CharacterUpdateAndRegenerateRequest, CharacterUpdateAndRegenerateResponse } from "./DTO/movieEdit";
|
import { VideoFlowProjectResponse, NewCharacterItem, NewCharacterListResponse, CharacterListByProjectWithHighlightResponse, CharacterUpdateAndRegenerateRequest, CharacterUpdateAndRegenerateResponse } from "./DTO/movieEdit";
|
||||||
import { RoleResponse } from "./DTO/movieEdit";
|
import { RoleResponse } from "./DTO/movieEdit";
|
||||||
import { RoleRecognitionResponse } from "./DTO/movieEdit";
|
import { RoleRecognitionResponse } from "./DTO/movieEdit";
|
||||||
|
import { CreateMovieProjectV2Request, CreateMovieProjectV2Response } from "./DTO/movie_start_dto";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 角色替换参数接口
|
* 角色替换参数接口
|
||||||
@ -1149,3 +1150,19 @@ export const modifyCharacterOrScene = async (request: {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建电影项目V2
|
||||||
|
* @param request - 创建项目请求参数
|
||||||
|
* @returns Promise<ApiResponse<CreateMovieProjectV2Response>>
|
||||||
|
*/
|
||||||
|
export const createMovieProjectV2 = async (
|
||||||
|
request: CreateMovieProjectV2Request
|
||||||
|
)=> {
|
||||||
|
return post<ApiResponse<CreateMovieProjectV2Response>>(
|
||||||
|
"/movie/create_movie_project_v2",
|
||||||
|
request
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,9 @@ import {
|
|||||||
Dispatch,
|
Dispatch,
|
||||||
SetStateAction,
|
SetStateAction,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { CharacterAnalysis } from "@/api/DTO/movie_start_dto";
|
import { CharacterAnalysis, CreateMovieProjectV2Request, CreateMovieProjectV2Response } from "@/api/DTO/movie_start_dto";
|
||||||
|
import { createMovieProjectV2 } from "@/api/video_flow";
|
||||||
|
import { ApiResponse } from "@/api/common";
|
||||||
|
|
||||||
interface UseImageStoryService {
|
interface UseImageStoryService {
|
||||||
/** 当前图片故事数据 */
|
/** 当前图片故事数据 */
|
||||||
@ -48,7 +50,12 @@ interface UseImageStoryService {
|
|||||||
/** 重置图片故事数据 */
|
/** 重置图片故事数据 */
|
||||||
resetImageStory: (showAnalysisState?: boolean) => void;
|
resetImageStory: (showAnalysisState?: boolean) => void;
|
||||||
/** 生成动作电影 */
|
/** 生成动作电影 */
|
||||||
actionMovie: () => Promise<void>;
|
actionMovie: (
|
||||||
|
user_id: string,
|
||||||
|
mode?: "auto" | "manual",
|
||||||
|
resolution?: "720p" | "1080p" | "4k",
|
||||||
|
language?: string
|
||||||
|
) => Promise<CreateMovieProjectV2Response|undefined>;
|
||||||
/** 设置角色分析 */
|
/** 设置角色分析 */
|
||||||
setCharactersAnalysis: Dispatch<SetStateAction<CharacterAnalysis[]>>;
|
setCharactersAnalysis: Dispatch<SetStateAction<CharacterAnalysis[]>>;
|
||||||
/** 设置原始用户描述 */
|
/** 设置原始用户描述 */
|
||||||
@ -212,6 +219,7 @@ export const useImageStoryServiceHook = (): UseImageStoryService => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return charactersAnalysis.map((character) => {
|
return charactersAnalysis.map((character) => {
|
||||||
|
console.log('character', character)
|
||||||
// 如果已经有头像URL,直接返回
|
// 如果已经有头像URL,直接返回
|
||||||
if (character.avatarUrl) {
|
if (character.avatarUrl) {
|
||||||
return {
|
return {
|
||||||
@ -266,12 +274,7 @@ export const useImageStoryServiceHook = (): UseImageStoryService => {
|
|||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
}, [
|
}, [imageStoryUseCase, activeImageUrl, storyContent]);
|
||||||
activeImageUrl,
|
|
||||||
imageStoryUseCase,
|
|
||||||
storyContent,
|
|
||||||
setOriginalUserDescription,
|
|
||||||
]);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 触发生成剧本函数
|
* 触发生成剧本函数
|
||||||
@ -378,14 +381,7 @@ export const useImageStoryServiceHook = (): UseImageStoryService => {
|
|||||||
imageStoryUseCase.resetImageStory();
|
imageStoryUseCase.resetImageStory();
|
||||||
|
|
||||||
// 清理生成的头像URL,避免内存泄漏
|
// 清理生成的头像URL,避免内存泄漏
|
||||||
setCharactersAnalysis((prev) => {
|
setCharactersAnalysis([]);
|
||||||
prev.forEach((char) => {
|
|
||||||
if (char.avatarUrl) {
|
|
||||||
URL.revokeObjectURL(char.avatarUrl);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return [];
|
|
||||||
});
|
|
||||||
|
|
||||||
// 重置所有状态
|
// 重置所有状态
|
||||||
setImageStory({
|
setImageStory({
|
||||||
@ -453,18 +449,36 @@ export const useImageStoryServiceHook = (): UseImageStoryService => {
|
|||||||
});
|
});
|
||||||
}, [uploadFile]);
|
}, [uploadFile]);
|
||||||
|
|
||||||
const actionMovie = useCallback(async (): Promise<void> => {
|
const actionMovie = useCallback(async (
|
||||||
|
user_id: string,
|
||||||
|
mode: "auto" | "manual" = "auto",
|
||||||
|
resolution: "720p" | "1080p" | "4k" = "720p",
|
||||||
|
language: string = "English"
|
||||||
|
) => {
|
||||||
try {
|
try {
|
||||||
if (hasAnalyzed) {
|
if (hasAnalyzed) {
|
||||||
const params = {
|
// 从charactersAnalysis中提取whisk_caption字段组成数组
|
||||||
content: storyContent,
|
const character_briefs = charactersAnalysis.map(char => char.whisk_caption);
|
||||||
category: selectedCategory,
|
|
||||||
|
const params: CreateMovieProjectV2Request = {
|
||||||
|
script: storyContent,
|
||||||
|
user_id,
|
||||||
|
mode,
|
||||||
|
resolution,
|
||||||
|
genre: selectedCategory,
|
||||||
|
character_briefs,
|
||||||
|
language,
|
||||||
|
image_url: activeImageUrl,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 调用create_movie_project_v2接口
|
||||||
|
const result = await createMovieProjectV2(params)
|
||||||
|
return result.data;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("图片上传分析失败:", error);
|
console.error("创建电影项目失败:", error);
|
||||||
}
|
}
|
||||||
}, [activeImageUrl, imageStoryUseCase]);
|
}, [hasAnalyzed, storyContent, charactersAnalysis, selectedCategory, activeImageUrl]);
|
||||||
return {
|
return {
|
||||||
imageStory,
|
imageStory,
|
||||||
activeImageUrl,
|
activeImageUrl,
|
||||||
|
|||||||
@ -95,6 +95,7 @@ export class ImageStoryUseCase {
|
|||||||
async analyzeImageWithAI() {
|
async analyzeImageWithAI() {
|
||||||
console.log('this.imageStory.imageUrl', this.imageStory.imageUrl)
|
console.log('this.imageStory.imageUrl', this.imageStory.imageUrl)
|
||||||
try {
|
try {
|
||||||
|
//
|
||||||
// 调用AI分析接口
|
// 调用AI分析接口
|
||||||
const response = await AIGenerateImageStory({
|
const response = await AIGenerateImageStory({
|
||||||
image_url: this.imageStory.imageUrl || "",
|
image_url: this.imageStory.imageUrl || "",
|
||||||
|
|||||||
@ -508,7 +508,12 @@ export function ChatInputBox() {
|
|||||||
const [isCreating, setIsCreating] = useState(false); // 视频创建过程中的加载状态
|
const [isCreating, setIsCreating] = useState(false); // 视频创建过程中的加载状态
|
||||||
|
|
||||||
// 配置选项状态 - 整合所有配置项到一个对象
|
// 配置选项状态 - 整合所有配置项到一个对象
|
||||||
const [configOptions, setConfigOptions] = useState({
|
const [configOptions, setConfigOptions] = useState<{
|
||||||
|
mode: "auto" | "manual";
|
||||||
|
resolution: "720p" | "1080p" | "4k";
|
||||||
|
language: string;
|
||||||
|
videoDuration: string;
|
||||||
|
}>({
|
||||||
mode: "auto",
|
mode: "auto",
|
||||||
resolution: "720p",
|
resolution: "720p",
|
||||||
language: "english",
|
language: "english",
|
||||||
@ -702,6 +707,7 @@ export function ChatInputBox() {
|
|||||||
<PhotoStoryModal
|
<PhotoStoryModal
|
||||||
isOpen={isPhotoStoryModalOpen}
|
isOpen={isPhotoStoryModalOpen}
|
||||||
onClose={() => setIsPhotoStoryModalOpen(false)}
|
onClose={() => setIsPhotoStoryModalOpen(false)}
|
||||||
|
configOptions={configOptions}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -1003,9 +1009,21 @@ const RoleHighlightEditor = ({
|
|||||||
const PhotoStoryModal = ({
|
const PhotoStoryModal = ({
|
||||||
isOpen,
|
isOpen,
|
||||||
onClose,
|
onClose,
|
||||||
|
configOptions = {
|
||||||
|
mode: "auto" as "auto" | "manual",
|
||||||
|
resolution: "720p" as "720p" | "1080p" | "4k",
|
||||||
|
language: "english",
|
||||||
|
videoDuration: "1min",
|
||||||
|
},
|
||||||
}: {
|
}: {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
configOptions?: {
|
||||||
|
mode: "auto" | "manual";
|
||||||
|
resolution: "720p" | "1080p" | "4k";
|
||||||
|
language: string;
|
||||||
|
videoDuration: string;
|
||||||
|
};
|
||||||
}) => {
|
}) => {
|
||||||
// 使用图片故事服务hook管理状态
|
// 使用图片故事服务hook管理状态
|
||||||
const {
|
const {
|
||||||
@ -1023,7 +1041,8 @@ const PhotoStoryModal = ({
|
|||||||
avatarComputed,
|
avatarComputed,
|
||||||
uploadAndAnalyzeImage,
|
uploadAndAnalyzeImage,
|
||||||
setCharactersAnalysis,
|
setCharactersAnalysis,
|
||||||
originalUserDescription
|
originalUserDescription,
|
||||||
|
actionMovie
|
||||||
} = useImageStoryServiceHook();
|
} = useImageStoryServiceHook();
|
||||||
const { loadingText } = useLoadScriptText(isLoading);
|
const { loadingText } = useLoadScriptText(isLoading);
|
||||||
// 重置状态
|
// 重置状态
|
||||||
@ -1031,7 +1050,7 @@ const PhotoStoryModal = ({
|
|||||||
resetImageStory();
|
resetImageStory();
|
||||||
onClose();
|
onClose();
|
||||||
};
|
};
|
||||||
|
const router = useRouter();
|
||||||
// 处理图片上传
|
// 处理图片上传
|
||||||
const handleImageUpload = async () => {
|
const handleImageUpload = async () => {
|
||||||
try {
|
try {
|
||||||
@ -1042,8 +1061,31 @@ const PhotoStoryModal = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 处理确认
|
// 处理确认
|
||||||
const handleConfirm = () => {
|
const handleConfirm = async () => {
|
||||||
if (hasAnalyzed) {
|
try {
|
||||||
|
// 获取当前用户信息
|
||||||
|
const User = JSON.parse(localStorage.getItem("currentUser") || "{}");
|
||||||
|
|
||||||
|
if (!User.id) {
|
||||||
|
console.error("用户未登录");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用actionMovie接口
|
||||||
|
const episodeResponse = await actionMovie(
|
||||||
|
String(User.id),
|
||||||
|
configOptions.mode as "auto" | "manual",
|
||||||
|
configOptions.resolution as "720p" | "1080p" | "4k",
|
||||||
|
configOptions.language
|
||||||
|
);
|
||||||
|
if(!episodeResponse) return
|
||||||
|
let episodeId = episodeResponse.project_id;
|
||||||
|
// let episodeId = '9c34fcc4-c8d8-44fc-879e-9bd56f608c76';
|
||||||
|
router.push(`/create/work-flow?episodeId=${episodeId}`);
|
||||||
|
// 成功后关闭弹窗
|
||||||
|
handleClose();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("创建电影项目失败:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user