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
Commit
aa2f027d
authored
Nov 14, 2025
by
feitianbubu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: add hailuo i2v fl2v r2v
parent
c297f42c
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
86 additions
and
74 deletions
+86
-74
relay/channel/task/hailuo/adaptor.go
+9
-64
relay/channel/task/hailuo/constants.go
+7
-2
relay/channel/task/hailuo/models.go
+54
-6
relay/common/relay_info.go
+16
-2
No files found.
relay/channel/task/hailuo/adaptor.go
View file @
aa2f027d
...
@@ -22,6 +22,7 @@ import (
...
@@ -22,6 +22,7 @@ import (
"github.com/QuantumNous/new-api/service"
"github.com/QuantumNous/new-api/service"
)
)
// https://platform.minimaxi.com/docs/api-reference/video-generation-intro
type
TaskAdaptor
struct
{
type
TaskAdaptor
struct
{
ChannelType
int
ChannelType
int
apiKey
string
apiKey
string
...
@@ -84,7 +85,7 @@ func (a *TaskAdaptor) DoResponse(c *gin.Context, resp *http.Response, info *rela
...
@@ -84,7 +85,7 @@ func (a *TaskAdaptor) DoResponse(c *gin.Context, resp *http.Response, info *rela
}
}
_
=
resp
.
Body
.
Close
()
_
=
resp
.
Body
.
Close
()
var
hResp
TextTo
VideoResponse
var
hResp
VideoResponse
if
err
:=
json
.
Unmarshal
(
responseBody
,
&
hResp
);
err
!=
nil
{
if
err
:=
json
.
Unmarshal
(
responseBody
,
&
hResp
);
err
!=
nil
{
taskErr
=
service
.
TaskErrorWrapper
(
errors
.
Wrapf
(
err
,
"body: %s"
,
responseBody
),
"unmarshal_response_body_failed"
,
http
.
StatusInternalServerError
)
taskErr
=
service
.
TaskErrorWrapper
(
errors
.
Wrapf
(
err
,
"body: %s"
,
responseBody
),
"unmarshal_response_body_failed"
,
http
.
StatusInternalServerError
)
return
return
...
@@ -136,86 +137,28 @@ func (a *TaskAdaptor) GetChannelName() string {
...
@@ -136,86 +137,28 @@ func (a *TaskAdaptor) GetChannelName() string {
return
ChannelName
return
ChannelName
}
}
func
(
a
*
TaskAdaptor
)
convertToRequestPayload
(
req
*
relaycommon
.
TaskSubmitReq
)
(
*
TextTo
VideoRequest
,
error
)
{
func
(
a
*
TaskAdaptor
)
convertToRequestPayload
(
req
*
relaycommon
.
TaskSubmitReq
)
(
*
VideoRequest
,
error
)
{
modelConfig
:=
GetModelConfig
(
req
.
Model
)
modelConfig
:=
GetModelConfig
(
req
.
Model
)
if
!
contains
(
ModelList
,
req
.
Model
)
{
return
nil
,
fmt
.
Errorf
(
"unsupported model: %s"
,
req
.
Model
)
}
duration
:=
DefaultDuration
duration
:=
DefaultDuration
if
req
.
Duration
>
0
{
if
req
.
Duration
>
0
{
duration
=
req
.
Duration
duration
=
req
.
Duration
}
}
if
!
containsInt
(
modelConfig
.
SupportedDurations
,
duration
)
{
return
nil
,
fmt
.
Errorf
(
"duration %d is not supported by model %s, supported durations: %v"
,
duration
,
req
.
Model
,
modelConfig
.
SupportedDurations
)
}
resolution
:=
modelConfig
.
DefaultResolution
resolution
:=
modelConfig
.
DefaultResolution
if
req
.
Size
!=
""
{
if
req
.
Size
!=
""
{
resolution
=
a
.
parseResolutionFromSize
(
req
.
Size
,
modelConfig
)
resolution
=
a
.
parseResolutionFromSize
(
req
.
Size
,
modelConfig
)
}
}
if
!
contains
(
modelConfig
.
SupportedResolutions
,
resolution
)
{
videoRequest
:=
&
VideoRequest
{
return
nil
,
fmt
.
Errorf
(
"resolution %s is not supported by model %s, supported resolutions: %v"
,
resolution
,
req
.
Model
,
modelConfig
.
SupportedResolutions
)
}
hailuoReq
:=
&
TextToVideoRequest
{
Model
:
req
.
Model
,
Model
:
req
.
Model
,
Prompt
:
req
.
Prompt
,
Prompt
:
req
.
Prompt
,
Duration
:
&
duration
,
Duration
:
&
duration
,
Resolution
:
resolution
,
Resolution
:
resolution
,
}
}
if
err
:=
req
.
UnmarshalMetadata
(
&
videoRequest
);
err
!=
nil
{
promptOptimizer
:=
DefaultPromptOptimizer
return
nil
,
errors
.
Wrap
(
err
,
"unmarshal metadata to video request failed"
)
hailuoReq
.
PromptOptimizer
=
&
promptOptimizer
metadata
:=
req
.
Metadata
if
metadata
!=
nil
{
metadataBytes
,
err
:=
json
.
Marshal
(
metadata
)
if
err
!=
nil
{
return
nil
,
errors
.
Wrap
(
err
,
"marshal metadata failed"
)
}
var
metadataMap
map
[
string
]
interface
{}
if
err
:=
json
.
Unmarshal
(
metadataBytes
,
&
metadataMap
);
err
!=
nil
{
return
nil
,
errors
.
Wrap
(
err
,
"unmarshal metadata failed"
)
}
if
val
,
exists
:=
metadataMap
[
"prompt_optimizer"
];
exists
{
if
boolVal
,
ok
:=
val
.
(
bool
);
ok
{
hailuoReq
.
PromptOptimizer
=
&
boolVal
}
}
if
modelConfig
.
HasFastPretreatment
{
if
val
,
exists
:=
metadataMap
[
"fast_pretreatment"
];
exists
{
if
boolVal
,
ok
:=
val
.
(
bool
);
ok
{
hailuoReq
.
FastPretreatment
=
&
boolVal
}
}
}
if
val
,
exists
:=
metadataMap
[
"callback_url"
];
exists
{
if
strVal
,
ok
:=
val
.
(
string
);
ok
{
hailuoReq
.
CallbackURL
=
strVal
}
}
if
val
,
exists
:=
metadataMap
[
"aigc_watermark"
];
exists
{
if
boolVal
,
ok
:=
val
.
(
bool
);
ok
{
hailuoReq
.
AigcWatermark
=
&
boolVal
}
}
}
if
req
.
HasImage
()
{
return
nil
,
fmt
.
Errorf
(
"image input is not supported by hailuo video generation"
)
}
}
return
hailuoReq
,
nil
return
videoRequest
,
nil
}
}
func
(
a
*
TaskAdaptor
)
parseResolutionFromSize
(
size
string
,
modelConfig
ModelConfig
)
string
{
func
(
a
*
TaskAdaptor
)
parseResolutionFromSize
(
size
string
,
modelConfig
ModelConfig
)
string
{
...
@@ -226,6 +169,8 @@ func (a *TaskAdaptor) parseResolutionFromSize(size string, modelConfig ModelConf
...
@@ -226,6 +169,8 @@ func (a *TaskAdaptor) parseResolutionFromSize(size string, modelConfig ModelConf
return
Resolution768P
return
Resolution768P
case
strings
.
Contains
(
size
,
"720"
)
:
case
strings
.
Contains
(
size
,
"720"
)
:
return
Resolution720P
return
Resolution720P
case
strings
.
Contains
(
size
,
"512"
)
:
return
Resolution512P
default
:
default
:
return
modelConfig
.
DefaultResolution
return
modelConfig
.
DefaultResolution
}
}
...
...
relay/channel/task/hailuo/constants.go
View file @
aa2f027d
...
@@ -6,9 +6,14 @@ const (
...
@@ -6,9 +6,14 @@ const (
var
ModelList
=
[]
string
{
var
ModelList
=
[]
string
{
"MiniMax-Hailuo-2.3"
,
"MiniMax-Hailuo-2.3"
,
"MiniMax-Hailuo-2.3-Fast"
,
"MiniMax-Hailuo-02"
,
"MiniMax-Hailuo-02"
,
"T2V-01-Director"
,
"T2V-01-Director"
,
"T2V-01"
,
"T2V-01"
,
"I2V-01-Director"
,
"I2V-01-live"
,
"I2V-01"
,
"S2V-01"
,
}
}
const
(
const
(
...
@@ -35,6 +40,7 @@ const (
...
@@ -35,6 +40,7 @@ const (
)
)
const
(
const
(
Resolution512P
=
"512P"
Resolution720P
=
"720P"
Resolution720P
=
"720P"
Resolution768P
=
"768P"
Resolution768P
=
"768P"
Resolution1080P
=
"1080P"
Resolution1080P
=
"1080P"
...
@@ -42,6 +48,5 @@ const (
...
@@ -42,6 +48,5 @@ const (
const
(
const
(
DefaultDuration
=
6
DefaultDuration
=
6
DefaultResolution
=
Resolution768P
DefaultResolution
=
Resolution720P
DefaultPromptOptimizer
=
true
)
)
relay/channel/task/hailuo/models.go
View file @
aa2f027d
package
hailuo
package
hailuo
type
TextToVideoRequest
struct
{
type
SubjectReference
struct
{
Type
string
`json:"type"`
// Subject type, currently only supports "character"
Image
[]
string
`json:"image"`
// Array of subject reference images (currently only supports single image)
}
type
VideoRequest
struct
{
Model
string
`json:"model"`
Model
string
`json:"model"`
Prompt
string
`json:"prompt
"`
Prompt
string
`json:"prompt,omitempty
"`
PromptOptimizer
*
bool
`json:"prompt_optimizer,omitempty"`
PromptOptimizer
*
bool
`json:"prompt_optimizer,omitempty"`
FastPretreatment
*
bool
`json:"fast_pretreatment,omitempty"`
FastPretreatment
*
bool
`json:"fast_pretreatment,omitempty"`
Duration
*
int
`json:"duration,omitempty"`
Duration
*
int
`json:"duration,omitempty"`
Resolution
string
`json:"resolution,omitempty"`
Resolution
string
`json:"resolution,omitempty"`
CallbackURL
string
`json:"callback_url,omitempty"`
CallbackURL
string
`json:"callback_url,omitempty"`
AigcWatermark
*
bool
`json:"aigc_watermark,omitempty"`
AigcWatermark
*
bool
`json:"aigc_watermark,omitempty"`
FirstFrameImage
string
`json:"first_frame_image,omitempty"`
// For image-to-video and start-end-to-video
LastFrameImage
string
`json:"last_frame_image,omitempty"`
// For start-end-to-video
SubjectReference
[]
SubjectReference
`json:"subject_reference,omitempty"`
// For subject-reference-to-video
}
}
type
TextTo
VideoResponse
struct
{
type
VideoResponse
struct
{
TaskID
string
`json:"task_id"`
TaskID
string
`json:"task_id"`
BaseResp
BaseResp
`json:"base_resp"`
BaseResp
BaseResp
`json:"base_resp"`
}
}
...
@@ -81,11 +89,19 @@ func GetModelConfig(model string) ModelConfig {
...
@@ -81,11 +89,19 @@ func GetModelConfig(model string) ModelConfig {
HasPromptOptimizer
:
true
,
HasPromptOptimizer
:
true
,
HasFastPretreatment
:
true
,
HasFastPretreatment
:
true
,
},
},
"MiniMax-Hailuo-2.3-Fast"
:
{
Name
:
"MiniMax-Hailuo-2.3-Fast"
,
DefaultResolution
:
Resolution768P
,
SupportedDurations
:
[]
int
{
6
,
10
},
SupportedResolutions
:
[]
string
{
Resolution768P
,
Resolution1080P
},
HasPromptOptimizer
:
true
,
HasFastPretreatment
:
true
,
},
"MiniMax-Hailuo-02"
:
{
"MiniMax-Hailuo-02"
:
{
Name
:
"MiniMax-Hailuo-02"
,
Name
:
"MiniMax-Hailuo-02"
,
DefaultResolution
:
Resolution768P
,
DefaultResolution
:
Resolution768P
,
SupportedDurations
:
[]
int
{
6
,
10
},
SupportedDurations
:
[]
int
{
6
,
10
},
SupportedResolutions
:
[]
string
{
Resolution768P
,
Resolution1080P
},
SupportedResolutions
:
[]
string
{
Resolution
512P
,
Resolution
768P
,
Resolution1080P
},
HasPromptOptimizer
:
true
,
HasPromptOptimizer
:
true
,
HasFastPretreatment
:
true
,
HasFastPretreatment
:
true
,
},
},
...
@@ -105,6 +121,38 @@ func GetModelConfig(model string) ModelConfig {
...
@@ -105,6 +121,38 @@ func GetModelConfig(model string) ModelConfig {
HasPromptOptimizer
:
true
,
HasPromptOptimizer
:
true
,
HasFastPretreatment
:
false
,
HasFastPretreatment
:
false
,
},
},
"I2V-01-Director"
:
{
Name
:
"I2V-01-Director"
,
DefaultResolution
:
Resolution720P
,
SupportedDurations
:
[]
int
{
6
},
SupportedResolutions
:
[]
string
{
Resolution720P
,
Resolution1080P
},
HasPromptOptimizer
:
true
,
HasFastPretreatment
:
false
,
},
"I2V-01-live"
:
{
Name
:
"I2V-01-live"
,
DefaultResolution
:
Resolution720P
,
SupportedDurations
:
[]
int
{
6
},
SupportedResolutions
:
[]
string
{
Resolution720P
,
Resolution1080P
},
HasPromptOptimizer
:
true
,
HasFastPretreatment
:
false
,
},
"I2V-01"
:
{
Name
:
"I2V-01"
,
DefaultResolution
:
Resolution720P
,
SupportedDurations
:
[]
int
{
6
},
SupportedResolutions
:
[]
string
{
Resolution720P
,
Resolution1080P
},
HasPromptOptimizer
:
true
,
HasFastPretreatment
:
false
,
},
"S2V-01"
:
{
Name
:
"S2V-01"
,
DefaultResolution
:
Resolution720P
,
SupportedDurations
:
[]
int
{
6
},
SupportedResolutions
:
[]
string
{
Resolution720P
},
HasPromptOptimizer
:
true
,
HasFastPretreatment
:
false
,
},
}
}
if
config
,
exists
:=
configs
[
model
];
exists
{
if
config
,
exists
:=
configs
[
model
];
exists
{
...
@@ -113,9 +161,9 @@ func GetModelConfig(model string) ModelConfig {
...
@@ -113,9 +161,9 @@ func GetModelConfig(model string) ModelConfig {
return
ModelConfig
{
return
ModelConfig
{
Name
:
model
,
Name
:
model
,
DefaultResolution
:
Resolution720P
,
DefaultResolution
:
DefaultResolution
,
SupportedDurations
:
[]
int
{
6
},
SupportedDurations
:
[]
int
{
6
},
SupportedResolutions
:
[]
string
{
Resolution720P
},
SupportedResolutions
:
[]
string
{
DefaultResolution
},
HasPromptOptimizer
:
true
,
HasPromptOptimizer
:
true
,
HasFastPretreatment
:
false
,
HasFastPretreatment
:
false
,
}
}
...
...
relay/common/relay_info.go
View file @
aa2f027d
...
@@ -498,11 +498,11 @@ type TaskSubmitReq struct {
...
@@ -498,11 +498,11 @@ type TaskSubmitReq struct {
Metadata
map
[
string
]
interface
{}
`json:"metadata,omitempty"`
Metadata
map
[
string
]
interface
{}
`json:"metadata,omitempty"`
}
}
func
(
t
TaskSubmitReq
)
GetPrompt
()
string
{
func
(
t
*
TaskSubmitReq
)
GetPrompt
()
string
{
return
t
.
Prompt
return
t
.
Prompt
}
}
func
(
t
TaskSubmitReq
)
HasImage
()
bool
{
func
(
t
*
TaskSubmitReq
)
HasImage
()
bool
{
return
len
(
t
.
Images
)
>
0
return
len
(
t
.
Images
)
>
0
}
}
...
@@ -537,6 +537,20 @@ func (t *TaskSubmitReq) UnmarshalJSON(data []byte) error {
...
@@ -537,6 +537,20 @@ func (t *TaskSubmitReq) UnmarshalJSON(data []byte) error {
return
nil
return
nil
}
}
func
(
t
*
TaskSubmitReq
)
UnmarshalMetadata
(
v
any
)
error
{
metadata
:=
t
.
Metadata
if
metadata
!=
nil
{
metadataBytes
,
err
:=
json
.
Marshal
(
metadata
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"marshal metadata failed: %w"
,
err
)
}
err
=
json
.
Unmarshal
(
metadataBytes
,
v
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"unmarshal metadata to target failed: %w"
,
err
)
}
}
return
nil
}
type
TaskInfo
struct
{
type
TaskInfo
struct
{
Code
int
`json:"code"`
Code
int
`json:"code"`
...
...
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