diff --git a/relay/channel/task/kling/adaptor.go b/relay/channel/task/kling/adaptor.go index e91562aca..4befd8e2e 100644 --- a/relay/channel/task/kling/adaptor.go +++ b/relay/channel/task/kling/adaptor.go @@ -7,9 +7,11 @@ import ( "io" "net/http" "one-api/model" + "strconv" "strings" "time" + "github.com/bytedance/gopkg/util/logger" "github.com/samber/lo" "github.com/gin-gonic/gin" @@ -303,14 +305,6 @@ func (a *TaskAdaptor) createJWTToken() (string, error) { return a.createJWTTokenWithKey(a.apiKey) } -//func (a *TaskAdaptor) createJWTTokenWithKey(apiKey string) (string, error) { -// parts := strings.Split(apiKey, "|") -// if len(parts) != 2 { -// return "", fmt.Errorf("invalid API key format, expected 'access_key,secret_key'") -// } -// return a.createJWTTokenWithKey(strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])) -//} - func (a *TaskAdaptor) createJWTTokenWithKey(apiKey string) (string, error) { if isNewAPIRelay(apiKey) { return apiKey, nil // new api relay @@ -369,3 +363,50 @@ func (a *TaskAdaptor) ParseTaskResult(respBody []byte) (*relaycommon.TaskInfo, e func isNewAPIRelay(apiKey string) bool { return strings.HasPrefix(apiKey, "sk-") } + +func (a *TaskAdaptor) ConvertToOpenAIVideo(originTask *model.Task) (*relaycommon.OpenAIVideo, error) { + var klingResp responsePayload + if err := json.Unmarshal(originTask.Data, &klingResp); err != nil { + return nil, errors.Wrap(err, "unmarshal kling task data failed") + } + + convertProgress := func(progress string) int { + progress = strings.TrimSuffix(progress, "%") + p, err := strconv.Atoi(progress) + if err != nil { + logger.Warnf("convert progress failed, progress: %s, err: %v", progress, err) + } + return p + } + + openAIVideo := &relaycommon.OpenAIVideo{ + ID: klingResp.Data.TaskId, + Object: "video", + //Model: "kling-v1", //todo save model + Status: string(originTask.Status), + CreatedAt: klingResp.Data.CreatedAt, + CompletedAt: klingResp.Data.UpdatedAt, + Metadata: make(map[string]any), + Progress: convertProgress(originTask.Progress), + } + + // 处理视频 URL + if len(klingResp.Data.TaskResult.Videos) > 0 { + video := klingResp.Data.TaskResult.Videos[0] + if video.Url != "" { + openAIVideo.Metadata["url"] = video.Url + } + if video.Duration != "" { + openAIVideo.Seconds = video.Duration + } + } + + if klingResp.Code != 0 && klingResp.Message != "" { + openAIVideo.Error = &relaycommon.OpenAIVideoError{ + Message: klingResp.Message, + Code: fmt.Sprintf("%d", klingResp.Code), + } + } + + return openAIVideo, nil +} diff --git a/relay/common/relay_info.go b/relay/common/relay_info.go index 7939b48dd..cb3a6709f 100644 --- a/relay/common/relay_info.go +++ b/relay/common/relay_info.go @@ -552,20 +552,22 @@ func RemoveDisabledFields(jsonData []byte, channelOtherSettings dto.ChannelOther } type OpenAIVideo struct { - ID string `json:"id"` - TaskID string `json:"task_id,omitempty"` //兼容旧接口 - Object string `json:"object"` - Model string `json:"model"` - Status string `json:"status"` - Progress int `json:"progress"` - CreatedAt int64 `json:"created_at"` - CompletedAt int64 `json:"completed_at,omitempty"` - ExpiresAt int64 `json:"expires_at,omitempty"` - Seconds string `json:"seconds,omitempty"` - Size string `json:"size,omitempty"` - RemixedFromVideoID string `json:"remixed_from_video_id,omitempty"` - Error *struct { - Message string `json:"message"` - Code string `json:"code"` - } `json:"error,omitempty"` + ID string `json:"id"` + TaskID string `json:"task_id,omitempty"` //兼容旧接口 待废弃 + Object string `json:"object"` + Model string `json:"model"` + Status string `json:"status"` + Progress int `json:"progress"` + CreatedAt int64 `json:"created_at"` + CompletedAt int64 `json:"completed_at,omitempty"` + ExpiresAt int64 `json:"expires_at,omitempty"` + Seconds string `json:"seconds,omitempty"` + Size string `json:"size,omitempty"` + RemixedFromVideoID string `json:"remixed_from_video_id,omitempty"` + Error *OpenAIVideoError `json:"error,omitempty"` + Metadata map[string]any `json:"metadata,omitempty"` +} +type OpenAIVideoError struct { + Message string `json:"message"` + Code string `json:"code"` }