Files
digital-me-history/tools/build_woyanmo_lyrics_20shots.py
T
admin 0593ff7e62
nginx serve /uploads direct (audio speed) / patch-nginx (push) Failing after 1m34s
数字我 Digital Me:全量入库(大文件走 Git LFS)
2026-10-10 16:24:43 +08:00

326 lines
30 KiB
Python
Executable File
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from __future__ import annotations
from pathlib import Path
from docx import Document
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.shared import Inches, Pt
import build_woyanmo_docx as b
OUT = Path(r"D:\workspace\digital_me\artifacts\《我为你研墨》完整歌词脚本与20镜分镜提示词(每镜10秒).docx")
SHOTS = [
dict(n=1, section="Intro", title="不会写字的孤女", lyric="(研墨声)你杀了我祖父的那一年 / 我还不会写字",
beats=[("0–2秒", "黑场中先出现研墨声,烛火从暗处显出。"), ("2–6秒", "俯视缓推,幼年婉儿在掖庭矮桌前歪斜描红。"), ("6–10秒", "镜头停在握笔的小手与高墙长影,红簪成为唯一亮色。")],
subtitles="1.0–6.0秒「你杀了我祖父的那一年」;6.0–9.8秒「我还不会写字」",
prompt="开场黑场约1秒,只有细微研墨声。烛火渐亮,俯视机位从高耸暗红宫墙缓慢下推,揭示幼年上官婉儿穿暗蓝粗布囚衣、背对镜头伏在窄矮木桌前描红。她握笔生涩,纸上笔画歪斜;发髻一支朱砂红簪为唯一鲜明色。宫墙占画面七成以上,长影压住弱小人物。最后四秒镜头近乎静止,仅烛焰、衣袖和笔尖微动。",
transition="0.8秒叠化,歪斜墨迹溶入成年婉儿笔下端正诏书。"),
dict(n=2, section="Verse 1", title="替她写漂亮的诏书", lyric="如今我替你 把诏书写得漂亮",
beats=[("0–3秒", "成年婉儿伏案,镜头从诏书卷首缓慢推向执笔手。"), ("3–7秒", "笔锋稳定行进,字迹端整,武则天身影在后景虚化。"), ("7–10秒", "婉儿停笔半拍,烛光将她的脸切成明暗两半。")],
subtitles="1.0–9.5秒「如今我替你 把诏书写得漂亮」",
prompt="成年上官婉儿身着玄红唐代女官服,夜间宫室内伏案书写明黄诏书。镜头从诏书卷首极缓推向执笔右手,毛笔写出端整有力的墨字;画面后景仅保留晚年武则天模糊侧影与明黄衣色,不抢主体。右上烛光照亮婉儿半张脸,另一半隐入墨影。第七秒后停笔半拍,目光仍落在诏书上,情绪克制、专业、不可揣测。",
transition="笔尖悬停处硬切至下一镜的锋利落笔。"),
dict(n=3, section="Verse 1", title="每一笔都是锋芒", lyric="一笔一划 都是你要的锋芒",
beats=[("0–3秒", "微距笔尖悬于纸面,朱砂与墨色并置。"), ("3–7秒", "笔锋快速但稳定地压、行、提,形成一道锐利转折。"), ("7–10秒", "镜头沿笔画末端滑动,墨迹边缘缓慢渗入宣纸。")],
subtitles="1.0–9.5秒「一笔一划 都是你要的锋芒」",
prompt="微距特写毛笔、手指与宣纸,成年婉儿的手腕佩细银镯。笔尖先悬停,随后以清晰的压笔、行笔、提锋完成一道锐利而端正的墨色笔画,笔锋末端带少量朱砂红高光,象征权力锋芒。镜头沿新写成的笔画缓慢横移,展示墨色在纸纤维中细微晕开;手指结构稳定,笔杆与笔毫不变形。",
transition="墨迹晕染扩满画面,叠化成掖庭冷灰墙面。"),
dict(n=4, section="Verse 1", title="掖庭长大的罪臣之孙", lyric="掖庭里长大 罪臣的孙女",
beats=[("0–3秒", "远景展示门字形高墙与极小人物。"), ("3–7秒", "少女提灯穿过狭长廊道,步伐安静。"), ("7–10秒", "她停在门洞中央,灯火变弱,墙体继续压迫。")],
subtitles="1.0–5.0秒「掖庭里长大」;5.0–9.5秒「罪臣的孙女」",
prompt="高耸暗红宫墙围出狭窄门字形通道,冷灰空气中,少年上官婉儿穿素色旧衣,手提一盏小灯缓慢穿过。人物只占画面约8%,巨大墙体形成强烈压迫。镜头固定,仅做极轻缓推;她走至门洞中央停下,灯焰渐弱,烛泪沿灯烛下滑。无人出现,无夸张表演,以空间体量表现“罪臣孙女”的身份烙印。",
transition="灯焰焦外光斑溶成砚池中的暖金倒影。"),
dict(n=5, section="Verse 1", title="把恨磨成墨", lyric="我把恨 磨成了墨 / 一滴 不许它响",
beats=[("0–3秒", "俯拍砚台,墨锭缓慢画圆,水滴在上方凝结。"), ("3–6秒", "水滴无声落入墨池,扩散三圈涟漪。"), ("6–10秒", "墨气升起又散去,砚面恢复黑镜般平静。")],
subtitles="0.8–5.0秒「我把恨 磨成了墨」;5.0–9.8秒「一滴 不许它响」",
prompt="微距俯拍黑色砚台占画面九成,女子手持墨锭缓慢画圆研磨。一滴清水在画面上方凝结,第三秒无声落入墨池中央,扩散三圈细密涟漪;落墨瞬间只有极轻视觉震颤,不出现剧烈水花。水雾化成细长墨气升至画面三分之一,再缓缓散去。砚面映着虚化暖金烛斑,最后恢复黑镜般平静。",
transition="黑色墨面中央裂开一道竖痕,进入火宅与递笔的对照画面。"),
dict(n=6, section="Pre 1", title="恨与谢的分屏", lyric="该恨你 还是该谢你 / 你毁了我的家 又给了我笔",
beats=[("0–3秒", "左侧祖宅燃烧,右侧一支毛笔悬在少女面前。"), ("3–7秒", "少女左手握紧、右手接笔,中央墨痕向下滴落。"), ("7–10秒", "火焰爆裂与接笔动作同拍,画面轻震后定住。")],
subtitles="0.5–4.5秒「该恨你 还是该谢你」;4.5–9.8秒「你毁了我的家 又给了我笔」",
prompt="左右对称分屏构图。左屏为唐代上官府宅在夜色中燃烧,火焰舔过屋檐,少女剪影站在火前不动;右屏为宫室烛光下一支毛笔从画外递到少女面前,她迟疑后伸手接住。中央分隔线是一道竖直墨痕,第三秒开始向下滴墨。第七秒火焰轻微爆裂与指尖握住笔杆同步,双屏极轻震动后稳定。建议左右画面分别生成10秒,再后期合成。",
transition="中央墨痕向两侧晕开,覆盖火焰并化作宫城夜色。"),
dict(n=7, section="Chorus 1", title="为她研墨,也为自己活", lyric="我为你研墨 也为自己活 / 仇人的江山 我替她说",
beats=[("0–3秒", "砚面与研墨手势近景,婉儿倒影浮现。"), ("3–7秒", "镜头升起后拉,砚面转化为水墨宫城。"), ("7–10秒", "婉儿立于城楼俯瞰灯火,身影虽小却居于制高点。")],
subtitles="0.5–4.8秒「我为你研墨 也为自己活」;4.8–9.8秒「仇人的江山 我替她说」",
prompt="从俯拍砚面和研墨手势开始,黑色墨面映出成年婉儿克制的半脸倒影。镜头缓慢升起并后拉,砚池边缘自然转化为水墨大明宫城墙与宫阙,近景烛火连续变成万家灯火。后段婉儿背影立于最高城楼,玄红衣摆被风轻动,人物虽小却位于画面上三分之一制高点,俯瞰仇人的江山,表达她在权力中争取生存。",
transition="宫城灯火排列成棋盘格,俯视进入黑白棋局。"),
dict(n=8, section="Chorus 1", title="看不透的棋局", lyric="你看不透我 我也看不透我 / 这盘棋里 谁是谁的 因果",
beats=[("0–4秒", "墨镜中婉儿的脸一半清晰、一半被墨纹遮住。"), ("4–8秒", "画面叠化为棋盘,两双手分别落黑白子。"), ("8–10秒", "棋子落点泛起墨晕,两只手同时退出画面。")],
subtitles="0.5–4.5秒「你看不透我 我也看不透我」;4.5–9.8秒「这盘棋里 谁是谁的 因果」",
prompt="前四秒中近景:成年婉儿凝视砚中自己,现实半脸清晰,倒影半脸被流动墨纹遮住,目光冷静而困惑。随后以墨纹叠化成青玉棋盘俯拍,左侧婉儿纤白手戴银镯落白子,右侧年老帝王枯瘦手戴玉扳指落黑子。两枚棋子先后落盘,落点各泛一圈淡墨晕;最后两只手同时缓慢退出,只留下未完棋局。",
transition="棋盘墨晕旋转上升,变成掌心的墨色风旋。"),
dict(n=9, section="Chorus 1|间奏", title="掌上起风,婉儿落笔", lyric="(掌上起风 婉儿落笔)",
beats=[("0–3秒", "女子摊开手掌,掌心墨气聚拢。"), ("3–7秒", "墨气旋转三圈上升,另一只手在焦外蘸墨。"), ("7–10秒", "墨风散开,毛笔从上方落向宣纸,停在触纸一刻。")],
subtitles="1.0–9.0秒「(掌上起风 婉儿落笔)」;使用28pt淡灰括号体",
prompt="女子摊开的手掌占画面六成,掌心黑色墨气聚拢并形成缓慢旋转的风涡,连续旋转三圈后上升。另一只手在左侧焦外区域执笔蘸墨,右下烛光勾亮指尖边缘。第七秒墨风向两侧散开,画面上方一支毛笔缓慢落向宣纸;第十秒停在笔毫刚触纸的瞬间。手指自然稳定,无多余手指和肢体。",
transition="笔毫触纸硬切到帝王凝视婉儿书写的宫室。"),
dict(n=10, section="Verse 2", title="她只看字写得好不好", lyric="你不问我恨不恨 你只看我写得好不好",
beats=[("0–3秒", "婉儿书写近景,帝王在后景审视。"), ("3–7秒", "镜头横移至诏书,展示整齐字列与朱砂批记。"), ("7–10秒", "帝王手指轻点纸面,婉儿没有抬头。")],
subtitles="0.8–9.7秒「你不问我恨不恨 你只看我写得好不好」",
prompt="宫室夜景,中近景拍成年婉儿伏案书写,晚年武则天在后景虚化端坐,只露明黄衣袖和审视的侧影。镜头缓慢横移到诏书,展示端整墨字与少量朱砂批记。第七秒帝王枯瘦手指从画外伸入,轻点纸面某一行;婉儿笔尖停顿半拍但不抬头,继续书写。情绪是无声考核,不做争吵或夸张对峙。",
transition="镜头沿帝王指尖下移,进入纸边极小批注的微距。"),
dict(n=11, section="Verse 2", title="把心藏进小字号", lyric="我也学会了 把心 藏进批注的小字号",
beats=[("0–3秒", "极小字号批注在宣纸边缘逐行出现。"), ("3–7秒", "笔尖写到一个字时微停,墨迹化成短暂心形涟漪。"), ("7–10秒", "婉儿袖口遮住批注,诏书正文保持端正。")],
subtitles="0.8–9.7秒「我也学会了 把心 藏进批注的小字号」",
prompt="超近景拍宣纸边缘与纤细笔尖,诏书正文大字端正,边缘批注字号极小、密而整齐,不要求文字可辨读。婉儿写到一处时笔尖微停,墨面反光短暂形成近似心形的细小涟漪,随即恢复普通墨迹。后段她轻移玄色衣袖遮住批注区域,只留下公开正文。避免真实可读文字,强调“隐藏”而非魔幻发光。",
transition="玄色袖口掠过画面,叠化成长廊中搀扶帝王的玄衣背影。"),
dict(n=12, section="Verse 2", title="扶老帝王上朝", lyric="你老了 手也抖了 我扶你上朝",
beats=[("0–3秒", "幽深宫廊中,两人背影缓慢前行。"), ("3–7秒", "帝王袖口颤动、步履迟缓,婉儿手臂稳定。"), ("7–10秒", "前方朝堂暖光增强,帝王加重搭臂力道。")],
subtitles="0.8–5.0秒「你老了 手也抖了」;5.0–9.8秒「我扶你上朝」",
prompt="幽深唐代宫廊纵深透视,固定跟随镜头缓慢前推。左侧玄衣上官婉儿背影挺拔,右侧身着明黄龙袍的晚年武则天略显佝偻,婉儿搀扶她向朝堂走去。帝王袖口和手指细微颤动,步伐迟缓;婉儿步伐稳定。两侧红柱与灯火缓慢后退,前方暖金朝堂光晕渐亮。第八秒帝王在婉儿手臂上加重力道,全程不露正脸。",
transition="二人长影拉长,地面影子逐渐变成一卷血红诏书。"),
dict(n=13, section="Verse 2", title="谁也没提过那道诏", lyric="这一路 我们谁也没提过 那道诏",
beats=[("0–3秒", "延续宫廊跟随,青砖地面开始浮出红色卷轴虚影。"), ("3–7秒", "诏书虚影展开,两人脚步从其上踏过。"), ("7–10秒", "诏影散为红墨气,婉儿停半拍又继续走。")],
subtitles="0.8–6.0秒「这一路 我们谁也没提过」;6.0–9.8秒「那道诏」",
prompt="延续上一镜同一宫廊、同一背影与光位。两人缓步前行时,青砖地面从脚下浮现一卷血红诏书虚影,卷轴缓慢展开,朱砂字迹模糊不可辨读。二人脚步踏过虚影,没有低头。第七秒诏书散成红色墨气,被步风卷走;婉儿脚步停顿半拍,随后继续搀扶帝王前行。红色只用于诏影,不污染整体暗调。",
transition="红墨气上升并遮满画面,化成第二次Pre的火光与笔影。"),
dict(n=14, section="Pre 2", title="第二次选择", lyric="该恨你 还是该谢你 / 你毁了我的家 又给了我笔",
beats=[("0–3秒", "婉儿眼中闪回焚宅与祖父剪影。"), ("3–7秒", "现实中她握紧毛笔,火光倒影与烛光重合。"), ("7–10秒", "她松开紧绷手指,重新落笔,完成主动选择。")],
subtitles="0.5–4.5秒「该恨你 还是该谢你」;4.5–9.8秒「你毁了我的家 又给了我笔」",
prompt="成年婉儿中近景,先凝视手中毛笔。她瞳孔中短暂闪回燃烧的祖宅与白发祖父剪影,火光倒影和现实烛光在眼中重叠。第三秒手指用力握紧笔杆,指节泛白;第七秒她缓慢放松手指,深吸气但不流泪、不哭喊,随后把笔落向诏书。与第一次Pre相比,这一镜不是被动接笔,而是她清醒地再次选择使用这支笔。",
transition="笔尖落下的一滴墨扩散,进入第二次更明亮、更主动的宫城全景。"),
dict(n=15, section="Chorus 2", title="第二次为自己活", lyric="我为你研墨 也为自己活 / 仇人的江山 我替她说",
beats=[("0–3秒", "婉儿研墨并抬眼,目光从砚面转向宫城。"), ("3–7秒", "墨迹化为朝堂奏章与宫阙,镜头升高。"), ("7–10秒", "她立于朝堂与宫城之间,主动向前一步。")],
subtitles="0.5–4.8秒「我为你研墨 也为自己活」;4.8–9.8秒「仇人的江山 我替她说」",
prompt="第二次副歌采用更坚定的视觉。成年婉儿研墨后缓慢抬眼,目光从砚面转向前方。黑色墨迹从砚边流出,连续化为摊开的奏章、朝堂台阶与远处宫阙,镜头缓慢升高。婉儿从暗处向暖金光区迈出一步,玄红女官服衣摆轻动;她不再只是城楼上的孤小棋子,而是站在文字与江山之间的执笔者。",
transition="朝堂地砖转化为棋盘,婉儿迈出的一步对应白子落盘。"),
dict(n=16, section="Chorus 2", title="第二盘棋的答案", lyric="你看不透我 我也看不透我 / 这盘棋里 谁是谁的 因果",
beats=[("0–3秒", "铜镜中出现婉儿、祖父与帝王三重淡影。"), ("3–7秒", "镜面裂成棋盘格,白子落在关键位置。"), ("7–10秒", "黑子周围墨色退开,棋局仍未结束。")],
subtitles="0.5–4.5秒「你看不透我 我也看不透我」;4.5–9.8秒「这盘棋里 谁是谁的 因果」",
prompt="铜镜与砚面融合的黑镜中,成年婉儿自己的脸最清晰,白发祖父和晚年帝王只以淡淡轮廓在两侧重叠,三者随墨纹轻微错位。第三秒镜面逐格转化为青玉棋盘,婉儿戴银镯的手把白子落在关键位置,周围黑子不消失但墨色阴影逐渐退开。最后棋局仍未终结,镜头停在白子与婉儿手指离开的空隙。",
transition="白子落点泛出的墨晕旋成更大的掌上风。"),
dict(n=17, section="Chorus 2|间奏", title="风从掌上吹向江山", lyric="(掌上起风 婉儿落笔)",
beats=[("0–3秒", "掌心墨风比第一次更强,卷起细小纸页。"), ("3–7秒", "墨风沿手臂流向笔尖,婉儿落笔。"), ("7–10秒", "笔画化作宫阙轮廓,风越过城楼吹向远方。")],
subtitles="1.0–9.0秒「(掌上起风 婉儿落笔)」;使用28pt淡灰括号体",
prompt="呼应镜9但规模升级。婉儿摊开手掌,墨色风涡从掌心升起,卷动几张轻薄奏章纸页,但不形成暴风。墨风沿手腕和毛笔方向流动,第三秒另一只手稳稳落笔;新写出的墨色笔画从纸面升起,连续化成微缩宫阙与城墙轮廓。后段镜头随墨风越过城楼,吹向远处夜色,表达她的笔已经进入江山叙事。",
transition="远处墨云缓慢聚拢成祖父的白发面容,进入Bridge。"),
dict(n=18, section="Bridge", title="比报仇更长的一句咒", lyric="(古琴独白)祖父啊 我没替你报仇 / 我活成了 比报仇 更长的一句咒",
beats=[("0–3秒", "古琴独白中,祖父面容从砚中缓慢浮现。"), ("3–7秒", "婉儿凝视祖父,宫城与诏书片段在墨面掠过。"), ("7–10秒", "祖父面容与婉儿倒影重合,烛泪落入砚池。")],
subtitles="0.5–4.5秒「祖父啊 我没替你报仇」;4.5–9.8秒「我活成了 比报仇 更长的一句咒」",
prompt="古琴独白氛围,中近景缓推。成年婉儿俯身凝视砚中墨面,白发祖父上官仪的清瘦威严面容从涟漪中缓慢浮现。墨面边缘掠过焚宅、诏书、宫城和搀扶帝王的淡淡片段,如漫长人生回声。第七秒祖父面容与婉儿自己的倒影短暂重合,一滴烛泪落入砚池,重合影像被涟漪打散。婉儿唇角微颤但不落泪。",
transition="涟漪散尽后只留下婉儿自己的倒影,进入自我回答。"),
dict(n=19, section="Bridge", title="只是想活下去的人", lyric="或者 只是一个 想活下去的人",
beats=[("0–3秒", "黑镜只映出婉儿自己,她第一次正视倒影。"), ("3–7秒", "她直起身,身后宫门缓慢打开,冷夜转为黎明。"), ("7–10秒", "她走向门口但停在光影交界,留下选择余地。")],
subtitles="0.8–9.5秒「或者 只是一个 想活下去的人」;30pt淡灰,像低声自语",
prompt="砚面恢复平静,只映出成年婉儿自己的脸,不再出现祖父或帝王。她与倒影对视约三秒,随后缓慢直起身。身后半闭宫门逐渐打开,门外不是炫目强光,而是冷灰黎明与淡金天色。婉儿向门口走两步,停在阴影与晨光交界处,侧脸安静、疲惫但仍有生命力。镜头不煽情,表达她也可能只是一个努力活下来的人。",
transition="门外淡金天色叠化为明黄诏书纸面。"),
dict(n=20, section="Outro", title="墨干诏成,风仍在掌上", lyric="(研墨声渐远)墨干了 诏成了 / 风 还在掌上",
beats=[("0–3秒", "俯拍诏书,墨迹由湿转干,研墨声渐远。"), ("3–7秒", "墨字离纸化成宫阙,镜头升起俯瞰灯火。"), ("7–10秒", "婉儿在城楼摊开手掌,灯火逐盏熄灭,最终全黑。")],
subtitles="0.5–5.0秒「墨干了 诏成了」;5.0–9.1秒「风 还在掌上」;9.1秒后全黑",
prompt="俯拍明黄诏书,湿润墨迹在前三秒内缓慢失去反光并变干,研墨声逐渐远去。随后墨色笔画从纸面升起,化为微缩宫阙与大明宫夜景,镜头随之上升后拉。婉儿背影立在最高城楼,轻轻摊开一只手掌,掌心只剩一缕很淡的墨风。第七秒起万家灯火逐盏熄灭,最后仅剩她身旁一盏灯,约第九秒熄灭并归于全黑。生成完整10秒;合成199.152秒音频时裁掉末尾约0.85秒黑场。",
transition="全黑结束,不加片尾文字或Logo。"),
]
def tc_for(n):
start = (n - 1) * 10
end = n * 10
return f"{start // 60:02d}:{start % 60:02d}–{end // 60:02d}:{end % 60:02d}"
def add_cover(doc):
p = doc.add_paragraph()
p.paragraph_format.space_before = Pt(62)
p.paragraph_format.space_after = Pt(16)
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
b.set_run_font(p.add_run("上官婉儿主题音乐视频"), size=11, bold=True, color=b.GOLD)
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.paragraph_format.space_after = Pt(8)
b.set_run_font(p.add_run("《我为你研墨》"), size=30, bold=True, color=b.INK, name=b.SERIF)
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.paragraph_format.space_after = Pt(10)
b.set_run_font(p.add_run("完整歌词脚本与分镜头提示词"), size=17, color=b.CINNABAR)
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.paragraph_format.space_after = Pt(30)
b.set_run_font(p.add_run("20 个分镜 × 每镜严格 10 秒|不生成图片"), size=11, bold=True, color=b.GOLD)
table = doc.add_table(rows=6, cols=2)
b.set_table_geometry(table, [1900, 7460])
b.set_repeat_table_header(table.rows[0])
for j, text in enumerate(("项目", "制作参数")):
b.set_cell_shading(table.cell(0, j), b.INK)
p = table.cell(0, j).paragraphs[0]
p.paragraph_format.space_after = Pt(0)
b.set_run_font(p.add_run(text), size=9.2, bold=True, color=b.WHITE)
rows = [
("歌词结构", "Intro → Verse → Pre → Chorus → Verse → Pre → Chorus → Bridge → Outro"),
("分镜", "20镜;每条图生视频提示词生成时长固定为10秒"),
("素材总长", "200秒;与199.152秒音频合成时,裁掉最后约0.85秒黑场"),
("画幅", "9:16竖屏,1080×1920,H.264,30fps"),
("说明", "本文件只提供脚本、字幕与提示词,不生成任何图片或视频素材"),
]
for i, (label, value) in enumerate(rows, start=1):
b.set_cell_shading(table.cell(i, 0), b.PALE)
for j, text in enumerate((label, value)):
p = table.cell(i, j).paragraphs[0]
p.paragraph_format.space_after = Pt(0)
b.set_run_font(p.add_run(text), size=9.4, bold=(j == 0), color=b.CINNABAR if j == 0 else b.INK)
doc.add_page_break()
def add_front(doc):
b.add_heading(doc, "1. 创作说明", 1)
b.add_label_para(doc, "核心叙事|", "不会写字的罪臣孤女,在仇人的宫廷中学会用笔;她替武则天书写江山,也借文字延长自己的生命,最终承认自己或许不是复仇者,只是一个想活下去的人。")
b.add_label_para(doc, "歌词原则|", "所有歌词严格按照用户提供的顺序出现;重复的Pre与Chorus采用不同情绪层级,第一次偏被动与撕裂,第二次偏清醒与主动。")
b.add_label_para(doc, "10秒规则|", "每个分镜提示词都明确要求生成10秒,不拆成5秒或8秒。20条素材合计200秒;最后一镜的末尾是黑场,可安全裁掉约0.85秒以匹配199.152秒音频。")
b.add_label_para(doc, "字幕规则|", "文档给出的是镜内建议区间。正式剪辑时,歌词字幕应以实际演唱咬字和音频波形为准,在相邻10秒镜头内前后微调,不需要改变画面提示词。")
b.add_heading(doc, "2. 统一视觉风格", 1)
b.add_prompt(doc, b.STYLE_PREFIX + "人物以成年上官婉儿为主,幼年与少年阶段只在明确镜头出现;武则天采用晚年帝王形象;全片不生成可辨读文字,字幕统一后期添加。")
b.add_heading(doc, "2.1 统一负面提示词", 2)
b.add_label_para(doc, "负面提示|", b.NEGATIVE, after=8, shade="F4EEEE")
b.add_heading(doc, "3. 20镜歌词分配总表", 1)
table = doc.add_table(rows=1, cols=5)
widths = [540, 1320, 930, 3710, 2860]
b.set_table_geometry(table, widths)
b.set_repeat_table_header(table.rows[0])
for j, text in enumerate(("镜", "时间", "段落", "歌词", "画面主题")):
b.set_cell_shading(table.cell(0, j), b.INK)
p = table.cell(0, j).paragraphs[0]
p.paragraph_format.space_after = Pt(0)
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
b.set_run_font(p.add_run(text), size=8.8, bold=True, color=b.WHITE)
for s in SHOTS:
cells = table.add_row().cells
values = (str(s["n"]), tc_for(s["n"]), s["section"], s["lyric"].replace(" / ", "\n"), s["title"])
for j, text in enumerate(values):
p = cells[j].paragraphs[0]
p.paragraph_format.space_after = Pt(0)
p.paragraph_format.line_spacing = 1.05
p.alignment = WD_ALIGN_PARAGRAPH.CENTER if j < 3 else WD_ALIGN_PARAGRAPH.LEFT
for k, line in enumerate(text.split("\n")):
if k:
p.add_run().add_break()
b.set_run_font(p.add_run(line), size=8.2, bold=(j == 0), color=b.INK)
if s["n"] % 2 == 0:
b.set_cell_shading(cells[j], "FBF8F4")
b.set_table_geometry(table, widths)
b.add_label_para(doc, "音频收尾|", "第20镜生成00:10完整黑场尾帧;成片在03:19.152结束,裁掉最后约0.848秒黑场即可,不影响歌词和画面动作。", shade=b.PAPER)
doc.add_page_break()
def add_shot(doc, s):
h = doc.add_paragraph(style="Heading 1")
h.paragraph_format.page_break_before = True
h.paragraph_format.keep_with_next = True
b.set_run_font(h.add_run(f"分镜 {s['n']:02d}|{s['title']}"), size=16, bold=True, color=b.CINNABAR)
p = doc.add_paragraph()
p.paragraph_format.space_after = Pt(8)
b.shade_paragraph(p, b.PALE, b.GOLD)
for idx, (label, value) in enumerate((("时间", tc_for(s["n"])), ("生成", "严格10.00秒"), ("段落", s["section"]))):
if idx:
b.set_run_font(p.add_run(" | "), size=8.8, color=b.GOLD)
b.set_run_font(p.add_run(label + " "), size=8.8, bold=True, color=b.CINNABAR)
b.set_run_font(p.add_run(value), size=8.8, color=b.INK)
b.add_label_para(doc, "对应歌词|", s["lyric"], after=9, shade=b.PAPER)
b.add_heading(doc, "10秒导演脚本", 2)
for timing, action in s["beats"]:
b.add_label_para(doc, timing + "|", action, after=4)
b.add_heading(doc, "字幕建议", 2)
b.add_label_para(doc, "镜内字幕|", s["subtitles"], after=5)
b.add_label_para(doc, "转场|", s["transition"], after=7)
b.add_heading(doc, "10秒分镜提示词(可直接复制)", 2)
full_prompt = (
b.STYLE_PREFIX
+ "生成时长严格10秒,整个动作必须在0–10秒内完成;首帧和尾帧稳定可剪辑;不生成字幕、歌词、Logo或水印。"
+ s["prompt"]
+ "镜内节拍:"
+ ";".join(f"{timing}{action}" for timing, action in s["beats"])
+ "。"
)
b.add_prompt(doc, full_prompt)
b.add_label_para(doc, "统一负面提示|", b.NEGATIVE, after=7, shade="F4EEEE")
def add_end(doc):
h = doc.add_paragraph(style="Heading 1")
h.paragraph_format.page_break_before = True
b.set_run_font(h.add_run("4. 剪辑与验收"), size=16, bold=True, color=b.CINNABAR)
b.add_heading(doc, "4.1 剪辑执行", 2)
steps = [
("01|生成", "按分镜01至20顺序生成,每条时长选10秒;镜6左右分屏建议分别生成10秒再合成。"),
("02|铺音频", "先锁定《我为你研墨》原音频,再将20条素材按每10秒排列。"),
("03|字幕", "字幕不写入生成画面;以本文歌词顺序为准,以实际演唱波形微调入出点。"),
("04|收尾", "第20镜在03:19.152结束,裁掉素材末尾约0.848秒黑场。"),
("05|导出", "1080×1920,H.264,30fps,8–12Mbps;不添加未要求的片头、片尾或Logo。"),
]
for label, text in steps:
b.add_label_para(doc, label + " ", text, after=6)
b.add_heading(doc, "4.2 验收标准", 2)
table = doc.add_table(rows=1, cols=2)
b.set_table_geometry(table, [1800, 7560])
b.set_repeat_table_header(table.rows[0])
for j, text in enumerate(("验收项", "通过标准")):
b.set_cell_shading(table.cell(0, j), b.INK)
p = table.cell(0, j).paragraphs[0]
p.paragraph_format.space_after = Pt(0)
b.set_run_font(p.add_run(text), size=9.2, bold=True, color=b.WHITE)
rows = [
("提示词时长", "20条提示词均明确标注10.00秒,无5秒、7秒或16秒生成要求。"),
("歌词完整", "用户提供的全部歌词按原顺序出现,两次Pre和两次Chorus均完整保留。"),
("人物连续", "幼年、少年与成年婉儿阶段清晰;成年服装、红簪、银镯和右上烛光方向保持统一。"),
("画面安全", "无现代元素、可辨读文字、字幕、水印、Logo、畸形手指、穿模或面部突变。"),
("音频结尾", "最终成片在03:19.152结束,最后一句和研墨声尾音完整保留。"),
]
for label, value in rows:
cells = table.add_row().cells
b.set_cell_shading(cells[0], b.PALE)
for j, text in enumerate((label, value)):
p = cells[j].paragraphs[0]
p.paragraph_format.space_after = Pt(0)
b.set_run_font(p.add_run(text), size=9.2, bold=(j == 0), color=b.CINNABAR if j == 0 else b.INK)
b.set_table_geometry(table, [1800, 7560])
def build():
OUT.parent.mkdir(parents=True, exist_ok=True)
doc = Document()
sec = doc.sections[0]
sec.page_width = Inches(8.5)
sec.page_height = Inches(11)
sec.top_margin = Inches(1)
sec.bottom_margin = Inches(1)
sec.left_margin = Inches(1)
sec.right_margin = Inches(1)
sec.header_distance = Inches(0.492)
sec.footer_distance = Inches(0.492)
sec.different_first_page_header_footer = True
b.configure_styles(doc)
hp = sec.header.paragraphs[0]
b.set_run_font(hp.add_run("《我为你研墨》|完整歌词20镜执行稿"), size=8.5, color=b.MUTED)
b.add_page_field(sec.footer.paragraphs[0])
core = doc.core_properties
core.title = "《我为你研墨》完整歌词脚本与20镜分镜提示词(每镜10秒)"
core.subject = "上官婉儿主题音乐视频制作执行稿"
core.author = ""
core.keywords = "我为你研墨, 上官婉儿, 完整歌词, 20镜, 10秒, 分镜提示词"
core.comments = "根据用户提供完整歌词顺序创作,不生成图片。"
add_cover(doc)
add_front(doc)
for shot in SHOTS:
add_shot(doc, shot)
add_end(doc)
doc.save(OUT)
print(OUT)
if __name__ == "__main__":
build()