feat(*): 生图与视频工作台 - 新增独立生成流程并整合平台配置
This commit is contained in:
1 parent
4c1d2b4012
commit
1f3f2c6020
69 files changed
+7108
-87
No files matched your search
@@ -2,6 +2,7 @@ package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -317,6 +318,202 @@ func publicTaskInputJSON(raw string) string {
|
||||
if len(public) == 0 {
|
||||
return ""
|
||||
}
|
||||
if workbench := publicWorkbenchInput(input); workbench != nil {
|
||||
public["workbench"] = workbench
|
||||
}
|
||||
data, _ := json.Marshal(public)
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func publicWorkbenchInput(input map[string]any) map[string]any {
|
||||
metadata, ok := input["metadata"].(map[string]any)
|
||||
if !ok || metadata["source"] != "workbench" {
|
||||
return nil
|
||||
}
|
||||
kind := strings.TrimSpace(stringValue(metadata["workbenchKind"]))
|
||||
if kind != model.WorkbenchKindImage && kind != model.WorkbenchKindVideo {
|
||||
return nil
|
||||
}
|
||||
snapshot, _ := metadata["workbench"].(map[string]any)
|
||||
result := map[string]any{
|
||||
"kind": kind,
|
||||
"parameters": publicWorkbenchParameters(kind, snapshot, input),
|
||||
}
|
||||
if toolID := strings.TrimSpace(stringValue(metadata["workbenchToolId"])); toolID != "" {
|
||||
result["toolId"] = toolID
|
||||
}
|
||||
if presetID := strings.TrimSpace(stringValue(metadata["workbenchPresetId"])); presetID != "" {
|
||||
result["presetId"] = presetID
|
||||
}
|
||||
result["references"] = publicWorkbenchReferences(snapshot["references"], input)
|
||||
return result
|
||||
}
|
||||
|
||||
func publicWorkbenchParameters(kind string, snapshot, input map[string]any) map[string]any {
|
||||
parameters, _ := snapshot["parameters"].(map[string]any)
|
||||
config, _ := input["config"].(map[string]any)
|
||||
result := map[string]any{}
|
||||
if kind == model.WorkbenchKindImage {
|
||||
copyWorkbenchTextParameter(result, "size", parameters["size"])
|
||||
copyWorkbenchTextParameter(result, "quality", parameters["quality"])
|
||||
if result["size"] == nil {
|
||||
copyWorkbenchTextParameter(result, "size", config["size"])
|
||||
}
|
||||
if result["quality"] == nil {
|
||||
copyWorkbenchTextParameter(result, "quality", config["quality"])
|
||||
}
|
||||
if value, ok := workbenchInteger(parameters["count"], 20); ok {
|
||||
result["count"] = value
|
||||
} else if value, ok := workbenchInteger(config["count"], 20); ok {
|
||||
result["count"] = value
|
||||
}
|
||||
return result
|
||||
}
|
||||
if value, ok := workbenchInteger(parameters["seconds"], 3600); ok {
|
||||
result["seconds"] = value
|
||||
} else if value, ok := workbenchInteger(config["videoSeconds"], 3600); ok {
|
||||
result["seconds"] = value
|
||||
}
|
||||
copyWorkbenchTextParameter(result, "ratio", firstWorkbenchValue(parameters["ratio"], config["size"]))
|
||||
copyWorkbenchTextParameter(result, "resolution", firstWorkbenchValue(parameters["resolution"], config["vquality"]))
|
||||
if value, ok := workbenchBoolean(firstWorkbenchValue(parameters["generateAudio"], config["videoGenerateAudio"])); ok {
|
||||
result["generateAudio"] = value
|
||||
}
|
||||
if value, ok := workbenchBoolean(firstWorkbenchValue(parameters["watermark"], config["videoWatermark"])); ok {
|
||||
result["watermark"] = value
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func firstWorkbenchValue(values ...any) any {
|
||||
for _, value := range values {
|
||||
if value != nil {
|
||||
return value
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyWorkbenchTextParameter(target map[string]any, key string, value any) {
|
||||
text, ok := value.(string)
|
||||
text = strings.TrimSpace(text)
|
||||
if ok && text != "" && len(text) <= 64 && !strings.Contains(text, "://") && !strings.HasPrefix(strings.ToLower(text), "data:") {
|
||||
target[key] = text
|
||||
}
|
||||
}
|
||||
|
||||
func workbenchInteger(value any, max int) (int, bool) {
|
||||
var parsed int
|
||||
switch number := value.(type) {
|
||||
case float64:
|
||||
parsed = int(number)
|
||||
if float64(parsed) != number {
|
||||
return 0, false
|
||||
}
|
||||
case int:
|
||||
parsed = number
|
||||
case int64:
|
||||
parsed = int(number)
|
||||
if int64(parsed) != number {
|
||||
return 0, false
|
||||
}
|
||||
case json.Number:
|
||||
var err error
|
||||
parsed, err = strconv.Atoi(number.String())
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
case string:
|
||||
var err error
|
||||
parsed, err = strconv.Atoi(strings.TrimSpace(number))
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
default:
|
||||
return 0, false
|
||||
}
|
||||
return parsed, parsed >= 1 && parsed <= max
|
||||
}
|
||||
|
||||
func workbenchBoolean(value any) (bool, bool) {
|
||||
switch flag := value.(type) {
|
||||
case bool:
|
||||
return flag, true
|
||||
case string:
|
||||
if strings.EqualFold(flag, "true") {
|
||||
return true, true
|
||||
}
|
||||
if strings.EqualFold(flag, "false") {
|
||||
return false, true
|
||||
}
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func publicWorkbenchReferences(snapshotReferences any, input map[string]any) []map[string]any {
|
||||
result := make([]map[string]any, 0, 20)
|
||||
appendReference := func(value map[string]any, fallbackKind string) {
|
||||
if len(result) >= 20 {
|
||||
return
|
||||
}
|
||||
resourceID := strings.TrimSpace(stringValue(value["resourceId"]))
|
||||
if resourceID == "" {
|
||||
storageKey := strings.TrimSpace(stringValue(value["storageKey"]))
|
||||
if strings.HasPrefix(storageKey, "resource:") {
|
||||
resourceID = strings.TrimPrefix(storageKey, "resource:")
|
||||
}
|
||||
}
|
||||
if resourceID == "" || strings.ContainsAny(resourceID, "/\\?#") {
|
||||
return
|
||||
}
|
||||
kind := strings.TrimSpace(stringValue(value["kind"]))
|
||||
if kind != "image" && kind != "video" && kind != "audio" {
|
||||
kind = fallbackKind
|
||||
}
|
||||
if kind != "image" && kind != "video" && kind != "audio" {
|
||||
return
|
||||
}
|
||||
item := map[string]any{"resourceId": resourceID, "kind": kind}
|
||||
role := strings.TrimSpace(stringValue(value["role"]))
|
||||
if role == "reference" || role == "first_frame" || role == "last_frame" {
|
||||
item["role"] = role
|
||||
}
|
||||
if slotKey := safeWorkbenchSlotKey(stringValue(value["slotKey"])); slotKey != "" {
|
||||
item["slotKey"] = slotKey
|
||||
}
|
||||
result = append(result, item)
|
||||
}
|
||||
if values, ok := snapshotReferences.([]any); ok {
|
||||
for _, value := range values {
|
||||
if item, ok := value.(map[string]any); ok {
|
||||
appendReference(item, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(result) > 0 {
|
||||
return result
|
||||
}
|
||||
for _, group := range []struct{ key, kind string }{{"referenceImages", "image"}, {"referenceVideos", "video"}, {"referenceAudios", "audio"}} {
|
||||
values, _ := input[group.key].([]any)
|
||||
for _, value := range values {
|
||||
if item, ok := value.(map[string]any); ok {
|
||||
appendReference(item, group.kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func safeWorkbenchSlotKey(value string) string {
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" || len(value) > 64 {
|
||||
return ""
|
||||
}
|
||||
for _, character := range value {
|
||||
if (character >= 'a' && character <= 'z') || (character >= 'A' && character <= 'Z') || (character >= '0' && character <= '9') || character == '_' || character == '-' {
|
||||
continue
|
||||
}
|
||||
return ""
|
||||
}
|
||||
return value
|
||||
}
|
||||
Reference in new issue
Block a user