feat: add doubao video 1.5
This commit is contained in:
@@ -0,0 +1,55 @@
|
|||||||
|
package dto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IntValue int
|
||||||
|
|
||||||
|
func (i *IntValue) UnmarshalJSON(b []byte) error {
|
||||||
|
var n int
|
||||||
|
if err := json.Unmarshal(b, &n); err == nil {
|
||||||
|
*i = IntValue(n)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var s string
|
||||||
|
if err := json.Unmarshal(b, &s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
v, err := strconv.Atoi(s)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*i = IntValue(v)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i IntValue) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(int(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
type BoolValue bool
|
||||||
|
|
||||||
|
func (b *BoolValue) UnmarshalJSON(data []byte) error {
|
||||||
|
var boolean bool
|
||||||
|
if err := json.Unmarshal(data, &boolean); err == nil {
|
||||||
|
*b = BoolValue(boolean)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var str string
|
||||||
|
if err := json.Unmarshal(data, &str); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if str == "true" {
|
||||||
|
*b = BoolValue(true)
|
||||||
|
} else if str == "false" {
|
||||||
|
*b = BoolValue(false)
|
||||||
|
} else {
|
||||||
|
return json.Unmarshal(data, &boolean)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (b BoolValue) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(bool(b))
|
||||||
|
}
|
||||||
@@ -6,6 +6,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/QuantumNous/new-api/common"
|
||||||
|
|
||||||
"github.com/QuantumNous/new-api/constant"
|
"github.com/QuantumNous/new-api/constant"
|
||||||
"github.com/QuantumNous/new-api/dto"
|
"github.com/QuantumNous/new-api/dto"
|
||||||
@@ -23,18 +26,36 @@ import (
|
|||||||
// ============================
|
// ============================
|
||||||
|
|
||||||
type ContentItem struct {
|
type ContentItem struct {
|
||||||
Type string `json:"type"` // "text" or "image_url"
|
Type string `json:"type"` // "text", "image_url" or "video"
|
||||||
Text string `json:"text,omitempty"` // for text type
|
Text string `json:"text,omitempty"` // for text type
|
||||||
ImageURL *ImageURL `json:"image_url,omitempty"` // for image_url type
|
ImageURL *ImageURL `json:"image_url,omitempty"` // for image_url type
|
||||||
|
Video *VideoReference `json:"video,omitempty"` // for video (sample) type
|
||||||
}
|
}
|
||||||
|
|
||||||
type ImageURL struct {
|
type ImageURL struct {
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type VideoReference struct {
|
||||||
|
URL string `json:"url"` // Draft video URL
|
||||||
|
}
|
||||||
|
|
||||||
type requestPayload struct {
|
type requestPayload struct {
|
||||||
Model string `json:"model"`
|
Model string `json:"model"`
|
||||||
Content []ContentItem `json:"content"`
|
Content []ContentItem `json:"content"`
|
||||||
|
CallbackURL string `json:"callback_url,omitempty"`
|
||||||
|
ReturnLastFrame *dto.BoolValue `json:"return_last_frame,omitempty"`
|
||||||
|
ServiceTier string `json:"service_tier,omitempty"`
|
||||||
|
ExecutionExpiresAfter dto.IntValue `json:"execution_expires_after,omitempty"`
|
||||||
|
GenerateAudio *dto.BoolValue `json:"generate_audio,omitempty"`
|
||||||
|
Draft *dto.BoolValue `json:"draft,omitempty"`
|
||||||
|
Resolution string `json:"resolution,omitempty"`
|
||||||
|
Ratio string `json:"ratio,omitempty"`
|
||||||
|
Duration dto.IntValue `json:"duration,omitempty"`
|
||||||
|
Frames dto.IntValue `json:"frames,omitempty"`
|
||||||
|
Seed dto.IntValue `json:"seed,omitempty"`
|
||||||
|
CameraFixed *dto.BoolValue `json:"camera_fixed,omitempty"`
|
||||||
|
Watermark *dto.BoolValue `json:"watermark,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type responsePayload struct {
|
type responsePayload struct {
|
||||||
@@ -53,6 +74,7 @@ type responseTask struct {
|
|||||||
Duration int `json:"duration"`
|
Duration int `json:"duration"`
|
||||||
Ratio string `json:"ratio"`
|
Ratio string `json:"ratio"`
|
||||||
FramesPerSecond int `json:"framespersecond"`
|
FramesPerSecond int `json:"framespersecond"`
|
||||||
|
ServiceTier string `json:"service_tier"`
|
||||||
Usage struct {
|
Usage struct {
|
||||||
CompletionTokens int `json:"completion_tokens"`
|
CompletionTokens int `json:"completion_tokens"`
|
||||||
TotalTokens int `json:"total_tokens"`
|
TotalTokens int `json:"total_tokens"`
|
||||||
@@ -98,16 +120,16 @@ func (a *TaskAdaptor) BuildRequestHeader(c *gin.Context, req *http.Request, info
|
|||||||
|
|
||||||
// BuildRequestBody converts request into Doubao specific format.
|
// BuildRequestBody converts request into Doubao specific format.
|
||||||
func (a *TaskAdaptor) BuildRequestBody(c *gin.Context, info *relaycommon.RelayInfo) (io.Reader, error) {
|
func (a *TaskAdaptor) BuildRequestBody(c *gin.Context, info *relaycommon.RelayInfo) (io.Reader, error) {
|
||||||
v, exists := c.Get("task_request")
|
req, err := relaycommon.GetTaskRequest(c)
|
||||||
if !exists {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("request not found in context")
|
return nil, err
|
||||||
}
|
}
|
||||||
req := v.(relaycommon.TaskSubmitReq)
|
|
||||||
|
|
||||||
body, err := a.convertToRequestPayload(&req)
|
body, err := a.convertToRequestPayload(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "convert request payload failed")
|
return nil, errors.Wrap(err, "convert request payload failed")
|
||||||
}
|
}
|
||||||
|
info.UpstreamModelName = body.Model
|
||||||
data, err := json.Marshal(body)
|
data, err := json.Marshal(body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -141,7 +163,13 @@ func (a *TaskAdaptor) DoResponse(c *gin.Context, resp *http.Response, info *rela
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{"task_id": dResp.ID})
|
ov := dto.NewOpenAIVideo()
|
||||||
|
ov.ID = dResp.ID
|
||||||
|
ov.TaskID = dResp.ID
|
||||||
|
ov.CreatedAt = time.Now().Unix()
|
||||||
|
ov.Model = info.OriginModelName
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, ov)
|
||||||
return dResp.ID, responseBody, nil
|
return dResp.ID, responseBody, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,12 +232,15 @@ func (a *TaskAdaptor) convertToRequestPayload(req *relaycommon.TaskSubmitReq) (*
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add support for additional parameters from metadata
|
metadata := req.Metadata
|
||||||
// such as ratio, duration, seed, etc.
|
medaBytes, err := json.Marshal(metadata)
|
||||||
// metadata := req.Metadata
|
if err != nil {
|
||||||
// if metadata != nil {
|
return nil, errors.Wrap(err, "metadata marshal metadata failed")
|
||||||
// // Parse and apply metadata parameters
|
}
|
||||||
// }
|
err = json.Unmarshal(medaBytes, &r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "unmarshal metadata failed")
|
||||||
|
}
|
||||||
|
|
||||||
return &r, nil
|
return &r, nil
|
||||||
}
|
}
|
||||||
@@ -229,7 +260,7 @@ func (a *TaskAdaptor) ParseTaskResult(respBody []byte) (*relaycommon.TaskInfo, e
|
|||||||
case "pending", "queued":
|
case "pending", "queued":
|
||||||
taskResult.Status = model.TaskStatusQueued
|
taskResult.Status = model.TaskStatusQueued
|
||||||
taskResult.Progress = "10%"
|
taskResult.Progress = "10%"
|
||||||
case "processing":
|
case "processing", "running":
|
||||||
taskResult.Status = model.TaskStatusInProgress
|
taskResult.Status = model.TaskStatusInProgress
|
||||||
taskResult.Progress = "50%"
|
taskResult.Progress = "50%"
|
||||||
case "succeeded":
|
case "succeeded":
|
||||||
@@ -251,3 +282,30 @@ func (a *TaskAdaptor) ParseTaskResult(respBody []byte) (*relaycommon.TaskInfo, e
|
|||||||
|
|
||||||
return &taskResult, nil
|
return &taskResult, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *TaskAdaptor) ConvertToOpenAIVideo(originTask *model.Task) ([]byte, error) {
|
||||||
|
var dResp responseTask
|
||||||
|
if err := json.Unmarshal(originTask.Data, &dResp); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "unmarshal doubao task data failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
openAIVideo := dto.NewOpenAIVideo()
|
||||||
|
openAIVideo.ID = originTask.TaskID
|
||||||
|
openAIVideo.TaskID = originTask.TaskID
|
||||||
|
openAIVideo.Status = originTask.Status.ToVideoStatus()
|
||||||
|
openAIVideo.SetProgressStr(originTask.Progress)
|
||||||
|
openAIVideo.SetMetadata("url", dResp.Content.VideoURL)
|
||||||
|
openAIVideo.CreatedAt = originTask.CreatedAt
|
||||||
|
openAIVideo.CompletedAt = originTask.UpdatedAt
|
||||||
|
openAIVideo.Model = originTask.Properties.OriginModelName
|
||||||
|
|
||||||
|
if dResp.Status == "failed" {
|
||||||
|
openAIVideo.Error = &dto.OpenAIVideoError{
|
||||||
|
Message: "task failed",
|
||||||
|
Code: "failed",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonData, _ := common.Marshal(openAIVideo)
|
||||||
|
return jsonData, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ var ModelList = []string{
|
|||||||
"doubao-seedance-1-0-pro-250528",
|
"doubao-seedance-1-0-pro-250528",
|
||||||
"doubao-seedance-1-0-lite-t2v",
|
"doubao-seedance-1-0-lite-t2v",
|
||||||
"doubao-seedance-1-0-lite-i2v",
|
"doubao-seedance-1-0-lite-i2v",
|
||||||
|
"doubao-seedance-1-5-pro-251215",
|
||||||
}
|
}
|
||||||
|
|
||||||
var ChannelName = "doubao-video"
|
var ChannelName = "doubao-video"
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ func GetTaskAdaptor(platform constant.TaskPlatform) channel.TaskAdaptor {
|
|||||||
return &taskvertex.TaskAdaptor{}
|
return &taskvertex.TaskAdaptor{}
|
||||||
case constant.ChannelTypeVidu:
|
case constant.ChannelTypeVidu:
|
||||||
return &taskVidu.TaskAdaptor{}
|
return &taskVidu.TaskAdaptor{}
|
||||||
case constant.ChannelTypeDoubaoVideo:
|
case constant.ChannelTypeDoubaoVideo, constant.ChannelTypeVolcEngine:
|
||||||
return &taskdoubao.TaskAdaptor{}
|
return &taskdoubao.TaskAdaptor{}
|
||||||
case constant.ChannelTypeSora, constant.ChannelTypeOpenAI:
|
case constant.ChannelTypeSora, constant.ChannelTypeOpenAI:
|
||||||
return &tasksora.TaskAdaptor{}
|
return &tasksora.TaskAdaptor{}
|
||||||
|
|||||||
Reference in New Issue
Block a user