fix: 修复工作流执行记录创建与静音模式约束
- 执行记录仅在合法 execId 时写入,查询失败时返回错误 - 字幕构建改为词级精确对齐并增加比例兜底,避免整句被吞 - 静音模式下从转写与段级 prompt 双重杜绝口播/字幕/口型 - 清理静音事件描述中的说话类动词
This commit is contained in:
@@ -108,6 +108,10 @@ func ScriptTranscribeLambda(ctx context.Context, input any) (any, error) {
|
||||
} else {
|
||||
systemPrompt += shotDurationConstraintPrompt(maxSeg)
|
||||
}
|
||||
// 静音模式硬约束:从转写源头杜绝对白/旁白/开口说话,后续清洗只做兜底
|
||||
if noSpeech {
|
||||
systemPrompt += noSpeechSystemPromptConstraint()
|
||||
}
|
||||
|
||||
info, err := gateway.GetModelInfoById(ctx, &gateway.GetModelInfoByIdReq{ModelId: nodeInput.Config.ModelConfig.ModelId})
|
||||
if err != nil {
|
||||
@@ -148,6 +152,8 @@ func ScriptTranscribeLambda(ctx context.Context, input any) (any, error) {
|
||||
for i := range shots {
|
||||
shots[i].Dialogue = ""
|
||||
shots[i].Narration = ""
|
||||
// event 里的说话动词仍会经 事件:%s 块写进分段 prompt,导致视频模型生成口型/字幕,需确定性清洗
|
||||
shots[i].Event = cleanSpeechVerbs(shots[i].Event)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,6 +170,7 @@ func ScriptTranscribeLambda(ctx context.Context, input any) (any, error) {
|
||||
FlatRefs: refsItem,
|
||||
Seed: nodeInput.Global.ExecutionId % 1000000,
|
||||
NegativePrompt: nodeInput.Config.NegativePrompt,
|
||||
NoSpeech: noSpeech,
|
||||
}
|
||||
data, err := processor.Call(ctx, "split_shots_pipeline", gconv.Map(args))
|
||||
if err != nil {
|
||||
@@ -320,6 +327,32 @@ func splitDialogueNarration(s string) (dialogue, narration string) {
|
||||
}
|
||||
}
|
||||
|
||||
// cleanSpeechVerbs 静音模式下清洗 event 中的说话动词:把常见说话/喊叫/对白表达替换为空串,
|
||||
// 避免"事件:%s"块里残留的说话动词让视频模型生成口型/字幕。仅做机械兜底,硬约束在转写提示词。
|
||||
// NewReplacer 按最长匹配替换,故先列含"说/喊"的非开口语义词做保护(no-op,如"说明""呐喊"),
|
||||
// 再列开口表达;"叫"语义多变(呼叫/叫停/叫住),不做裸清洗以免误伤。
|
||||
func cleanSpeechVerbs(s string) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
repl := strings.NewReplacer(
|
||||
"说明", "说明", "解说", "解说", "据说", "据说", "传说", "传说", "小说", "小说",
|
||||
"学说", "学说", "说法", "说法", "说服", "说服", "呐喊", "呐喊",
|
||||
"开口说话", "", "开口说", "", "开口", "",
|
||||
"说道:", "", "说道:", "", "说道", "",
|
||||
"说着", "", "说话", "", "讲话", "", "台词", "", "对白", "",
|
||||
"喊道:", "", "喊道:", "", "喊道", "", "大喊", "", "喊叫", "",
|
||||
"叫道:", "", "叫道:", "", "叫道", "", "叫到", "", "叫喊", "",
|
||||
"回答", "", "答道", "", "回应", "", "回话", "",
|
||||
"问道:", "", "问道:", "", "问道", "",
|
||||
"念叨", "", "嘟囔", "", "嘀咕", "", "自言自语", "",
|
||||
"呼唤", "", "呼叫", "", "叫唤", "", "惊叫", "", "惨叫", "",
|
||||
"说:", "", "说:", "", "说", "",
|
||||
"喊:", "", "喊:", "", "喊", "",
|
||||
)
|
||||
return strings.TrimSpace(repl.Replace(s))
|
||||
}
|
||||
|
||||
// splitList 按常见分隔符拆分人名/道具列表(兼容中英文顿号、逗号、分号、"和""及"等)。
|
||||
func splitList(s string) []string {
|
||||
repl := strings.NewReplacer("、", "|", ",", "|", ",", "|", ";", "|", ";", "|", "和", "|", "及", "|", "&", "|", "/", "|", " ", "|")
|
||||
@@ -339,3 +372,13 @@ func shotDurationConstraintPrompt(maxSeg int) string {
|
||||
}
|
||||
return fmt.Sprintf("\n\n单个镜头时长不超过 %d 秒:每镜的 startTime 与 endTime 之差必须 ≤ %d 秒。", maxSeg, maxSeg)
|
||||
}
|
||||
|
||||
// noSpeechSystemPromptConstraint 静音模式的转写硬约束:要求模型从源头就不产出对白/旁白/说话动词,
|
||||
// 后续 noSpeech 清洗(清空台词旁白 + cleanSpeechVerbs)只做机械兜底。
|
||||
func noSpeechSystemPromptConstraint() string {
|
||||
return "\n\n本片为静音模式,镜头里禁止任何声音类内容:\n" +
|
||||
"- 所有镜头禁止出现台词、旁白、画外音,narration 与 dialogue 一律留空、不要输出;\n" +
|
||||
"- 禁止角色开口说话,事件描述只能写无声的动作、表情、神态、场景变化,不要出现“说”“喊”“叫”“对白”“讲话”“开口”“问”“回答”“念叨”等说话类动词;\n" +
|
||||
"- characters 只是出镜角色名,不代表开口说话;\n" +
|
||||
"- 视频不包含口型动作与字幕,据此调整分镜描写。"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user