From f66954ee400c12d8acfac4f9e8cb57414ea3badf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E6=96=8C?= <259278618@qq.com>
Date: Mon, 20 Jul 2026 14:23:01 +0800
Subject: [PATCH] 1
---
short_drama.db | Bin 462848 -> 462848 bytes
shortdrama/service/config_service.go | 6 +---
shortdrama/service/drama_service.go | 49 ++++++++++++++++++++++-----
3 files changed, 42 insertions(+), 13 deletions(-)
diff --git a/short_drama.db b/short_drama.db
index 7701ec07ca59f77d94783e5b529deb911e514996..b31df93f009381d8237fb123a71a44456e8c0a0f 100644
GIT binary patch
delta 6389
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
delta 4967
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
C{+*=&
diff --git a/shortdrama/service/config_service.go b/shortdrama/service/config_service.go
index bea1083..8d37693 100644
--- a/shortdrama/service/config_service.go
+++ b/shortdrama/service/config_service.go
@@ -335,13 +335,9 @@ func (s *configService) GetMergedConfig(ctx context.Context, userId int64, model
} else if modelType == "chat" {
merged.Temperature = 0.85
}
- // UserMaxTokens 仅 chat 模型有效(不超过系统上限,系统上限从 schema 解析)
+ // UserMaxTokens 从用户模型配置读取(仅 chat 模型)
if modelType == "chat" && userCfg.MaxTokens > 0 {
merged.MaxTokens = userCfg.MaxTokens
- sysMax := schemaMaxTokens(sysCfg.Schema)
- if merged.MaxTokens > sysMax && sysMax > 0 {
- merged.MaxTokens = sysMax
- }
}
return merged
}
diff --git a/shortdrama/service/drama_service.go b/shortdrama/service/drama_service.go
index 21d5cb7..f60004b 100644
--- a/shortdrama/service/drama_service.go
+++ b/shortdrama/service/drama_service.go
@@ -485,18 +485,24 @@ func (s *dramaService) generateOneSegment(ctx context.Context, d *entity.Drama,
// 调用模型前写入模型名称
_ = dao.GenerationTask.UpdateFields(ctx, taskId, g.Map{"model_name": videoCfg.ModelName})
- taskID, requestJSON, submitErr := s.submitVideoTask(ctx, d, ep, segIdx, segDur, segOutput.Scenes, videoRefs, firstFrameURL)
+ // 复用已有 task.script,只注入首帧参考 + 转换 base64,不再重新构建请求体
+ taskID, requestJSON, submitErr := s.submitFromExistingScript(ctx, taskId, videoCfg, firstFrameURL)
if submitErr != nil {
- g.Log().Errorf(ctx, "第%d段视频提交失败: %v", segIdx+1, submitErr)
- return submitErr
- } else {
- g.Log().Infof(ctx, "第%d集第%d段视频已提交(taskId=%s, duration=%ds)", ep.Index, segIdx+1, taskID, segDur)
+ // 回退到完整构建(task.script 可能为空)
+ g.Log().Warningf(ctx, "复用 task.script 提交失败,回退到完整构建: %v", submitErr)
+ taskID, requestJSON, submitErr = s.submitVideoTask(ctx, d, ep, segIdx, segDur, segOutput.Scenes, videoRefs, firstFrameURL)
+ if submitErr != nil {
+ g.Log().Errorf(ctx, "第%d段视频提交失败: %v", segIdx+1, submitErr)
+ return submitErr
+ }
}
+ g.Log().Infof(ctx, "第%d集第%d段视频已提交(taskId=%s, duration=%ds)", ep.Index, segIdx+1, taskID, segDur)
- // 更新 video_task_id、num_segments 和 script(含首帧参考)
+ // 更新 video_task_id、num_segments、duration 和 script(含首帧参考)
updateFields := g.Map{
"num_segments": numSegments,
"script": requestJSON,
+ "duration": segDur,
"updated_at": nil,
}
if taskID != "" {
@@ -1286,6 +1292,33 @@ func (s *dramaService) pollVideoTaskOnce(ctx context.Context, modelCfg *MergedMo
}
// ==================== Video Generation ====================
+// submitFromExistingScript 复用 task.script 提交视频任务,只注入首帧参考 + 转换 base64
+func (s *dramaService) submitFromExistingScript(ctx context.Context, taskId int64, modelCfg *MergedModelConfig, firstFrameURL string) (string, string, error) {
+ task, err := dao.GenerationTask.GetOne(ctx, taskId)
+ if err != nil || task == nil || task.Script == "" {
+ return "", "", fmt.Errorf("task.script 为空")
+ }
+
+ var bodyMap map[string]any
+ if err := json.Unmarshal([]byte(task.Script), &bodyMap); err != nil {
+ return "", "", fmt.Errorf("解析 task.script 失败: %w", err)
+ }
+
+ // 串行模式下注入首帧参考
+ if firstFrameURL != "" {
+ injectFirstFrame(bodyMap, modelCfg.Schema, firstFrameURL)
+ }
+
+ // 将修改后的 body(含文件路径)序列化,用于保存到 task.script
+ updatedBody, _ := json.Marshal(bodyMap)
+
+ // 复用 resubmitVideoTask 将文件路径转 base64 并提交 API
+ taskID, _, err := resubmitVideoTask(ctx, modelCfg.ApiKey, modelCfg.BaseUrl, modelCfg.Schema, updatedBody)
+ if err != nil {
+ return "", "", err
+ }
+ return taskID, string(updatedBody), nil
+}
// submitVideoTask 提交视频合成任务,返回 (taskID, requestBodyJSON, error)
// requestBodyJSON 是调用视频模型 API 时发送的完整请求体 JSON 字符串
@@ -1707,7 +1740,7 @@ func convertBodyMediaToBase64(body map[string]any) {
if refs, ok := input["reference_urls"].([]any); ok {
for i, r := range refs {
u, _ := r.(string)
- if u == "" || strings.HasPrefix(u, "http://") || strings.HasPrefix(u, "https://") || strings.HasPrefix(u, "data:") {
+ if u == "" || strings.HasPrefix(u, "http://") || strings.HasPrefix(u, "https://") {
continue
}
if b64, err := imageFileToBase64(u); err == nil {
@@ -1724,7 +1757,7 @@ func convertBodyMediaToBase64(body map[string]any) {
continue
}
u, _ := m["url"].(string)
- if u == "" || strings.HasPrefix(u, "http://") || strings.HasPrefix(u, "https://") || strings.HasPrefix(u, "data:") {
+ if u == "" || strings.HasPrefix(u, "http://") || strings.HasPrefix(u, "https://") {
continue
}
if b64, err := imageFileToBase64(u); err == nil {