diff --git a/short_drama.db b/short_drama.db index 7701ec0..b31df93 100644 Binary files a/short_drama.db and b/short_drama.db differ 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 {