竖屏短视频工作室(专业版)
端到端流程:(首次运行:询问用户的账号/水印/行动号召/语音偏好)→ 主题 → 研究 → 草稿 → 审批 → 配音 → 定时 → Remotion场景 → 渲染 → Reels导出 → 质量检查 → 封面+字幕 → 交付。
这是 vertical-reels-video-studio(基础版)的完整版本。品牌配置存储在 brand.config.json 中(由 src/brand.ts 读取,并作为 brand 属性传递给组合组件)。
0a. 首次运行:询问用户TA们的设置(切勿使用默认值)
在第一个视频之前,如果 brand.config.json 缺失、包含 "configured": false 或仍含有 @yourhandle,依次询问用户(每次一个问题)并将答案保存在 brand.config.json 中:
- 社交账号:Instagram、Threads、TikTok、X(用户使用的平台)。
- 水印文字(完全按显示样式,例如
@yourhandle或@ig / @x)及位置(bottom-center、bottom-left、top-left、top-right)。 - 行动号召文本及其提及的账号。
- 语音:用户的ElevenLabs语音ID + 模型 + 语言,或“我自己录制语音”。API密钥仅以
ELEVENLABS_API_KEY密钥形式请求。 - 语言和语气;语音应如何称呼用户的名字/账号。
然后将 "configured" 设置为 true。切勿伪造账号,切勿使用他人的账号(包括此工具包的作者),也切勿渲染仍显示 @yourhandle 的水印。
0b. 品牌配置(brand.config.json,根据用户回答填充)
| 键 | 占位符 | 说明 |
|---|---|---|
| 账号 | {{IG_HANDLE}}、{{THREADS_HANDLE}}、{{TIKTOK_HANDLE}}、{{X_HANDLE}} | handles.*,用户自己的 |
| 水印 | {{WATERMARK}} + 位置 | watermark.text / watermark.position,用户提供的确切文本;切勿在场景中硬编码 |
| 语言/语气 | {{LANGUAGE}}、{{TONE}} | 例如非正式的印尼语,少用表情符号 |
| 语音昵称 | {{SPOKEN_NAME}} | 语音如何称呼用户的账号(例如 @janedoe_ 说成“Jane Doe”)。字幕仍显示真实账号 |
| 免责声明 | {{DISCLAIMER}} | 对于金融话题,例如“教育性内容,非财务建议” |
| 语音 | {{VOICE_ID}}、{{TTS_MODEL}}、{{LANGUAGE_CODE}} | voice.*,用户的选项(或用户自己的录音) |
| API密钥 | 环境变量 ELEVENLABS_API_KEY | 切勿打印、记录或提交 |
| 行动号召 | {{CTA}}、{{CTA_HANDLE}} | cta.text / cta.handle,由用户提供(例如“关注{{CTA_HANDLE}}获取更多”、“评论TUTORIAL”) |
| 硬性规则 | {{HARD_RULES}} | 永远不要嘲笑的品牌、需要模糊的名称、永远不要说的词语 |
| 渲染设备 | {{RENDER_DEVICE}} | GPU机器或CPU。始终报告实际使用的设备 |
1. 研究与草稿(无音频,无渲染)
- 使用原始来源核实每一项主张:官方文档/新闻稿、作者自己的帖子、注册机构、带日期的截图。高管帖子算作官方声明。将估算标记为(
ESTIMATE · not official),指控标记为(ALLEGED)。无法核实的内容直接删除,而非软化表述。 - 每个视频讲述一个故事,使用日常用语,节奏平缓。硬产品名称在屏幕上显示,而非旁白中。
- 提供2–4个钩子选项(H1、H2等):一个为什么/如何的问题或一个鲜明的对比。让用户选择。
- 定时表:
时间 | 屏幕内容 | 旁白。目标时长45–65秒,硬上限90秒(目标≤88秒,以确保修订后仍能适应)。 - 编写
factcheck.md(主张→来源→状态)和sources.md。 - 发送草稿并等待审批。 来自用户的“不要渲染”意见是最终决定,除非他们说继续。
2. 配音(ElevenLabs)
- 两个脚本:
script-display.txt(字幕显示的内容)和script-tts.txt(为语音拼写的版本)。保留显示↔TTS映射。 - 发音(参见
docs/VOICEOVER.md):A.I.带点号使其听起来像英语;非英语旁白中逐个字母朗读代码(ETH →E, T, H);数字读作单词;英语术语使用普通英语拼写(无连字符重拼);在最后一个/t/后加逗号再接元音;品牌名称仅在测试证明有帮助时才重新拼写。 - 后处理
atempo1.05(快节奏内容为1.1)。响度−14 LUFS集成值,≤ −1 dBTP。 - 无重复行。 如果某行重复了钩子或之前的要点,则裁剪或改写。
- 首先检查字符配额。仅对失败的行重新配音(传递
previous_text以保持连续性)。
3. 定时
- 从TTS对齐(除以节奏因子)或 faster-whisper 获取单词时间戳 →
timing.json{duration, phrases:[{s,e,words:[{w,s,e}]}], scenes:[{id,start}]}(scripts/build-timing.py)。 - 将重拼的标记合并回显示单词(
A.I.→AI、E, T, H→ETH),否则字幕会延迟开始。 - 场景根据口语单词确定:
wt(scene, word)→ 该单词开始的帧。
4. 动效风格(Remotion,1080x1920,30 fps)
配色: 基础 #0A1016,奶油色 #EFE6D2,琥珀色 #FFB000,红色 #E2553F,绿色 #7BD88F。字体通过 @remotion/google-fonts:Big Shoulders 800(标题)、Plus Jakarta Sans(正文/字幕)、JetBrains Mono(标签/代码)。
布局: 重要内容位于y 200–1500。底部区域:卡拉OK字幕约为y 1310–1353,水印(如果用户选择底部)约为y 1427–1446,进度条约为y 1474,所有内容位于x 960左侧(Reels在其右侧绘制按钮)。
无空白帧: 钩子在帧0时即可读取;开头和结尾与中间部分一样充实(英雄图片、主持人、标签),从不在空白背景上单独一行。
缓动辅助函数(src/motion/ease.ts):
const clamp01=(x:number)=>Math.max(0,Math.min(1,x));
const P=(t:number,a:number,b:number)=>clamp01((t-a)/(b-a));
const eOut=(x:number)=>1-Math.pow(1-x,3);
const eIn=(x:number)=>x*x*x;
const backOut=(x:number,s=1.70158)=>1+(s+1)*Math.pow(x-1,3)+s*Math.pow(x-1,2);
const sec=(f:number,at:number)=>(f-at)/30;
const ap=(f:number,at:number,d=0.3)=>eOut(P(sec(f,at),0,d));
const pop=(f:number,at:number)=>Math.max(0,backOut(P(sec(f,at),0,0.35),2.2));
const punch=(f:number,at:number)=>{const t=sec(f,at);if(t<0)return 1;return 1+0.12*eOut(P(t,0,0.2))-0.06*eOut(P(t,0.2,2.5));};
const shake=(f:number,at:number)=>{const t=sec(f,at);return t<0||t>0.4?0:14*Math.exp(-t*10)*Math.sin(t*70);};
移动效果: 动态文字(单词在其配音时间落地,scale(0.6+0.4*pop),±4°在0.25秒内稳定,重音词更大且为琥珀色/红色),关键图片上的缩放冲击,圆形蒙版揭示,缩放过渡(scale 1→4.2约9帧,下一场景1.3→1),旋转印章和等宽标签,截图上的红色高亮框,步骤计数器,卡拉OK字幕(当前词琥珀色+1.08×),行动号召弹出加抖动,以及在配音下的嗖嗖/弹出音效。大约每1.5–3秒一个节奏点。
视频片段: 将每个 <OffthreadVideo> 包裹在 <Sequence from={at}> 中,并设置相对于它的 startFrom;否则片段会钳制在其最后一帧上,看起来像冻结。对于长节拍,循环短片段。片段从第一个可用帧开始。
音频过渡: 当开场在旁白使用现场音频(歌曲、片段)时,将其淡出至静音,并在第一个旁白单词前留约0.3–0.5秒(闪光/嗖嗖过渡),确保不会遮住旁白。
可选主持人(吉祥物)与唇形同步
- 每个视频中保持一致的字符形象。分离图层:身体(闭口画好)、手臂在衣领边缘的肩部枢轴上、静态肩垫、嘴部精灵图
closed/half/open/wide/round。 - 使用VO wav驱动嘴部,而非循环:
scripts/build-mouth-track.py→ 每帧状态(静音和结束保持时闭口,2帧最小保持)。将手臂限制在装置的范围内;仅依靠全身晃动是不够的。 - 只有在屏幕上时才显示主持人;封面使用静态闭口身体。
5. 渲染
- 如果可能,优先使用GPU机器(Remotion
--hardware-acceleration,配置中不包含会破坏所需NVENC的encodingBufferSize/encodingMaxRate);仅在允许时才回退到CPU。始终说明实际使用的设备。 - 原始渲染:在
remotion.config.ts中使用yuv420p+bt709,然后进行Reels处理。
6. Reels安全导出(scripts/reels-export.sh,详情参见 docs/REELS_SAFE_EXPORT.md)
1080x1920 SAR 1,H.264 High level 4.1,yuv420p TV范围,BT.709标签,CFR 30,GOP 60闭合,10 Mbps(最小8,最大12),两遍 loudnorm −14 LUFS / −1.5 dBTP,AAC 192k 48 kHz立体声,+faststart,< 90秒。同时提供小于40 MB的小预览(scripts/make-preview.sh)。
7. 质量检查(强制,交付前)
- 使用Whisper检查最终MP4(
scripts/whisper-check.py):错误发音、口吃、杂音、重复行、每个场景第一个单词是否可听清。 - 在每场景边界生成联系表(
scripts/contact-sheet.sh):画面瑕疵、重叠、文本截断、安全区域、冻结片段、空白开头/结尾、水印是否存在、是否与brand.config.json完全匹配。 scripts/qa-check.sh:编解码器/配置文件/级别、像素格式、范围、色彩标签、CFR、AAC 48k、moov在mdat之前、时长<90秒、−14 LUFS。- 修复并重新渲染。修订时保留之前版本。
8. 始终随视频交付
- 各平台字幕:Instagram(钩子、正文、行动号召、少量标签词)、Threads(更短,无标签)、TikTok,以及一个
.srt文件。 - 四种封面A–D:1080x1920 + 1080x1350网格,关键文本位于中心1080x1080区域内;一个钩子、一张主照片、最多2–3个数字卡片;提供联系表并让用户选择。
- 来源引用和事实检查文件。
- 在
videos-log.md中添加一行:标题、文件名、时长、响度、设备、来源、状态“未发布”。
规则
- 切勿发布、私信、上传或购买。仅交付文件。
- 无虚构事实、明星、价格或结果。在屏幕上致谢开源作者。
- 仅使用真实照片、logo和片段;无真实人物的AI生成面部图像。将模拟图标记为
illustration。 - 使用您有权使用的媒体;当音乐或片段受版权保护时告知用户(静音/索赔风险)。
- 文件中不含秘密。最后询问任何问题,单独消息发送。