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 {
|
||||
/** 角色头像URL */
|
||||
crop_url: string;
|
||||
/** 角色ID */
|
||||
id: string;
|
||||
/** 角色名称 */
|
||||
role_name: string;
|
||||
/** 角色区域 */
|
||||
region: CharacterRegion|null;
|
||||
/** 角色描述 */
|
||||
whisk_caption: string;
|
||||
/** 角色头像URL(可选,用于存储裁剪后的头像) */
|
||||
avatarUrl?: string;
|
||||
}
|
||||
@ -41,3 +45,108 @@ export interface MovieStartDTO {
|
||||
/** 错误信息 */
|
||||
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 { RoleResponse } 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,
|
||||
SetStateAction,
|
||||
} 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 {
|
||||
/** 当前图片故事数据 */
|
||||
@ -48,7 +50,12 @@ interface UseImageStoryService {
|
||||
/** 重置图片故事数据 */
|
||||
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[]>>;
|
||||
/** 设置原始用户描述 */
|
||||
@ -212,6 +219,7 @@ export const useImageStoryServiceHook = (): UseImageStoryService => {
|
||||
}
|
||||
|
||||
return charactersAnalysis.map((character) => {
|
||||
console.log('character', character)
|
||||
// 如果已经有头像URL,直接返回
|
||||
if (character.avatarUrl) {
|
||||
return {
|
||||
@ -266,12 +274,7 @@ export const useImageStoryServiceHook = (): UseImageStoryService => {
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [
|
||||
activeImageUrl,
|
||||
imageStoryUseCase,
|
||||
storyContent,
|
||||
setOriginalUserDescription,
|
||||
]);
|
||||
}, [imageStoryUseCase, activeImageUrl, storyContent]);
|
||||
|
||||
/**
|
||||
* 触发生成剧本函数
|
||||
@ -378,14 +381,7 @@ export const useImageStoryServiceHook = (): UseImageStoryService => {
|
||||
imageStoryUseCase.resetImageStory();
|
||||
|
||||
// 清理生成的头像URL,避免内存泄漏
|
||||
setCharactersAnalysis((prev) => {
|
||||
prev.forEach((char) => {
|
||||
if (char.avatarUrl) {
|
||||
URL.revokeObjectURL(char.avatarUrl);
|
||||
}
|
||||
});
|
||||
return [];
|
||||
});
|
||||
setCharactersAnalysis([]);
|
||||
|
||||
// 重置所有状态
|
||||
setImageStory({
|
||||
@ -453,18 +449,36 @@ export const useImageStoryServiceHook = (): UseImageStoryService => {
|
||||
});
|
||||
}, [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 {
|
||||
if (hasAnalyzed) {
|
||||
const params = {
|
||||
content: storyContent,
|
||||
category: selectedCategory,
|
||||
// 从charactersAnalysis中提取whisk_caption字段组成数组
|
||||
const character_briefs = charactersAnalysis.map(char => char.whisk_caption);
|
||||
|
||||
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) {
|
||||
console.error("图片上传分析失败:", error);
|
||||
console.error("创建电影项目失败:", error);
|
||||
}
|
||||
}, [activeImageUrl, imageStoryUseCase]);
|
||||
}, [hasAnalyzed, storyContent, charactersAnalysis, selectedCategory, activeImageUrl]);
|
||||
return {
|
||||
imageStory,
|
||||
activeImageUrl,
|
||||
|
||||
@ -95,6 +95,7 @@ export class ImageStoryUseCase {
|
||||
async analyzeImageWithAI() {
|
||||
console.log('this.imageStory.imageUrl', this.imageStory.imageUrl)
|
||||
try {
|
||||
//
|
||||
// 调用AI分析接口
|
||||
const response = await AIGenerateImageStory({
|
||||
image_url: this.imageStory.imageUrl || "",
|
||||
|
||||
@ -508,7 +508,12 @@ export function ChatInputBox() {
|
||||
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",
|
||||
resolution: "720p",
|
||||
language: "english",
|
||||
@ -699,10 +704,11 @@ export function ChatInputBox() {
|
||||
</Tooltip>
|
||||
|
||||
{/* 图片故事弹窗 */}
|
||||
<PhotoStoryModal
|
||||
isOpen={isPhotoStoryModalOpen}
|
||||
onClose={() => setIsPhotoStoryModalOpen(false)}
|
||||
/>
|
||||
<PhotoStoryModal
|
||||
isOpen={isPhotoStoryModalOpen}
|
||||
onClose={() => setIsPhotoStoryModalOpen(false)}
|
||||
configOptions={configOptions}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 右侧Action按钮 */}
|
||||
@ -1003,9 +1009,21 @@ const RoleHighlightEditor = ({
|
||||
const PhotoStoryModal = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
configOptions = {
|
||||
mode: "auto" as "auto" | "manual",
|
||||
resolution: "720p" as "720p" | "1080p" | "4k",
|
||||
language: "english",
|
||||
videoDuration: "1min",
|
||||
},
|
||||
}: {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
configOptions?: {
|
||||
mode: "auto" | "manual";
|
||||
resolution: "720p" | "1080p" | "4k";
|
||||
language: string;
|
||||
videoDuration: string;
|
||||
};
|
||||
}) => {
|
||||
// 使用图片故事服务hook管理状态
|
||||
const {
|
||||
@ -1023,7 +1041,8 @@ const PhotoStoryModal = ({
|
||||
avatarComputed,
|
||||
uploadAndAnalyzeImage,
|
||||
setCharactersAnalysis,
|
||||
originalUserDescription
|
||||
originalUserDescription,
|
||||
actionMovie
|
||||
} = useImageStoryServiceHook();
|
||||
const { loadingText } = useLoadScriptText(isLoading);
|
||||
// 重置状态
|
||||
@ -1031,7 +1050,7 @@ const PhotoStoryModal = ({
|
||||
resetImageStory();
|
||||
onClose();
|
||||
};
|
||||
|
||||
const router = useRouter();
|
||||
// 处理图片上传
|
||||
const handleImageUpload = async () => {
|
||||
try {
|
||||
@ -1042,8 +1061,31 @@ const PhotoStoryModal = ({
|
||||
};
|
||||
|
||||
// 处理确认
|
||||
const handleConfirm = () => {
|
||||
if (hasAnalyzed) {
|
||||
const handleConfirm = async () => {
|
||||
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