diff --git a/apps/desktop/src-tauri/src/business/services/volcano_video_service.rs b/apps/desktop/src-tauri/src/business/services/volcano_video_service.rs index 71c203d..1e468fa 100644 --- a/apps/desktop/src-tauri/src/business/services/volcano_video_service.rs +++ b/apps/desktop/src-tauri/src/business/services/volcano_video_service.rs @@ -15,6 +15,7 @@ use crate::data::models::video_generation_record::{ }; use crate::data::repositories::video_generation_record_repository::VideoGenerationRecordRepository; use crate::infrastructure::database::Database; +use crate::business::services::cloud_upload_service::CloudUploadService; /// 火山云视频生成API响应(提交任务) #[derive(Debug, Clone, Serialize, Deserialize)] @@ -88,6 +89,7 @@ pub struct VolcanoVideoService { database: Arc, repository: VideoGenerationRecordRepository, http_client: Client, + cloud_upload_service: CloudUploadService, vol_access_key: String, vol_secret_key: String, } @@ -108,6 +110,7 @@ impl VolcanoVideoService { database, repository, http_client, + cloud_upload_service: CloudUploadService::new(), vol_access_key, vol_secret_key, } @@ -210,19 +213,48 @@ impl VolcanoVideoService { /// 调用火山云视频生成API async fn call_volcano_api(&self, record: &VideoGenerationRecord) -> Result { - let image_url = record.image_url.as_ref() - .ok_or_else(|| anyhow!("图片URL不能为空"))?; + // 获取本地文件路径 + let image_path = record.image_url.as_ref() + .ok_or_else(|| anyhow!("图片路径不能为空"))?; + let driving_video_path = record.audio_url.as_ref() + .ok_or_else(|| anyhow!("驱动视频路径不能为空,请上传驱动视频文件"))?; - // 检查是否有驱动视频URL(这个API需要驱动视频) - let driving_video_url = record.audio_url.as_ref() - .ok_or_else(|| anyhow!("驱动视频URL不能为空,请上传驱动视频文件"))?; + // 上传图片到云端 + info!("正在上传图片到云端: {}", image_path); + let image_upload_result = self.cloud_upload_service + .upload_file(image_path, None, None) + .await?; + + if !image_upload_result.success { + return Err(anyhow!("图片上传失败: {}", + image_upload_result.error_message.unwrap_or_default())); + } + + let image_url = image_upload_result.remote_url + .ok_or_else(|| anyhow!("图片上传成功但未返回URL"))?; + + // 上传驱动视频到云端 + info!("正在上传驱动视频到云端: {}", driving_video_path); + let video_upload_result = self.cloud_upload_service + .upload_file(driving_video_path, None, None) + .await?; + + if !video_upload_result.success { + return Err(anyhow!("驱动视频上传失败: {}", + video_upload_result.error_message.unwrap_or_default())); + } + + let driving_video_url = video_upload_result.remote_url + .ok_or_else(|| anyhow!("驱动视频上传成功但未返回URL"))?; + + info!("文件上传完成 - 图片: {}, 驱动视频: {}", image_url, driving_video_url); let request_body = VolcanoVideoGenerationRequest { req_key: "realman_avatar_imitator_v2v_gen_video".to_string(), - image_url: image_url.clone(), + image_url, driving_video_info: DrivingVideoInfo { store_type: 0, // 固定值 - video_url: driving_video_url.clone(), + video_url: driving_video_url, }, }; @@ -543,6 +575,7 @@ impl Clone for VolcanoVideoService { database: self.database.clone(), repository: VideoGenerationRecordRepository::new(self.database.clone()), http_client: self.http_client.clone(), + cloud_upload_service: CloudUploadService::new(), vol_access_key: self.vol_access_key.clone(), vol_secret_key: self.vol_secret_key.clone(), } diff --git a/apps/desktop/src/pages/tools/VideoGenerationTool.tsx b/apps/desktop/src/pages/tools/VideoGenerationTool.tsx index e65f5a6..da2b7c5 100644 --- a/apps/desktop/src/pages/tools/VideoGenerationTool.tsx +++ b/apps/desktop/src/pages/tools/VideoGenerationTool.tsx @@ -446,8 +446,8 @@ const VideoGenerationTool: React.FC = () => { )} {record.audio_url && ( - - 音频 + + 驱动视频 )}