支持Midjourney视频任务和图片编辑

This commit is contained in:
iszcz
2025-06-30 22:31:12 +08:00
parent d389befc9e
commit 660180ea1b
12 changed files with 1111 additions and 1 deletions

View File

@@ -22,6 +22,8 @@ const (
MjActionPan = "PAN" MjActionPan = "PAN"
MjActionSwapFace = "SWAP_FACE" MjActionSwapFace = "SWAP_FACE"
MjActionUpload = "UPLOAD" MjActionUpload = "UPLOAD"
MjActionVideo = "VIDEO"
MjActionEdits = "EDITS"
) )
var MidjourneyModel2Action = map[string]string{ var MidjourneyModel2Action = map[string]string{
@@ -41,4 +43,6 @@ var MidjourneyModel2Action = map[string]string{
"mj_pan": MjActionPan, "mj_pan": MjActionPan,
"swap_face": MjActionSwapFace, "swap_face": MjActionSwapFace,
"mj_upload": MjActionUpload, "mj_upload": MjActionUpload,
"mj_video": MjActionVideo,
"mj_edits": MjActionEdits,
} }

View File

@@ -57,6 +57,8 @@ type MidjourneyDto struct {
StartTime int64 `json:"startTime"` StartTime int64 `json:"startTime"`
FinishTime int64 `json:"finishTime"` FinishTime int64 `json:"finishTime"`
ImageUrl string `json:"imageUrl"` ImageUrl string `json:"imageUrl"`
VideoUrl string `json:"videoUrl"`
VideoUrls []ImgUrls `json:"videoUrls"`
Status string `json:"status"` Status string `json:"status"`
Progress string `json:"progress"` Progress string `json:"progress"`
FailReason string `json:"failReason"` FailReason string `json:"failReason"`
@@ -65,6 +67,10 @@ type MidjourneyDto struct {
Properties *Properties `json:"properties"` Properties *Properties `json:"properties"`
} }
type ImgUrls struct {
Url string `json:"url"`
}
type MidjourneyStatus struct { type MidjourneyStatus struct {
Status int `json:"status"` Status int `json:"status"`
} }

1041
i18n/zh-cn.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -14,6 +14,8 @@ type Midjourney struct {
StartTime int64 `json:"start_time" gorm:"index"` StartTime int64 `json:"start_time" gorm:"index"`
FinishTime int64 `json:"finish_time" gorm:"index"` FinishTime int64 `json:"finish_time" gorm:"index"`
ImageUrl string `json:"image_url"` ImageUrl string `json:"image_url"`
VideoUrl string `json:"video_url"`
VideoUrls string `json:"video_urls"`
Status string `json:"status" gorm:"type:varchar(20);index"` Status string `json:"status" gorm:"type:varchar(20);index"`
Progress string `json:"progress" gorm:"type:varchar(30);index"` Progress string `json:"progress" gorm:"type:varchar(30);index"`
FailReason string `json:"fail_reason"` FailReason string `json:"fail_reason"`

View File

@@ -29,6 +29,8 @@ const (
RelayModeMidjourneyShorten RelayModeMidjourneyShorten
RelayModeSwapFace RelayModeSwapFace
RelayModeMidjourneyUpload RelayModeMidjourneyUpload
RelayModeMidjourneyVideo
RelayModeMidjourneyEdits
RelayModeAudioSpeech // tts RelayModeAudioSpeech // tts
RelayModeAudioTranscription // whisper RelayModeAudioTranscription // whisper
@@ -105,6 +107,10 @@ func Path2RelayModeMidjourney(path string) int {
relayMode = RelayModeMidjourneyUpload relayMode = RelayModeMidjourneyUpload
} else if strings.HasSuffix(path, "/mj/submit/imagine") { } else if strings.HasSuffix(path, "/mj/submit/imagine") {
relayMode = RelayModeMidjourneyImagine relayMode = RelayModeMidjourneyImagine
} else if strings.HasSuffix(path, "/mj/submit/video") {
relayMode = RelayModeMidjourneyVideo
} else if strings.HasSuffix(path, "/mj/submit/edits") {
relayMode = RelayModeMidjourneyEdits
} else if strings.HasSuffix(path, "/mj/submit/blend") { } else if strings.HasSuffix(path, "/mj/submit/blend") {
relayMode = RelayModeMidjourneyBlend relayMode = RelayModeMidjourneyBlend
} else if strings.HasSuffix(path, "/mj/submit/describe") { } else if strings.HasSuffix(path, "/mj/submit/describe") {

View File

@@ -106,6 +106,9 @@ func RelayMidjourneyNotify(c *gin.Context) *dto.MidjourneyResponse {
midjourneyTask.StartTime = midjRequest.StartTime midjourneyTask.StartTime = midjRequest.StartTime
midjourneyTask.FinishTime = midjRequest.FinishTime midjourneyTask.FinishTime = midjRequest.FinishTime
midjourneyTask.ImageUrl = midjRequest.ImageUrl midjourneyTask.ImageUrl = midjRequest.ImageUrl
midjourneyTask.VideoUrl = midjRequest.VideoUrl
videoUrlsStr, _ := json.Marshal(midjRequest.VideoUrls)
midjourneyTask.VideoUrls = string(videoUrlsStr)
midjourneyTask.Status = midjRequest.Status midjourneyTask.Status = midjRequest.Status
midjourneyTask.FailReason = midjRequest.FailReason midjourneyTask.FailReason = midjRequest.FailReason
err = midjourneyTask.Update() err = midjourneyTask.Update()
@@ -136,6 +139,9 @@ func coverMidjourneyTaskDto(c *gin.Context, originTask *model.Midjourney) (midjo
} else { } else {
midjourneyTask.ImageUrl = originTask.ImageUrl midjourneyTask.ImageUrl = originTask.ImageUrl
} }
if originTask.VideoUrl != "" {
midjourneyTask.VideoUrl = originTask.VideoUrl
}
midjourneyTask.Status = originTask.Status midjourneyTask.Status = originTask.Status
midjourneyTask.FailReason = originTask.FailReason midjourneyTask.FailReason = originTask.FailReason
midjourneyTask.Action = originTask.Action midjourneyTask.Action = originTask.Action
@@ -148,6 +154,13 @@ func coverMidjourneyTaskDto(c *gin.Context, originTask *model.Midjourney) (midjo
midjourneyTask.Buttons = buttons midjourneyTask.Buttons = buttons
} }
} }
if originTask.VideoUrls != "" {
var videoUrls []dto.ImgUrls
err := json.Unmarshal([]byte(originTask.VideoUrls), &videoUrls)
if err == nil {
midjourneyTask.VideoUrls = videoUrls
}
}
if originTask.Properties != "" { if originTask.Properties != "" {
var properties dto.Properties var properties dto.Properties
err := json.Unmarshal([]byte(originTask.Properties), &properties) err := json.Unmarshal([]byte(originTask.Properties), &properties)
@@ -391,6 +404,9 @@ func RelayMidjourneySubmit(c *gin.Context, relayMode int) *dto.MidjourneyRespons
} }
relayMode = relayconstant.RelayModeMidjourneyChange relayMode = relayconstant.RelayModeMidjourneyChange
} }
if relayMode == relayconstant.RelayModeMidjourneyVideo {
midjRequest.Action = constant.MjActionVideo
}
if relayMode == relayconstant.RelayModeMidjourneyImagine { //绘画任务,此类任务可重复 if relayMode == relayconstant.RelayModeMidjourneyImagine { //绘画任务,此类任务可重复
if midjRequest.Prompt == "" { if midjRequest.Prompt == "" {
@@ -399,6 +415,8 @@ func RelayMidjourneySubmit(c *gin.Context, relayMode int) *dto.MidjourneyRespons
midjRequest.Action = constant.MjActionImagine midjRequest.Action = constant.MjActionImagine
} else if relayMode == relayconstant.RelayModeMidjourneyDescribe { //按图生文任务,此类任务可重复 } else if relayMode == relayconstant.RelayModeMidjourneyDescribe { //按图生文任务,此类任务可重复
midjRequest.Action = constant.MjActionDescribe midjRequest.Action = constant.MjActionDescribe
} else if relayMode == relayconstant.RelayModeMidjourneyEdits { //编辑任务,此类任务可重复
midjRequest.Action = constant.MjActionEdits
} else if relayMode == relayconstant.RelayModeMidjourneyShorten { //缩短任务此类任务可重复plus only } else if relayMode == relayconstant.RelayModeMidjourneyShorten { //缩短任务此类任务可重复plus only
midjRequest.Action = constant.MjActionShorten midjRequest.Action = constant.MjActionShorten
} else if relayMode == relayconstant.RelayModeMidjourneyBlend { //绘画任务,此类任务可重复 } else if relayMode == relayconstant.RelayModeMidjourneyBlend { //绘画任务,此类任务可重复
@@ -433,6 +451,14 @@ func RelayMidjourneySubmit(c *gin.Context, relayMode int) *dto.MidjourneyRespons
//} //}
mjId = midjRequest.TaskId mjId = midjRequest.TaskId
midjRequest.Action = constant.MjActionModal midjRequest.Action = constant.MjActionModal
} else if relayMode == relayconstant.RelayModeMidjourneyVideo {
midjRequest.Action = constant.MjActionVideo
if midjRequest.TaskId == "" {
return service.MidjourneyErrorWrapper(constant.MjRequestError, "task_id_is_required")
} else if midjRequest.Action == "" {
return service.MidjourneyErrorWrapper(constant.MjRequestError, "action_is_required")
}
mjId = midjRequest.TaskId
} }
originTask := model.GetByMJId(userId, mjId) originTask := model.GetByMJId(userId, mjId)

View File

@@ -102,6 +102,8 @@ func registerMjRouterGroup(relayMjRouter *gin.RouterGroup) {
relayMjRouter.POST("/submit/simple-change", controller.RelayMidjourney) relayMjRouter.POST("/submit/simple-change", controller.RelayMidjourney)
relayMjRouter.POST("/submit/describe", controller.RelayMidjourney) relayMjRouter.POST("/submit/describe", controller.RelayMidjourney)
relayMjRouter.POST("/submit/blend", controller.RelayMidjourney) relayMjRouter.POST("/submit/blend", controller.RelayMidjourney)
relayMjRouter.POST("/submit/edits", controller.RelayMidjourney)
relayMjRouter.POST("/submit/video", controller.RelayMidjourney)
relayMjRouter.POST("/notify", controller.RelayMidjourney) relayMjRouter.POST("/notify", controller.RelayMidjourney)
relayMjRouter.GET("/task/:id/fetch", controller.RelayMidjourney) relayMjRouter.GET("/task/:id/fetch", controller.RelayMidjourney)
relayMjRouter.GET("/task/:id/image-seed", controller.RelayMidjourney) relayMjRouter.GET("/task/:id/image-seed", controller.RelayMidjourney)

View File

@@ -3,7 +3,6 @@ package service
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"github.com/gin-gonic/gin"
"io" "io"
"log" "log"
"net/http" "net/http"
@@ -15,6 +14,8 @@ import (
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/gin-gonic/gin"
) )
func CoverActionToModelName(mjAction string) string { func CoverActionToModelName(mjAction string) string {
@@ -38,6 +39,10 @@ func GetMjRequestModel(relayMode int, midjRequest *dto.MidjourneyRequest) (strin
switch relayMode { switch relayMode {
case relayconstant.RelayModeMidjourneyImagine: case relayconstant.RelayModeMidjourneyImagine:
action = constant.MjActionImagine action = constant.MjActionImagine
case relayconstant.RelayModeMidjourneyVideo:
action = constant.MjActionVideo
case relayconstant.RelayModeMidjourneyEdits:
action = constant.MjActionEdits
case relayconstant.RelayModeMidjourneyDescribe: case relayconstant.RelayModeMidjourneyDescribe:
action = constant.MjActionDescribe action = constant.MjActionDescribe
case relayconstant.RelayModeMidjourneyBlend: case relayconstant.RelayModeMidjourneyBlend:

View File

@@ -231,7 +231,9 @@ var defaultModelPrice = map[string]float64{
"dall-e-3": 0.04, "dall-e-3": 0.04,
"imagen-3.0-generate-002": 0.03, "imagen-3.0-generate-002": 0.03,
"gpt-4-gizmo-*": 0.1, "gpt-4-gizmo-*": 0.1,
"mj_video": 0.8,
"mj_imagine": 0.1, "mj_imagine": 0.1,
"mj_edits": 0.1,
"mj_variation": 0.1, "mj_variation": 0.1,
"mj_reroll": 0.1, "mj_reroll": 0.1,
"mj_blend": 0.1, "mj_blend": 0.1,

View File

@@ -194,6 +194,18 @@ const LogsTable = () => {
{t('放大')} {t('放大')}
</Tag> </Tag>
); );
case 'VIDEO':
return (
<Tag color='orange' size='large' shape='circle' prefixIcon={<Video size={14} />}>
{t('视频')}
</Tag>
);
case 'EDITS':
return (
<Tag color='orange' size='large' shape='circle' prefixIcon={<Video size={14} />}>
{t('编辑')}
</Tag>
);
case 'VARIATION': case 'VARIATION':
return ( return (
<Tag color='purple' size='large' shape='circle' prefixIcon={<Shuffle size={14} />}> <Tag color='purple' size='large' shape='circle' prefixIcon={<Shuffle size={14} />}>

View File

@@ -139,6 +139,8 @@ const EditChannel = (props) => {
localModels = [ localModels = [
'swap_face', 'swap_face',
'mj_imagine', 'mj_imagine',
'mj_video',
'mj_edits',
'mj_variation', 'mj_variation',
'mj_reroll', 'mj_reroll',
'mj_blend', 'mj_blend',

View File

@@ -73,6 +73,8 @@ const EditTagModal = (props) => {
localModels = [ localModels = [
'swap_face', 'swap_face',
'mj_imagine', 'mj_imagine',
'mj_video',
'mj_edits',
'mj_variation', 'mj_variation',
'mj_reroll', 'mj_reroll',
'mj_blend', 'mj_blend',