Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
new-api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
0193018a
authored
Apr 02, 2026
by
Calcium-Ion
Committed by
GitHub
Apr 02, 2026
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #4042 from feitianbubu/pr/fe9713dcbf8795e127fbea2fcb1f3011da86ad54
新增seedance2.0视频接口支持
parents
41cd051e
dafc7618
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
47 additions
and
31 deletions
+47
-31
relay/channel/task/doubao/adaptor.go
+45
-31
relay/channel/task/doubao/constants.go
+2
-0
No files found.
relay/channel/task/doubao/adaptor.go
View file @
0193018a
...
...
@@ -5,6 +5,7 @@ import (
"fmt"
"io"
"net/http"
"strconv"
"time"
"github.com/QuantumNous/new-api/common"
...
...
@@ -13,12 +14,13 @@ import (
"github.com/QuantumNous/new-api/dto"
"github.com/QuantumNous/new-api/model"
"github.com/QuantumNous/new-api/relay/channel"
taskcommon
"github.com/QuantumNous/new-api/relay/channel/task/taskcommon"
"github.com/QuantumNous/new-api/relay/channel/task/taskcommon"
relaycommon
"github.com/QuantumNous/new-api/relay/common"
"github.com/QuantumNous/new-api/service"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
"github.com/samber/lo"
)
// ============================
...
...
@@ -26,35 +28,35 @@ import (
// ============================
type
ContentItem
struct
{
Type
string
`json:"type"`
// "text", "image_url" or "video"
Text
string
`json:"text,omitempty"`
// for text type
ImageURL
*
ImageURL
`json:"image_url,omitempty"`
// for image_url type
Video
*
VideoReference
`json:"video,omitempty"`
// for video (sample) type
Role
string
`json:"role,omitempty"`
// reference_image / first_frame / last_frame
Type
string
`json:"type,omitempty"`
Text
string
`json:"text,omitempty"`
ImageURL
*
MediaURL
`json:"image_url,omitempty"`
VideoURL
*
MediaURL
`json:"video_url,omitempty"`
AudioURL
*
MediaURL
`json:"audio_url,omitempty"`
Role
string
`json:"role,omitempty"`
}
type
ImageURL
struct
{
URL
string
`json:"url"`
}
type
VideoReference
struct
{
URL
string
`json:"url"`
// Draft video URL
type
MediaURL
struct
{
URL
string
`json:"url,omitempty"`
}
type
requestPayload
struct
{
Model
string
`json:"model"`
Content
[]
ContentItem
`json:"content"`
Content
[]
ContentItem
`json:"content
,omitempty
"`
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"`
ExecutionExpiresAfter
*
dto
.
IntValue
`json:"execution_expires_after,omitempty"`
GenerateAudio
*
dto
.
BoolValue
`json:"generate_audio,omitempty"`
Draft
*
dto
.
BoolValue
`json:"draft,omitempty"`
Tools
[]
struct
{
Type
string
`json:"type,omitempty"`
}
`json:"tools,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"`
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"`
}
...
...
@@ -76,10 +78,20 @@ type responseTask struct {
Ratio
string
`json:"ratio"`
FramesPerSecond
int
`json:"framespersecond"`
ServiceTier
string
`json:"service_tier"`
Tools
[]
struct
{
Type
string
`json:"type"`
}
`json:"tools"`
Usage
struct
{
CompletionTokens
int
`json:"completion_tokens"`
TotalTokens
int
`json:"total_tokens"`
ToolUsage
struct
{
WebSearch
int
`json:"web_search"`
}
`json:"tool_usage"`
}
`json:"usage"`
Error
struct
{
Code
string
`json:"code"`
Message
string
`json:"message"`
}
`json:"error"`
CreatedAt
int64
`json:"created_at"`
UpdatedAt
int64
`json:"updated_at"`
}
...
...
@@ -108,12 +120,12 @@ func (a *TaskAdaptor) ValidateRequestAndSetAction(c *gin.Context, info *relaycom
}
// BuildRequestURL constructs the upstream URL.
func
(
a
*
TaskAdaptor
)
BuildRequestURL
(
info
*
relaycommon
.
RelayInfo
)
(
string
,
error
)
{
func
(
a
*
TaskAdaptor
)
BuildRequestURL
(
_
*
relaycommon
.
RelayInfo
)
(
string
,
error
)
{
return
fmt
.
Sprintf
(
"%s/api/v3/contents/generations/tasks"
,
a
.
baseURL
),
nil
}
// BuildRequestHeader sets required headers.
func
(
a
*
TaskAdaptor
)
BuildRequestHeader
(
c
*
gin
.
Context
,
req
*
http
.
Request
,
info
*
relaycommon
.
RelayInfo
)
error
{
func
(
a
*
TaskAdaptor
)
BuildRequestHeader
(
_
*
gin
.
Context
,
req
*
http
.
Request
,
_
*
relaycommon
.
RelayInfo
)
error
{
req
.
Header
.
Set
(
"Content-Type"
,
"application/json"
)
req
.
Header
.
Set
(
"Accept"
,
"application/json"
)
req
.
Header
.
Set
(
"Authorization"
,
"Bearer "
+
a
.
apiKey
)
...
...
@@ -218,20 +230,12 @@ func (a *TaskAdaptor) convertToRequestPayload(req *relaycommon.TaskSubmitReq) (*
Content
:
[]
ContentItem
{},
}
// Add text prompt
if
req
.
Prompt
!=
""
{
r
.
Content
=
append
(
r
.
Content
,
ContentItem
{
Type
:
"text"
,
Text
:
req
.
Prompt
,
})
}
// Add images if present
if
req
.
HasImage
()
{
for
_
,
imgURL
:=
range
req
.
Images
{
r
.
Content
=
append
(
r
.
Content
,
ContentItem
{
Type
:
"image_url"
,
ImageURL
:
&
Image
URL
{
ImageURL
:
&
Media
URL
{
URL
:
imgURL
,
},
})
...
...
@@ -243,6 +247,16 @@ func (a *TaskAdaptor) convertToRequestPayload(req *relaycommon.TaskSubmitReq) (*
return
nil
,
errors
.
Wrap
(
err
,
"unmarshal metadata failed"
)
}
if
sec
,
_
:=
strconv
.
Atoi
(
req
.
Seconds
);
sec
>
0
{
r
.
Duration
=
lo
.
ToPtr
(
dto
.
IntValue
(
sec
))
}
r
.
Content
=
lo
.
Reject
(
r
.
Content
,
func
(
c
ContentItem
,
_
int
)
bool
{
return
c
.
Type
==
"text"
})
r
.
Content
=
append
(
r
.
Content
,
ContentItem
{
Type
:
"text"
,
Text
:
req
.
Prompt
,
})
return
&
r
,
nil
}
...
...
@@ -274,7 +288,7 @@ func (a *TaskAdaptor) ParseTaskResult(respBody []byte) (*relaycommon.TaskInfo, e
case
"failed"
:
taskResult
.
Status
=
model
.
TaskStatusFailure
taskResult
.
Progress
=
"100%"
taskResult
.
Reason
=
"task failed"
taskResult
.
Reason
=
resTask
.
Error
.
Message
default
:
// Unknown status, treat as processing
taskResult
.
Status
=
model
.
TaskStatusInProgress
...
...
@@ -302,8 +316,8 @@ func (a *TaskAdaptor) ConvertToOpenAIVideo(originTask *model.Task) ([]byte, erro
if
dResp
.
Status
==
"failed"
{
openAIVideo
.
Error
=
&
dto
.
OpenAIVideoError
{
Message
:
"task failed"
,
Code
:
"failed"
,
Message
:
dResp
.
Error
.
Message
,
Code
:
dResp
.
Error
.
Code
,
}
}
...
...
relay/channel/task/doubao/constants.go
View file @
0193018a
...
...
@@ -5,6 +5,8 @@ var ModelList = []string{
"doubao-seedance-1-0-lite-t2v"
,
"doubao-seedance-1-0-lite-i2v"
,
"doubao-seedance-1-5-pro-251215"
,
"doubao-seedance-2-0-260128"
,
"doubao-seedance-2-0-fast-260128"
,
}
var
ChannelName
=
"doubao-video"
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment