Legenda Simples — 简短短语,无动画,与口型同步 是做什么的?
一次一句,白色粗体文本,小写,仅句首大写(像转录一样),无背景,柔和阴影,位于下方三分之一处,无红色且无入场动画。例:“O problema é que” / “sem prática”。
前置需求
- Premiere Pro(已在 2027/27.0 版本测试;ExtendScript)以及 Python 3.9+,并执行
pip install -r requirements.txt(Pillow)。 - 一种在 Premiere 中执行 ExtendScript 的方式(MCP 配合
execute_extendscript或基于文件的 CEP bridge)—— 请参阅仓库根目录下的docs/PREMIERE-BRIDGE.md。 - 已安装 Montserrat Bold 字体(免费,Google Fonts)。如果找不到,请设置
CAPTION_FONT_DIR或将.ttf文件放入技能目录下的fonts/中。 - 默认模式(PNG)不需要
.mogrt。只有.mogrt替代方案才需要assets/Simple_Text_WbW.mogrt(见assets/LEIA-ME.md)。
参数(最终依据:style.json 及 scripts/plan_phrases.py 中的 RULES)
- 9x16(1080x1920)。Montserrat Bold 66 px,白色,柔和阴影(模糊 6,偏移 4,透明度 55%)。
y_center为 0.70。 - 无入场动画:每句字幕是一个透明 PNG(1080x1920),由
make_stills.py生成。它会在第一帧完整出现,然后在硬切中消失。按词出现的.mogrt不合适:入场是内置的(只有“Out Animation”和“Anim Speed”50-500,没有“In Animation”)。PNG 的代价:文本在 Premiere 中不可编辑——要修改,请编辑blocks.json并重新生成(只需几秒)。 - 每句 3-4 个词,通过动态规划实现:避免 1-2 个单词的孤立句,不以“o/de/que...”结尾,优先在逗号或停顿处切分;逗号仅在至少有 3 个单词时才切分。在快速语速下(句子在 < 0.9 秒内完成)可合并至 5 个单词,但不跨越句尾(。?!)。
- 安全框:所有内容均在 Premiere 的字幕安全框(80% x 80%)内;有效宽度 78%(1080 下为 842 px),文本块在垂直方向 10%-90% 内。文本会缩小至
min_scale,如果仍无法放入,则换行;尺寸向下取整。使用check_margins.py检查(应输出fora da margem: 0)。 - 交付方式:直接在指定的序列上编辑(不复制),除非用户要求复制。
屏幕时间 = 语音时间(sync 模式,默认)
- 字幕在第一个词发音的开始处出现(零延迟),并在最后一个词结束后 +
tail0.3 秒消失。如果之后有静默,则延长至min_dur0.8 秒(绝不侵入下一句)。如果某句字幕的持续时间将 < 0.5 秒,则当且仅当:合并后不超过 5 个单词,且上一句尚未结束一个句子时,才将其合并到上一句。 - 项目说明:还存在
schedule_mode: "lag"模式(阅读时间模式:每句至少 ~0.9 秒,如果语速更快,则下一句会延迟进入,最多延迟 0.9 秒)。这会使字幕与语音分离(开始和结束时间不再一致,持续时间与所说话语无关),因此默认是sync。仅在用户要求更慢的阅读速度时使用lag模式(通过--config传入{"schedule_mode":"lag"})。 - 诚实的限制:非常密集的语速(约 3.6 词/秒,峰值 6 词/秒)会导致某些字幕持续时间很短(0.36-0.8 秒)。这是语音的特性,不是字幕的。
选项 A — 仅在已剪辑序列上叠加字幕
- 与用户确认项目/序列,并使其处于激活状态。
- 转写:从 Premiere 导出的 JSON(文本 > 转写 > ... > 导出;位于文档中,文件名为 "<序列名>.json")。
PYTHONIOENCODING=utf-8 python -I <skill>/scripts/plan_phrases.py <转写.json> <目录>/blocks.json;显示列表和单词以供[确认]。python -I <skill>/scripts/make_stills.py <目录>/blocks.json <目录>/png --track 1(生成 PNG + JSX;每次生成使用一个新目录——Premiere 会锁定已导入的 PNG)以及python -I <skill>/scripts/check_margins.py <目录>/png/stills_clips.json。- 在 Premiere 中,保持序列激活状态:运行
stills_import.jsx(将 PNG 导入到一个 bin 中),然后逐个运行stills_01.jsx...(显示ok=20/20)。时间已经按帧网格对齐(--fps,默认为 30)。
选项 B — 完整动态编辑(剪辑 + 缩放 + 字幕)
- 将视频导入项目并获取 Premiere 的转写。
python -I <skill>/scripts/plan_edit.py <转写.json> <目录>:移除 > 0.3 秒的停顿/呼吸以及犹豫(空白文本),按标点切分约 3 秒的子剪辑,交替缩放 100%/116%,并写入已修剪好时间的clips.json和blocks.json。可在脚本顶部调整(GAP、ZOOM_ALT、SUB_MIN/MAX)。python -I <skill>/scripts/build_cut_script.py <目录>/clips.json <目录> --item <项目中文件的名字> --name "<名字> editado 9x16"->montar.jsx;在 Premiere 中运行(原始序列不受影响)。- 字幕:同选项 A 的步骤 4 和 5,使用此目录中的
blocks.json。 - 保存项目并列出交付内容:剪辑点、缩放、可疑单词以及未审查的内容。
.mogrt 替代方案(可编辑文本,带按词入场动画)
python -I <skill>/scripts/make_graphics_script.py <目录>/blocks.json <目录>/lote.js --track 1(使用 assets/Simple_Text_WbW.mogrt;动画速度在 style.json 中设置),然后运行各批处理 lote_NN.js。仅当用户接受动画时使用。
Premiere 实用技巧(实践中发现)
importFiles需要绝对路径(new File(...).fsName);createNewSequenceFromClips会从竖版视频继承 1080x1920 设置。- 渲染:
app.encoder.encodeSequence(...)+startBatch()可能不会进入 Media Encoder 队列。已验证有效的方法:seq.exportAsMediaDirect(输出, 预设, app.encoder.ENCODE_ENTIRE)(在 Premiere 内部渲染,90 秒的片段大约需要 5 分钟)。预设位置:<Premiere 安装目录>/MediaIO/systempresets/.../H264 Match Source - High bitrate.epr(使用 glob 搜索;位于安装文件夹内)。"MooV" 预设会在 .mov/.mp4 中生成 PCM 音频;如果用于发布,请使用ffmpeg -c:v copy -c:a aac重新封装。 - 导出帧(通过 QE 的
exportFramePNG)可能失败;字幕的 PNG 不需要这个:PNG 中看到的就是最终视频中的内容。
快速调整
| 我想要 | 修改哪里 |
|---|---|
| 字体/大小/位置/阴影 | style.json(font_path、mogrt_font、mogrt_size、y_center、shadow_*) |
| 更长的屏幕时间 | RULES 中的 min_dur、tail(在 sync 模式下仅向静默延伸) |
| 3 个词而非 4 个 | 通过 --config 传入 {"max_words": 3} |
| 更多/更少的剪辑和缩放 | plan_edit.py 中的 GAP、ZOOM_ALT、SUB_MIN/SUB_MAX |
已知限制
- PNG 文本不可编辑(修改方法:编辑
blocks.json并重新生成)。 - Premiere 的转写可能出错;在应用前请检查
blocks.json。 - 参考字体似乎是 Proxima Nova Bold(更窄);这里使用免费的 Montserrat Bold。