From 87bc4ba419e38cfcd17d0ea72f6f5f99936b485f Mon Sep 17 00:00:00 2001 From: feitianbubu Date: Thu, 13 Nov 2025 23:26:21 +0800 Subject: [PATCH] feat: get hailuo video url --- controller/task_video.go | 1 + model/task.go | 11 +++++ relay/channel/task/hailuo/adaptor.go | 60 ++++++++++++++++++---------- relay/channel/task/hailuo/models.go | 25 +++++++++--- 4 files changed, 72 insertions(+), 25 deletions(-) diff --git a/controller/task_video.go b/controller/task_video.go index c39593507..8c9f9719e 100644 --- a/controller/task_video.go +++ b/controller/task_video.go @@ -52,6 +52,7 @@ func updateVideoTaskAll(ctx context.Context, platform constant.TaskPlatform, cha info.ChannelMeta = &relaycommon.ChannelMeta{ ChannelBaseUrl: cacheGetChannel.GetBaseURL(), } + info.ApiKey = cacheGetChannel.Key adaptor.Init(info) for _, taskId := range taskIds { if err := updateVideoSingleTask(ctx, adaptor, cacheGetChannel, taskId, taskM); err != nil { diff --git a/model/task.go b/model/task.go index 4e5b4193b..c76d26edf 100644 --- a/model/task.go +++ b/model/task.go @@ -429,3 +429,14 @@ func TaskCountAllUserTask(userId int, queryParams SyncTaskQueryParams) int64 { _ = query.Count(&total).Error return total } +func (t *Task) ToOpenAIVideo() *dto.OpenAIVideo { + openAIVideo := dto.NewOpenAIVideo() + openAIVideo.ID = t.TaskID + openAIVideo.Status = t.Status.ToVideoStatus() + openAIVideo.Model = t.Properties.OriginModelName + openAIVideo.SetProgressStr(t.Progress) + openAIVideo.CreatedAt = t.CreatedAt + openAIVideo.CompletedAt = t.UpdatedAt + openAIVideo.SetMetadata("url", t.FailReason) + return openAIVideo +} diff --git a/relay/channel/task/hailuo/adaptor.go b/relay/channel/task/hailuo/adaptor.go index 2c8e7e9d7..8920e70f6 100644 --- a/relay/channel/task/hailuo/adaptor.go +++ b/relay/channel/task/hailuo/adaptor.go @@ -12,7 +12,6 @@ import ( "github.com/QuantumNous/new-api/common" "github.com/QuantumNous/new-api/model" - "github.com/gin-gonic/gin" "github.com/pkg/errors" @@ -259,11 +258,7 @@ func (a *TaskAdaptor) ParseTaskResult(respBody []byte) (*relaycommon.TaskInfo, e case TaskStatusSuccess: taskResult.Status = model.TaskStatusSuccess taskResult.Progress = "100%" - if resTask.VideoURL != "" { - taskResult.Url = resTask.VideoURL - } else if resTask.FileID != "" { - taskResult.Url = fmt.Sprintf("https://api.minimaxi.com/v1/files/download?file_id=%s", resTask.FileID) - } + taskResult.Url = a.buildVideoURL(resTask.TaskID, resTask.FileID) case TaskStatusFailed: taskResult.Status = model.TaskStatusFailure taskResult.Progress = "100%" @@ -284,20 +279,7 @@ func (a *TaskAdaptor) ConvertToOpenAIVideo(originTask *model.Task) ([]byte, erro return nil, errors.Wrap(err, "unmarshal hailuo task data failed") } - openAIVideo := dto.NewOpenAIVideo() - openAIVideo.ID = originTask.TaskID - openAIVideo.Status = originTask.Status.ToVideoStatus() - openAIVideo.SetProgressStr(originTask.Progress) - openAIVideo.CreatedAt = originTask.CreatedAt - openAIVideo.CompletedAt = originTask.UpdatedAt - - if hailuoResp.VideoURL != "" { - openAIVideo.SetMetadata("url", hailuoResp.VideoURL) - } else if hailuoResp.FileID != "" { - openAIVideo.SetMetadata("file_id", hailuoResp.FileID) - openAIVideo.SetMetadata("url", fmt.Sprintf("https://api.minimaxi.com/v1/files/download?file_id=%s", hailuoResp.FileID)) - } - + openAIVideo := originTask.ToOpenAIVideo() if hailuoResp.BaseResp.StatusCode != StatusSuccess { openAIVideo.Error = &dto.OpenAIVideoError{ Message: hailuoResp.BaseResp.StatusMsg, @@ -313,6 +295,44 @@ func (a *TaskAdaptor) ConvertToOpenAIVideo(originTask *model.Task) ([]byte, erro return jsonData, nil } +func (a *TaskAdaptor) buildVideoURL(_, fileID string) string { + if a.apiKey == "" || a.baseURL == "" { + return "" + } + + url := fmt.Sprintf("%s/v1/files/retrieve?file_id=%s", a.baseURL, fileID) + + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return "" + } + + req.Header.Set("Accept", "application/json") + req.Header.Set("Authorization", "Bearer "+a.apiKey) + + resp, err := service.GetHttpClient().Do(req) + if err != nil { + return "" + } + defer resp.Body.Close() + + responseBody, err := io.ReadAll(resp.Body) + if err != nil { + return "" + } + + var retrieveResp RetrieveFileResponse + if err := json.Unmarshal(responseBody, &retrieveResp); err != nil { + return "" + } + + if retrieveResp.BaseResp.StatusCode != StatusSuccess { + return "" + } + + return retrieveResp.File.DownloadURL +} + func contains(slice []string, item string) bool { for _, s := range slice { if s == item { diff --git a/relay/channel/task/hailuo/models.go b/relay/channel/task/hailuo/models.go index a5d3d0a5c..242857015 100644 --- a/relay/channel/task/hailuo/models.go +++ b/relay/channel/task/hailuo/models.go @@ -26,11 +26,12 @@ type QueryTaskRequest struct { } type QueryTaskResponse struct { - TaskID string `json:"task_id"` - Status string `json:"status"` - FileID string `json:"file_id,omitempty"` - VideoURL string `json:"video_url,omitempty"` - BaseResp BaseResp `json:"base_resp"` + TaskID string `json:"task_id"` + Status string `json:"status"` + FileID string `json:"file_id,omitempty"` + VideoWidth int `json:"video_width,omitempty"` + VideoHeight int `json:"video_height,omitempty"` + BaseResp BaseResp `json:"base_resp"` } type ErrorInfo struct { @@ -56,6 +57,20 @@ type ModelConfig struct { HasFastPretreatment bool } +type RetrieveFileResponse struct { + File FileObject `json:"file"` + BaseResp BaseResp `json:"base_resp"` +} + +type FileObject struct { + FileID int64 `json:"file_id"` + Bytes int64 `json:"bytes"` + CreatedAt int64 `json:"created_at"` + Filename string `json:"filename"` + Purpose string `json:"purpose"` + DownloadURL string `json:"download_url"` +} + func GetModelConfig(model string) ModelConfig { configs := map[string]ModelConfig{ "MiniMax-Hailuo-2.3": {