优化脚本

This commit is contained in:
Azmat@qq.com
2026-08-28 14:45:38 +08:00
parent 849b14a0f6
commit c0a0b9603b
37 changed files with 541 additions and 1893 deletions
+59 -17
View File
@@ -137,15 +137,21 @@ _PERSONA_KEY_BY_LABEL = {label: key for key, label in PERSONA_LABELS.items()}
NARRATION_CHARS_PER_SECOND = 5.2
NARRATION_CHARS_PER_SECOND_MIN = 4.3
NARRATION_CHARS_HARD_CAP = 78
VISUAL_CHARS_MIN = 72
# 故事板下线后,visual 是出片模型唯一的画面依据,门槛从「够写一句」抬到「够当导演说明书」
VISUAL_CHARS_MIN = 110
SHOT_BEATS_MIN = 3
BEAT_SPAN_RE = re.compile(
r"(?P<start>\d{1,2})\s*[-–—~到至]\s*(?P<end>\d{1,2})\s*(?:s|秒)?\s*[:]",
re.IGNORECASE,
)
# 景别(拍多大)与 机位/运镜(怎么拍)分开把关:出片模型两样都要,缺一样画面就会平。
_SHOT_SIZE_MARKERS = (
"特写", "近景", "中近景", "中景", "全景", "远景", "胸上", "过肩",
"手持", "跟拍", "俯拍", "仰拍", "推近", "拉远", "",
"大特写", "特写", "近景", "中近景", "中景", "全景", "远景", "胸上", "过肩",
)
_CAMERA_MOVE_MARKERS = (
"手持", "跟拍", "跟随", "俯拍", "仰拍", "平视", "推近", "推进", "推镜",
"拉远", "拉回", "拉镜", "摇镜", "横摇", "移镜", "平移", "环绕", "升降",
"固定机位", "定机位", "固定镜头", "过肩", "第一人称", "越肩",
)
_MINOR_CHARACTER_RE = re.compile(
r"(?:婴儿|宝宝|宝贝|幼儿|儿童|小孩|小朋友|未成年|男童|女童|baby|toddler|infant)",
@@ -501,20 +507,47 @@ _CREATIVE_DIRECTION = """
输出前自问:遮住商品名后,这是不是仍然像一个真实的人在讲自己刚遇到的一件事?
如果像广告口号,重写得更具体、更有立场。
### visual 必须写成「导演说明书」,不是一句画面摘要
每个 segment 的 `visual` 采用下面的层级;这不是给用户看的散文,而是会原样交给故事板和视频模型的执行指令:
### visual 必须写成「导演说明书」,因为它是出片模型唯一的画面依据
**这条最重要:流程里没有分镜图了。** 你写的 `visual` 不会再经过一张关键帧图去"翻译"
而是**连同角色/商品/场景参考图一起,原样交给视频生成模型**。你没写清楚的,模型就自己编;
你写含糊的,画面就含糊。所以 `visual` 要写到「一个不认识这个商品的摄影师,照着就能拍」的程度。
每个 segment 的 `visual` 采用下面的层级,逐栏写满:
```
【本镜任务】这一段要让观众看懂的变化或悬念。
【光线氛围】光源方向与性质(窗光/顶光/台灯/逆光);色温冷暖;明暗对比;整体色调。全片各镜保持一致。
【声音】台词/旁白状态;音效;背景音乐;字幕。没有就写「无」;没有配乐写「无配乐,仅同期声」。
【画面内容】
0-3s:景别;机位;运镜;人物/商品动作;情绪或信息变化。
3-8s:景别;机位;运镜;手与商品的空间关系;可见细节。
8-12s:景别;机位;运镜;动作结果或卖点证据。
0-3s:景别;机位高度与角度;运镜;主体在画面中的位置;具体动作;情绪或信息变化。
3-8s:景别;机位;运镜;手与商品的空间关系(哪只手、握哪里、从哪个方向入画);可见细节。
8-12s:景别;机位;运镜;动作结果或卖点证据(看得见的变化:颜色/质地/形态/前后差别)
12-15s:景别;机位;运镜;反应/悬念/自然收束。
```
每条秒级分镜都要明确写出 **景别、机位、运镜、动作、信息变化** 五项中的至少四项。
输入如果是 `【镜头 01】` 导演分镜稿,把原稿的景别、机位、运镜、动作、表情、音效、背景音乐、字幕、备注折进对应栏,不要压成一句画面摘要。
同一角色、商品、场景的外观一律引用 entities 里的既定设定,不在每一镜随意换发型、服装、包装、光线或地点。
每条秒级分镜必须同时写出这五项,不能省:
1. **景别** —— 大特写/特写/近景/中近景/中景/全景(15 秒内至少切两次,别一个景别拍到底)
2. **机位** —— 高度与角度:平视/俯拍/仰拍/过肩/桌面视角
3. **运镜** —— 手持跟拍/推近/拉远/横摇/环绕/固定机位(**每镜至少出现一个运镜词**,否则画面会死)
4. **动作** —— 具体到肢体:谁、用哪只手、对什么、做了什么动作,动作要连贯可拍
5. **信息变化** —— 这 3–5 秒里画面上多了什么、变了什么
### 只写拍得出来的东西
- **禁止抽象词**:「展示商品」「呈现质感」「体现高级感」「氛围到位」「传递温暖」——
这些不是画面,是评价。要写成「杯壁上的水珠顺着往下滑」「她眉头松开,肩膀塌下来」。
- **禁止心理描写**:模型拍不出「她内心很纠结」,要写「她拿起又放下,手指在包装边缘停了两秒」。
- **禁止画面里出现文字**:不要写字幕、花字、标题、价格贴片、UI、弹窗、对比图表;
商品包装上原有的真实文字除外。
- **禁止一镜内跨场景/跨时间蒙太奇**:15 秒是**一个连续的动作链**,同一地点、同一光线、
同一套衣服。要换环境就换到下一镜,并在 entity_refs 里换成另一个 scene。
### 一致性靠文字锁死
同一角色、商品、场景的外观一律引用 entities 里的既定设定;不在每一镜随意换发型、服装、
包装、光线、地点或色调。每一镜的【光线氛围】要和相邻镜衔接得上(同一场戏不能上一镜暖黄台灯、
下一镜冷白日光)。商品的用法要符合物理常识:热饮有蒸汽、液体会流动、包装要先打开才能取出内容物。
输入如果是 `【镜头 01】` 导演分镜稿,把原稿的景别、机位、运镜、动作、表情、音效、背景音乐、字幕、备注
折进对应栏,不要压成一句画面摘要。
"""
# 这些句式几乎总会让首屏像模板广告。只作为生成后的最后一道门,不替代模型的创作判断。
@@ -698,12 +731,16 @@ def build_agent_messages(
speech_floor = narration_floor(SEGMENT_DURATION_MAX)
speech_cap = narration_limit(SEGMENT_DURATION_MAX)
beats_line = (
f"【秒级分镜】每个 {SEGMENT_DURATION_MAX} 秒场必须拆成 3–5 个分镜,visual 必须按「导演说明书」写成多行:"
"先写【本镜任务】、【声音】、【画面内容】,再写秒级分镜;"
f"每条格式`0-3s:景别;机位;运镜;谁在做什么;信息变化`,最后一条接到 {SEGMENT_DURATION_MAX}s。"
"每条写清手/商品/容器的空间关系和真实用法"
"(茶=热水+蒸汽+茶汤变色,禁止茶包丢进冷白开;手从真实方向入画,禁止悬浮肢体)。"
"禁止一句空画面撑满 15 秒。允许另给 beats 数组,后端会折进 visual。\n"
f"【秒级分镜】流程里没有分镜图了,visual 会**原样交给出片模型**,写多细画面就有多准。"
f"每个 {SEGMENT_DURATION_MAX} 秒场必须拆成 3–5 个分镜,visual 按「导演说明书」写成多行:"
"先写【本镜任务】、【光线氛围】(光源方向/色温/明暗/色调,各镜保持一致)、【声音】、【画面内容】,再写秒级分镜;"
f"每条格式`0-3s:景别;机位;运镜;主体位置与具体动作;信息变化`,最后一条接到 {SEGMENT_DURATION_MAX}s。"
"每条必须带景别(15 秒内至少切两次)+ 机位 + 运镜词(手持/跟拍/推近/拉远/环绕/固定机位,缺了画面会死),"
"并写清哪只手、从哪个方向入画、握商品哪里,以及真实用法"
"(茶=热水+蒸汽+茶汤变色,禁止茶包丢进冷白开;禁止悬浮肢体、商品凭空出现)。"
"只写拍得出来的东西:禁止「展示商品/呈现质感/体现高级感」这类评价词,禁止心理描写,"
"禁止画面里出现字幕花字标题价签,禁止一镜内跨场景跨时间。"
f"禁止一句空画面撑满 {SEGMENT_DURATION_MAX} 秒。允许另给 beats 数组,后端会折进 visual。\n"
)
if fmt == "oral":
writing_line = (
@@ -1025,6 +1062,11 @@ def assert_intra_shot_beats(seg: dict, index: int, duration: int) -> None:
markers = [mark for mark in _SHOT_SIZE_MARKERS if mark in visual]
if len(set(markers)) < 2:
raise ValueError(f"{index + 1} 镜 15 秒内至少要切两次景别,并写进秒级分镜")
# 故事板下线后没有关键帧兜底,机位/运镜只能靠这段文字告诉出片模型
if not any(mark in visual for mark in _CAMERA_MOVE_MARKERS):
raise ValueError(
f"{index + 1} 镜必须写清机位与运镜(手持/跟拍/推近/拉远/环绕/固定机位…),否则出片只会拍成呆板静止画面"
)
# 模型每次生成都可能换字段名(scene/screenDescription/visual…、dialogue/lines/caption…),