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 89b7d7a..42d29cf 100644 Binary files a/short_drama.db and b/short_drama.db differ 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{}