From c7fe43821328b84bcab7ebf1d8dbeb39a412a305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=96=8C?= <259278618@qq.com> Date: Wed, 29 Jul 2026 09:31:13 +0800 Subject: [PATCH] 1 --- common/util.go | 2 +- short_drama.db | Bin 462848 -> 462848 bytes shortdrama/service/episode_service.go | 76 +++++------------------ shortdrama/service/generation_service.go | 26 ++++---- 4 files changed, 29 insertions(+), 75 deletions(-) diff --git a/common/util.go b/common/util.go index fab2a78..cc93a94 100644 --- a/common/util.go +++ b/common/util.go @@ -98,7 +98,7 @@ func processField(name string, def map[string]any, input map[string]any) (any, e rawVal, exists := input[name] if !exists { if required { - return nil, fmt.Errorf("'%s' is required", name) + return nil, fmt.Errorf("%s", def["description"]) } if dflt, ok := def["default"]; ok { return convertDefault(dflt, fieldType), nil diff --git a/short_drama.db b/short_drama.db index 89b7d7a00a07b74b5cbd90fa9466596ebed26526..42d29cfe2607bf0edd57d2369ed458cadd8e6e48 100644 GIT binary patch delta 10755 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 delta 10570 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 diff --git a/shortdrama/service/episode_service.go b/shortdrama/service/episode_service.go index a13e34f..9c7fb4b 100644 --- a/shortdrama/service/episode_service.go +++ b/shortdrama/service/episode_service.go @@ -1238,7 +1238,6 @@ func buildCharacterGuide(charNames []string, chars []*entity.Character, labelOf // extractAndSaveEntities 从镜头数组中提取演员/场景/道具,去重后写入数据库。 // 如果同 drama 下已存在同名记录,跳过插入(避免重复)。 -// 描述信息从镜头的 event 画面描述中提取,保证是视觉/外观描述。 func extractAndSaveEntities(ctx context.Context, dramaId int64, shots []domain.Shot) { if len(shots) == 0 { return @@ -1247,39 +1246,22 @@ func extractAndSaveEntities(ctx context.Context, dramaId int64, shots []domain.S charSet := make(map[string]bool) sceneSet := make(map[string]bool) propSet := make(map[string]bool) - // name → []event 片段 - charEvents := make(map[string][]string) - sceneEvents := make(map[string][]string) - propEvents := make(map[string][]string) for _, sh := range shots { for _, c := range sh.Characters { if c == "" { continue } - if !charSet[c] { - charSet[c] = true - } - if sh.Event != "" { - charEvents[c] = append(charEvents[c], sh.Event) - } + charSet[c] = true } if sh.Scene != "" { sceneSet[sh.Scene] = true - if sh.Event != "" { - sceneEvents[sh.Scene] = append(sceneEvents[sh.Scene], sh.Event) - } } for _, p := range sh.Props { if p == "" { continue } - if !propSet[p] { - propSet[p] = true - } - if sh.Event != "" { - propEvents[p] = append(propEvents[p], sh.Event) - } + propSet[p] = true } } @@ -1312,43 +1294,17 @@ func extractAndSaveEntities(ctx context.Context, dramaId int64, shots []domain.S return false } - buildDesc := func(events []string) string { - seen := make(map[string]bool) - var parts []string - for _, e := range events { - if e == "" || seen[e] { - continue - } - seen[e] = true - parts = append(parts, e) - if len(parts) >= 3 { - break - } - } - if len(parts) == 0 { - return "" - } - result := strings.Join(parts, ";") - runes := []rune(result) - if len(runes) > 300 { - result = string(runes[:300]) + "……" - } - return result - } - now := time.Now().Format("2006-01-02 15:04:05") for name := range charSet { if existName(existingChars, name) { continue } - desc := buildDesc(charEvents[name]) _, _ = g.DB().Model(consts.TableNameCharacter).Ctx(ctx).Data(g.Map{ - "drama_id": dramaId, - "name": name, - "description": desc, - "created_at": now, - "updated_at": now, + "drama_id": dramaId, + "name": name, + "created_at": now, + "updated_at": now, }).Insert() } @@ -1356,13 +1312,11 @@ func extractAndSaveEntities(ctx context.Context, dramaId int64, shots []domain.S if existName(existingScenes, name) { continue } - desc := buildDesc(sceneEvents[name]) _, _ = g.DB().Model(consts.TableNameScene).Ctx(ctx).Data(g.Map{ - "drama_id": dramaId, - "name": name, - "description": desc, - "created_at": now, - "updated_at": now, + "drama_id": dramaId, + "name": name, + "created_at": now, + "updated_at": now, }).Insert() } @@ -1370,13 +1324,11 @@ func extractAndSaveEntities(ctx context.Context, dramaId int64, shots []domain.S if existName(existingProps, name) { continue } - desc := buildDesc(propEvents[name]) _, _ = g.DB().Model(consts.TableNameProp).Ctx(ctx).Data(g.Map{ - "drama_id": dramaId, - "name": name, - "description": desc, - "created_at": now, - "updated_at": now, + "drama_id": dramaId, + "name": name, + "created_at": now, + "updated_at": now, }).Insert() } } diff --git a/shortdrama/service/generation_service.go b/shortdrama/service/generation_service.go index d63e1b5..02b9ce5 100644 --- a/shortdrama/service/generation_service.go +++ b/shortdrama/service/generation_service.go @@ -4,6 +4,7 @@ import ( "context" "encoding/base64" "encoding/json" + "errors" "fmt" "io" "math" @@ -71,7 +72,17 @@ func (s *generationService) GenerateEpisode(ctx context.Context, dramaId, epId i if videoCfg.ApiKey == "" || videoCfg.BaseUrl == "" || videoCfg.ModelName == "" { return fmt.Errorf("video model not configured") } - // 客户身份:余额检查并预扣费 + + // ============ 检查待生成任务的 media 文件是否存在 ============ + if !continueIfMissing { + if missingNames := checkTaskMediaExistence(ctx, epId); len(missingNames) > 0 { + return errors.New("至少需要包含一个人物形象") + } + } else { + rebuildTasksMedia(ctx, epId) + } + + // 客户身份:余额检查并预扣费(放在 media 检查之后,确认可生成再扣费) if r := g.RequestFromCtx(ctx); r != nil { if role := r.GetCtxVar("role").String(); role == "customer" { userId := r.GetCtxVar("userId").Int64() @@ -100,15 +111,6 @@ func (s *generationService) GenerateEpisode(ctx context.Context, dramaId, epId i g.Log().Infof(ctx, "预加载引用数据: %d个演员, %d个场景, %d个道具, %d个引用", len(genCtx2.Characters), len(genCtx2.Scenes), len(genCtx2.Props), len(genCtx2.OrderedRefs)) - // ============ 检查待生成任务的 media 文件是否存在 ============ - if !continueIfMissing { - if missingNames := checkTaskMediaExistence(ctx, epId); len(missingNames) > 0 { - return fmt.Errorf("missing_character_media:%s", strings.Join(missingNames, ",")) - } - } else { - rebuildTasksMedia(ctx, epId) - } - genCtx := agent.WithDramaID(ctx, d.Id) segDurs := calcSegDurs(d.EpisodeDuration, videoCfg.ModelConfig) @@ -2125,7 +2127,7 @@ func (s *generationService) submitVideoTask(ctx context.Context, d *entity.Drama taskId, requestJSON, err := submitVideoGenRequest(ctx, modelCfg.ApiKey, modelCfg.BaseUrl, modelCfg.ModelName, prompt, negativePrompt, refURLs, effectiveDur, d.Resolution, d.AspectRatio, modelCfg.Schema, seed, segIdx, genTaskId, ep.Id, d.Title, ep.Title, modelCfg.SchemaMapping) if err != nil { - return "", "", fmt.Errorf("video composition request failed: %w", err) + return "", "", fmt.Errorf("%s", err) } if taskId == "" { @@ -2225,7 +2227,7 @@ func submitVideoGenRequest(ctx context.Context, apiKey, baseURL, modelName, prom bodyDef, _ := nested(vs, "body").(map[string]any) body, err := common.BuildSchemaRequest(bodyDef, input) if err != nil { - return "", "", fmt.Errorf("build request body failed: %w", err) + return "", "", fmt.Errorf("%s", err) } if body == nil { body = map[string]any{}