diff --git a/apps/desktop/src-tauri/src/data/models/bowong_text_video_agent.rs b/apps/desktop/src-tauri/src/data/models/bowong_text_video_agent.rs index c470d68..c59dcd8 100644 --- a/apps/desktop/src-tauri/src/data/models/bowong_text_video_agent.rs +++ b/apps/desktop/src-tauri/src/data/models/bowong_text_video_agent.rs @@ -258,12 +258,19 @@ pub struct ComfyUISyncExecuteRequest { pub max_wait_time: Option, } -/// Hedra 文件上传请求 +/// Hedra 文件上传请求(前端到后端) #[derive(Debug, Clone, Serialize, Deserialize)] pub struct HedraFileUploadRequest { + pub file_path: String, + pub purpose: Option, // 'image', 'audio', 'video', 'voice' +} + +/// Hedra 文件上传 API 请求(后端到 API) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct HedraFileUploadApiRequest { pub file_data: Vec, pub filename: String, - pub purpose: Option, // 'image', 'audio', 'video', 'voice' + pub purpose: Option, } /// Hedra 任务提交请求 diff --git a/apps/desktop/src-tauri/src/infrastructure/bowong_text_video_agent_service.rs b/apps/desktop/src-tauri/src/infrastructure/bowong_text_video_agent_service.rs index 10cf612..0610141 100644 --- a/apps/desktop/src-tauri/src/infrastructure/bowong_text_video_agent_service.rs +++ b/apps/desktop/src-tauri/src/infrastructure/bowong_text_video_agent_service.rs @@ -525,7 +525,25 @@ impl BowongTextVideoAgentService { /// Hedra 上传文件 pub async fn hedra_upload_file(&self, request: &HedraFileUploadRequest) -> Result { - self.execute_request("hedra_upload_file", Some(request)).await + // 读取文件内容 + let file_data = std::fs::read(&request.file_path) + .map_err(|e| anyhow!("Failed to read file {}: {}", request.file_path, e))?; + + // 获取文件名 + let filename = std::path::Path::new(&request.file_path) + .file_name() + .and_then(|name| name.to_str()) + .ok_or_else(|| anyhow!("Invalid file path: {}", request.file_path))? + .to_string(); + + // 构造 API 请求 + let api_request = HedraFileUploadApiRequest { + file_data, + filename, + purpose: request.purpose.clone(), + }; + + self.execute_request("hedra_upload_file", Some(&api_request)).await } /// Hedra 提交任务 diff --git a/apps/desktop/src/pages/tools/HedraLipSyncTool.tsx b/apps/desktop/src/pages/tools/HedraLipSyncTool.tsx index 23268ff..f01389f 100644 --- a/apps/desktop/src/pages/tools/HedraLipSyncTool.tsx +++ b/apps/desktop/src/pages/tools/HedraLipSyncTool.tsx @@ -14,6 +14,7 @@ import { FileImage, FileAudio } from 'lucide-react'; +import { open } from '@tauri-apps/api/dialog'; import { useNotifications } from '../../components/NotificationSystem'; import { createBowongTextVideoAgentService } from '../../services/bowongTextVideoAgentService'; import { @@ -104,14 +105,29 @@ const HedraLipSyncTool: React.FC = () => { } }, [addNotification]); - // 文件上传 - const uploadFile = useCallback(async (fileInfo: HedraFileInfo, purpose: 'image' | 'audio'): Promise => { - const request: HedraFileUploadRequest = { - local_file: fileInfo.file, - purpose - }; - + // 文件选择和上传 + const selectAndUploadFile = useCallback(async (purpose: 'image' | 'audio'): Promise => { try { + // 使用文件选择对话框 + const selected = await open({ + multiple: false, + filters: [{ + name: purpose === 'image' ? '图片文件' : '音频文件', + extensions: purpose === 'image' + ? ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'] + : ['mp3', 'wav', 'aac', 'flac', 'm4a', 'ogg'] + }] + }); + + if (!selected || typeof selected !== 'string') { + throw new Error('未选择文件'); + } + + const request: HedraFileUploadRequest = { + file_path: selected, + purpose + }; + const response = await bowongService.hedraUploadFile(request); if (response.status && response.data) { return response.data; @@ -119,7 +135,7 @@ const HedraLipSyncTool: React.FC = () => { throw new Error(response.msg || '文件上传失败'); } } catch (error) { - console.error('文件上传失败:', error); + console.error('文件选择和上传失败:', error); throw error; } }, []); @@ -144,7 +160,7 @@ const HedraLipSyncTool: React.FC = () => { imageFile: prev.imageFile ? { ...prev.imageFile, uploadStatus: 'uploading' } : null })); - const imageUrl = await uploadFile(state.imageFile, 'image'); + const imageUrl = await selectAndUploadFile('image'); setState(prev => ({ ...prev, @@ -157,7 +173,7 @@ const HedraLipSyncTool: React.FC = () => { audioFile: prev.audioFile ? { ...prev.audioFile, uploadStatus: 'uploading' } : null })); - const audioUrl = await uploadFile(state.audioFile, 'audio'); + const audioUrl = await selectAndUploadFile('audio'); setState(prev => ({ ...prev, @@ -217,7 +233,7 @@ const HedraLipSyncTool: React.FC = () => { message: error instanceof Error ? error.message : '口型合成任务失败' }); } - }, [state.imageFile, state.audioFile, uploadFile, addNotification]); + }, [selectAndUploadFile, addNotification]); // 轮询任务状态 const pollTaskStatus = useCallback(async (taskId: string) => { diff --git a/apps/desktop/src/services/bowongTextVideoAgentService.ts b/apps/desktop/src/services/bowongTextVideoAgentService.ts index 9e5f04f..c0783c2 100644 --- a/apps/desktop/src/services/bowongTextVideoAgentService.ts +++ b/apps/desktop/src/services/bowongTextVideoAgentService.ts @@ -606,15 +606,7 @@ export class BowongTextVideoAgentFastApiService implements BowongTextVideoAgentA // ============================================================================ async hedraUploadFile(request: HedraFileUploadRequest): Promise { - // 将 File 对象转换为后端期望的格式 - const fileData = await this.fileToBytes(request.local_file); - const backendRequest = { - file_data: Array.from(fileData), // 转换为数字数组 - filename: request.local_file.name, - purpose: request.purpose || 'image' - }; - - return this.invokeAPI('hedra_upload_file', backendRequest); + return this.invokeAPI('hedra_upload_file', request); } async hedraSubmitTask(request: HedraTaskSubmitRequest): Promise { @@ -641,23 +633,7 @@ export class BowongTextVideoAgentFastApiService implements BowongTextVideoAgentA // 工具方法 // ============================================================================ - /** - * 将 File 对象转换为字节数组 - */ - private async fileToBytes(file: File): Promise { - return new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.onload = () => { - if (reader.result instanceof ArrayBuffer) { - resolve(new Uint8Array(reader.result)); - } else { - reject(new Error('Failed to read file as ArrayBuffer')); - } - }; - reader.onerror = () => reject(reader.error); - reader.readAsArrayBuffer(file); - }); - } + /** * 获取服务配置 diff --git a/apps/desktop/src/types/bowongTextVideoAgent.ts b/apps/desktop/src/types/bowongTextVideoAgent.ts index 0e9c69e..39e7dd6 100644 --- a/apps/desktop/src/types/bowongTextVideoAgent.ts +++ b/apps/desktop/src/types/bowongTextVideoAgent.ts @@ -545,7 +545,7 @@ export interface ComfyUISyncExecuteRequest { * Hedra 文件上传请求 */ export interface HedraFileUploadRequest { - local_file: File; + file_path: string; purpose?: 'image' | 'audio' | 'video' | 'voice'; // 默认 'image' }