Shorts Video Studio
生成 30-60 秒、1080x1920 的 MP4 视频 + SRT 字幕 + 脚本。一切都通过程序化方式实现(Python + OpenCV + PIL + ffmpeg),由基于提示点的动画引擎驱动,确保视觉内容精确对应每个口语词。
本技能包含的文件
scripts/shorts_engine_template.py- 可用的参考引擎(9 个场景、9 种背景、8 种转场、音频、语音同步)。复制并编辑它;不要从头重写。scripts/tts_elevenlabs.py- 通过 REST API 生成配音(需要ELEVENLABS_API_KEY)。先使用--check和--list-voices。scripts/review_frames.py- 生成联系表 + QA 证据:时长、编码、分辨率、集成 LUFS、响度范围、真实峰值。失败时退出码非零。scripts/setup.sh- 创建.venv,安装依赖,检查 ffmpeg 和字体。之后执行source .venv/bin/activate。assets/fonts/- 15 个 OFL-1.1 字体文件 / 12 个字体系列 + Noto Color Emoji(真实图标)。包含许可证,索引在assets/fonts/LICENSES.md中。references/design-bible.md- 调色板、字体、图标词汇、背景、转场、效果、布局网格。设计场景前请阅读。references/script-and-voice.md- 脚本公式、Hinglish 规则、事实核查规则、语音和对齐细节。编写脚本前请阅读。
流程(按顺序执行步骤)
- 调研 - 如果主题是新闻/趋势,搜索 3 个以上来源,收集包含日期和数字的事实(“截至 <日期>”)。切勿编造数字。标记无法验证的声明,并软化措辞(“报告 ke mutabik”)。
- 脚本 - 120-140 词,时长约 45-50 秒,前 2.5 秒设置钩子,7-9 个短节奏,最后是行动号召。参考
script-and-voice.md。保存为script.txt(每个场景一个段落)。 - 场景规划 - 每个段落一个场景。为每个场景决定:背景风格、调色板、2 种字体、图标(emoji)、主角动画、提示词、到下一场景的转场。应用下方的多样性规则。将计划写入
plan.md。 - 配音 - 为整个脚本生成一次配音(使用
tts_elevenlabs.py或 ElevenLabs MCP)。保存为voice.mp3。如果无法下载音频(沙盒环境),请请求用户上传文件;同时使用预估时间进行构建。 - 构建 - 复制模板到
video.py,替换 SCENES 文本,编写bgN/dN函数,设置HIT和TRANS。对每个动画起始点使用提示查找C(scene_idx, "spokenword", occurrence, default_seconds)。 - 测试渲染 -
TEST=1 python video.py会写入 PNG(结束状态、中间状态和每个转场的一帧)。运行review_frames.py/ 查看它们。修复 QA 门控标记的所有问题。 - 最终渲染 -
VOICE=voice.mp3 python video.py。后台运行(setsid nohup ... &)并轮询日志;前台调用可能因工具超时被杀死。50 秒视频在单 CPU 上大约需要 1.5-3 分钟。混音会自动标准化响度至LUFS(默认 -16)。 - QA 门控(见下文)检查最终的 mp4,然后交付
video.mp4、captions.srt、script.txt、plan.md、qa_report.md。
多样性规则(这是使其看起来像人工制作而非 AI 制作的关键)
违反任何一条都会导致 QA 门控失败。
- 每个场景都有自己的背景技术和调色板(射线、合成波网格、半色调太阳爆、代码雨、渐变+斑点、蓝图网格、危险条纹、雷达环、五彩纸屑...)。相邻场景从不相同。从不使用全局单一颜色。
- 整个视频使用 >= 7 种不同字体,混合类别:紧缩冲击体、粗壮显示体、宽显示体、怪诞体、衬线体、斜体衬线体、等宽体、像素体、手写体。单个场景内最多使用 2-3 种字体。
- >= 5 种不同文字处理:渐变填充、粗轮廓+硬偏移阴影、发光、逐字母弹跳、打字机、贴纸/药丸芯片、旋转印章、手写倾斜。
- 真实图标,而非几何形状:使用彩色 emoji(Noto Color Emoji)作为图标,并赋予动画效果(带过冲弹出的弹出、旋转进入、浮动、轨道、摇摆)。永远不要出现纯文本场景。绝不使用品牌徽标(Adobe、GitHub 章鱼猫等);使用通用图标。
- 8 种以上不同转场,每切换一次场景使用一种:毛刺、扫动模糊、缩放穿过、虹膜+环、百叶窗擦拭、闪光+震动、像素化、上推。从不重复使用同一种。
- 冲击时刻获得组合效果:火花爆发+冲击波环+相机震动+RGB 分裂+爆炸音效。
- 字幕:每次 2-3 个词,大号粗体带粗轮廓,当前词以场景颜色高亮显示,每个词块有轻微弹出缩放。
- 所有元素都有运动:没有元素无动画出现,没有元素完全静止(空闲摆动/浮动/缓慢缩放 0 -> 3.5%)。
布局和安全区域(720x1280 工作画布,放大到 1080x1920)
- 顶部 0-130 像素:保持空白(平台 UI)。标签芯片仅在 y~62 处。
- 内容区域 y 150-830。字幕区域中心 y = 950 (H-330)。底部 250 像素:保持空白(平台 UI)。
- 宽度预算 640 像素。对任何可能溢出的行使用
TXF(text, size, font, maxw)。估计宽度 = 字符数 x 0.55-0.75 x 字号,取决于字体(宽显示体约为 0.75)。 - 计数器:固定字号,计数时绝不自动缩小(会导致抖动)。
语音和同步(摘要;详见参考资料)
- 一次录音,然后对齐:
apply_voice_peaks检测音节能量峰值,并通过动态规划将其与脚本的音节匹配(稳定在约 0.2 秒内)。ALIGN=pauses是慢速语音且有明显停顿时的备选。 - 提示词使用第一个以小写无标点文本开头的词(数字:精确匹配)。对重复词使用
occurrence。 - 场景开始 = 场景第一个词 - 0.45 秒。总时长跟随语音(加 1.2 秒尾音)。
- 音乐是合成的(垫音+鼓点+镲片+贝斯+琶音),在语音下约闪避 55%;语音经过高通+压缩+响度标准化(-15 LUFS)。每次转场有呼啸声,冲击时有爆炸声,打字有滴答声,计数器有叮咚声,行动号召有弹出声。
QA 门控(评判员/QA 代理必须通过所有检查才能交付)
python scripts/review_frames.py out/video.mp4 out/contact.png 12必须输出 PASS(否则退出码非零)。响度和峰值通过它获取,而非volumedetect。- 时长 30-60 秒,1080x1920,h264+aac,集成响度大致 -18 到 -13 LUFS,真实峰值 < -1 dBTP(无削波)。
- 查看包含 >= 9 帧的联系表 + 每个转场帧:无文本裁剪/溢出,无重叠元素,顶部 130 像素或底部 250 像素内无内容(除标签/字幕),字幕在每个背景上清晰可读。
- 满足多样性规则(在
plan.md中列出实际使用的字体、调色板、背景和转场)。 - 事实:脚本中的每个数字/日期/名称均可追溯到
plan.md中注明的来源;未经核实的声明已软化;除非有来源,否则不使用“复制”/“盗窃”措辞;在相关时说明 alpha/局限性。 - 同步抽查:选择 5 个提示点(钩子词、数字、名称、转场、行动号召),确认视觉内容在口语词开始 0.25 秒内出现(将 SRT/
SW时间与帧时间戳比较)。 如果任何检查失败:修复、重新渲染、重新运行门控。诚实地报告剩余已知问题。
已遇到的陷阱(请避免)
- 在现代 Debian/Ubuntu 系统上,使用
pip install安装到系统 Python 会失败(externally-managed-environment,PEP 668)。请使用scripts/setup.sh(创建.venv)和source .venv/bin/activate;不要试图使用--break-system-packages。 - 将
ffmpeg volumedetect的mean_volume(无加权 dBFS)与 LUFS 目标进行比较是无意义的,并导致早期构建自己的门控失败。始终使用ebur128测量(review_frames.py已经这样做了)。 - 在 PIL 图像或非连续裁剪上使用
Image.fromarray会导致TypeError: expected string or buffer。保持精灵图为连续 numpy 数组;rcard()返回 PIL 图像,而非数组。 - 将空数组切片传入
cv2.add会导致断言错误;在切片波段前检查b > a。 - 未使用
setsid nohup启动的后台进程会在工具调用返回时被杀死。 - 沙盒环境无法下载音频生成(MCP)的结果:请求用户上传 mp3/wav 文件。
- 基于停顿的同步对紧凑的 AI 语音失败(在 -35 dB 时仅发现 4 个停顿);基于峰值的对齐是默认选择。
- 重叠的提示窗口:如果两个元素共享一个口语词,将第二个元素偏移 0.2-0.4 秒。
- 带有变体选择器的 Emoji(例如盾牌、警告)在
embedded_color=True下可正常渲染;使用INTER_AREA缩小 /INTER_CUBIC放大。 - 缺失字体会静默回退到 DejaVu/Liberation 并显示
[warn]行 - 在归咎布局前检查渲染日志中的[warn]。