stripe-youtube
Adnaan 长格式技能(adnaan-youtube)的 Stripe 版本:相同的流水线和 v7 设计系统,但运行在 16:9 面板上,所有颜色均取自 单个品牌文件。默认品牌为 Stripe(brand/stripe.json,基于 Stripe 公开品牌页面编写:blurple #533AFD 强调色,slate #061B31 圆盘和墨水,cool paper #EEF1F6,白色卡片,strawberry 仅用于数据)。另一家公司 = 又一个品牌文件($Y/brand.py init --edit-dir edit --brand acme.json);其他一切不变。在开始任何操作前,请查看 assets/style/stripe_youtube_sheet.jpg(其制作的第一部视频的真实帧)并浏览 examples/stripe-v1/(其节拍表和场景)和 examples/yt-01-v7/。艺术方向具有约束力,存在于 references/style.md 中;章节、窗口和节奏存在于 references/planning.md 中;描述存在于 references/description.md 中。(旧的 Greg Light/Dark 标记外观仅在要求时保留。)
品牌如何嵌入: edit/brand/brand.json → $Y/brand.py 写入 brand.css(它重新指向运行时的标记)→ board.py 在它准备的每个场景中将其链接在 v7yt.css 之后,talkcaps.py 也对字幕叠加层执行相同操作;运行时的补间(V.mintTo / V.charcoalTo)也读取这些标记,compose 的图层遵循该文件。场景绝不会直接输入十六进制颜色。品牌文件中命名的 Logo 从官方套件获取到 edit/logos/ 中(绝不重新绘制)。
此技能是 adnaan-reel 的长格式姊妹版,并复用了其辅助工具(转录、剪辑、验证、页面捕获、Logo/照片/图标获取器、渲染/响度流水线、SFX 套件、头部姿态)。它必须安装在 ~/.claude/skills/adnaan-reel 中。使用该项目的环境运行每个辅助工具:
uv run --project ~/.claude/skills/adnaan-reel python <helper> … — 其中 R=~/.claude/skills/adnaan-reel/helpers,Y=~/.claude/skills/stripe-youtube/helpers。
长格式构建方式(与短视频的不同之处)
短视频让每个节拍都成为一个完整的 HyperFrames 场景。长视频不行(渲染时间过长,且观看疲劳)。具体如下:
- 剪辑 (
$R/render.py --base-only) →base.mp4:他的相机画面,剪辑后,1920x1080,带有语音(单个采样精确通道构建——见反模式,唇形同步偏移),然后$Y/lookdowns.py在低头看稿时保持一帧画面。 - 设计时刻是 HyperFrames 场景 (
$Y/board.py):画布、地图、面板、证明(不透明,3–10秒)和标注叠加层——通常每部视频 25–45 个,由代理并行构建。对话字幕作为生成的叠加层 ($Y/talkcaps.py),每个全帧对话窗口一个。 - 其他一切内容通过合成生成 (
$Y/compose.py):对话 = 基础全帧画面 + 字幕;屏幕 = 面板图层 + 他的屏幕录制(使用相同范围剪辑,由$Y/zoomplan.py缩放)+ 演讲者卡片;场景窗口 = 渲染输出 + 卡片;顶部的叠加层;SFX + 平衡音乐底噪;-14 LUFS。大约 40 秒合成处理一分钟的视频。
原则
- 面板是基础,他在卡片上。 大约 70–85% 的运行时间是面板布局,他的静态相机在卡片中(固定位置,仅在剪辑时移动,强调色环);全帧对话是标点符号(介绍、观点、故事、号召性用语)。默认无磨砂效果——他喜欢简单的卡片。
- 一个外观,一个品牌文件。 纸张 + 网格 + 强烈晕影,品牌主色作为单一强调色(Stripe blurple),其深色用于圆盘并搭配白色 Phosphor 字形和墨水(Stripe slate),平面白色卡片,干净的矢量描边,Inter Tight / Inter(Stripe 的公开字体不可用)。数据颜色(strawberry
#E8435A)仅用于数字。无标记,无 Caveat,无柔和色调,场景中不直接输入十六进制颜色。 - 对话带字幕,每个词都有。 全帧对话窗口带全屏动态字幕(白色,每个短语一个英雄词使用品牌的浅强调色,左栏放置在他背景的平静部分)。面板窗口将词汇融入设计中。SRT 字幕文件仍然提供。屏幕上的文字是他所说的内容。
- 展示真实内容。 他提到的每页纸、文件、帖子、研究都以真实形式出现(白色卡片中的可读条,品牌色调高亮笔标记所说短语);每个工具/公司得到其官方 Logo;人物使用真实照片。绝不编造数字、引用或截图。
- 屏幕是演示过程。 他的 Cap 录制放在窗口卡片中,放大他点击的内容(他的 Cap 缩放优先,然后点击集群,最后是手动目标),标注在缩放落定后绘制。等待时间被剪掉,绝不快放。
- 两次批准,然后构建所有内容。 章节大纲 → 节拍表 → 试点(2–3个场景 + 外观中的字幕)→ 并行构建所有时刻 → 合成 → 自检 → 交付。自动模式(“直接做”)跳过等待步骤。
- 绝不出现空面板。 每个设计时刻都有一个主要对象来表现该句子 + 1–3 个微动画;镜头移动;每个场景的第 0 帧已经显示其标题或主要对象。
- 声音支持语音。 仅使用结构性 SFX(大约每 30–60 秒一个,低调温暖的 v6 套件),平静平衡的音乐底噪大约比他的语音低 5 dB(再低他就听不到了),语音位于顶部,-14 LUFS。
- 展示前验证。 精确帧数,每次剪辑时检查唇形同步,每个窗口边界在单页上展示,字幕对照剪辑版本朗读,测量响度。他绝不应该是发现同步或电平问题的人。
硬性规则
- 大纲批准后,节拍表批准后,才构建任何场景(除非是自动模式)。
- adnaan-reel 的剪辑规则不变:词边界剪辑,每个填充词剪辑和每次拼接都需用
$R/verify_cuts.py验证(阅读 ⚠ TAIL/HEAD 标志),绝不渲染测试用的 EDL 到edit/目录,30 毫秒淡入淡出。 - 从他的 Cap 修剪开始 (
source/cap.json"trims")。然后移除重拍:保留每句台词的最后一个完整版本,绝不从两次尝试中拼接一句台词,丢弃他口头拒绝的内容(“不”、“再来”、“作废”)和花絮;检查会话结尾是否有重新录制的挂钩。通过单独转录每个保留范围以及与其相邻范围的每次拼接来查找重复内容——长时间剪辑中的低语可能会将同一句台词的两个版本合并为一个。 - 无静音:将每个范围修剪到仅剩语音(噪声底限 + 7 dB,语音前 0.07 秒 / 语音后 0.09 秒),并拆分内部停顿 ≥ 0.22 秒(
$R/audio_env.py tighten --margin 7 --min-gap 0.22)。他两次要求“剪掉所有停顿”——第一遍保留的 0.3–0.9 秒空隙被视为停顿。 - 屏幕录制使用与相机相同的范围进行剪辑(compose.py 从 timeline.json 中执行此操作)。
- 场景:精确遵守其帧数(board.py 预先设置,
board.py check验证);运行时(board.css/js,v7yt.css/js)已安装,绝不按场景编辑;全局外观更改仅在templates/runtime/中进行一次 →board.py runtime。卡片区域清晰;第 0 帧不为空。 - 仅通过
board.py render渲染(代理也如此,使用--only <id>):它为叠加层选择 ProRes 4444 .mov 格式(h264 .mov 是不透明的——对话窗口显示的是纸张而不是他)并在机器范围内共享渲染槽位。绝不使用pkill终止渲染进程——一个代理的 pkill 会杀死所有其他代理的渲染进程。 - 标注位置来自
compose.py where <out_t> <sx> <sy>,绝不猜测。 - 每个场景(或共享一个对象的场景族,如链条)使用一个子代理,所有子代理在一次消息中生成;在每个场景的静帧生成后立即审查,通过 SendMessage 向同一代理发送修复。共享对象只有一个所有者,负责编写共享模块 + 注释;其他代理复制,绝不派生。信任文件时间戳,而非报告。
- 下载通过
$R/fetch.py完成,捕获通过$R/capture.py完成(记录在 credits.md 中);所有输出放在<project>/edit/中;在编辑过程中绝不写入技能目录。 - 剪辑前对相机画面进行镜像检查(在全分辨率静帧中放大他衣服/背景上的任何印刷文字)。
- 在 shell 循环中,ffmpeg 使用
-nostdin(否则它会消耗循环的标准输入)。
辅助工具
| 辅助工具 | 功能说明 |
|---|---|
$Y/cap.py find / info <p.cap> / ingest <p.cap> --edit-dir E | Cap 项目(最新优先)→ source/cam.mov,source/screen.mp4,source/cap.json(点击、移动、修剪、缩放) |
$R/transcribe.py source/cam.mov --edit-dir E --vocab "…" | 词级转录 → transcripts/cam.json(缓存) |
$R/pack_transcripts.py · $R/audio_env.py · $R/verify_cuts.py · $R/timeline_view.py | 读取录制内容、收紧、验证每次拼接(adnaan-reel) |
$R/headpose.py source/cam.mov --start 0 --end <s> > E/headpose_report.txt | 录制过程中的头部俯仰角度 → 低头看稿的跨度 |
$R/render.py edl.json -o base.mp4 --base-only | 剪辑 → base.mp4 + timeline.json(采样精确的语音) |
$Y/lookdowns.py --edit-dir E | 在行开始/结束处的低头看稿时保持一帧相机画面;每次基础渲染后重新运行 |
$Y/sync_check.py --edit-dir E [--final final.mp4] | 每段(画面 vs 语音 vs 源)的唇形同步检查,以及最终版本 vs 基础版本;如果不同步则退出 1 |
$R/capture.py · $R/fetch.py logo/photo/icon/url/credits | 可读的页面条、官方 Logo、真实照片、Phosphor 图标、下载、credits.md |
$Y/board.py prepare/runtime/render/check --edit-dir E [--only ids] | 来自 animations/scenes.json 的场景项目(v7 运行时 + 图标 + 起始模板 + 资产 + TASK.md);有限槽位渲染;精确帧数/透明度检查 |
$Y/talkcaps.py --edit-dir E [--dry-run] | 全屏对话字幕:每个对话窗口一个生成的 cNN_talk 叠加层(任何剪辑/场景更改后重新运行) |
$Y/compose.py plan / where <t> <sx> <sy> / render -o final.mp4 [--preview] [--only-window N] / sheet <video> | 窗口表;标注坐标;合成物(窗口 + 卡片 + 叠加层 + SFX + 平衡音乐 + -14 LUFS);边界单页 |
$Y/zoomplan.py | 缩放相机(库) |
$Y/deliver.py srt / chapters / stills <video> t… | deliver/captions.srt,deliver/chapters.txt(已验证用于 YouTube),缩略图静帧 |
$Y/brand.py init / css / apply --edit-dir E [--brand x.json] | 品牌文件 → brand.css → 每个场景(board.py 和 talkcaps.py 调用它;apply 手动重新安装) |
$Y/review.py --edit-dir E <ids> | 每场景审查单页(5帧,卡片框线标注)→ verify/review/<id>.jpg |
$Y/inserts.py clip / splice / shift --edit-dir E | 带有自己音频的片段放在品牌面板上 → 帧精确地拼接进合成物 → SRT 和章节偏移 |
起始模板(templates/scenes/):canvas(画布)、map(地图)、board(面板)、proof(证明,不透明)、callout_overlay(标注叠加层)、talk_overlay(对话叠加层,透明)和 talk_captions(对话字幕,talkcaps.py 的模板)。运行时头部(board.js,v7yt.js)列出了每个基本元素。
参考场景:examples/stripe-v1/(Stripe 视频:节拍表、场景列表、链条 + 品牌卡片 + 页面模块)和 examples/yt-01-v7/(链条地图 + 共享模块、数据条、证明页面、面板流程、字幕)。
布局
<project>/
└── edit/
├── project.md 会话记忆
├── source/ (cam.mov, screen.mp4, cap.json) transcripts/ (cam.json 原始, CAM.json 修正)
├── edl.json, base.mp4 (+ base_unfrozen.mp4), timeline.json, headpose_report.txt, layout.json
├── brand/ (brand.json, brand.css) captures/ logos/ photos/ icons/ downloads/ music/ inserts/
├── animations/ (scenes.json, <id>/{hf/, TASK.md, render.mp4|mov, beats.json, qa/}, cNN_talk/ generated)
├── compose/ (plates, screen_cut.mp4, windows/) verify/
└── final.mp4, deliver/ (captions.srt, chapters.txt, description.txt, thumb_*.png), credits.md
流程
- 恢复。 如果
edit/project.md存在,用一行总结上次会话并询问是否继续。 - 导入。 如果他没有提供路径:
$Y/cap.py find并确认录音。不是 Cap:将相机文件链接为source/cam.mov(屏幕录制为source/screen.mp4使用一个时钟;一个极简的cap.json)。收集脚本、链接以及他希望展示的任何内容。品牌:$Y/brand.py init --edit-dir edit(Stripe;如果为另一家公司则使用--brand x.json),然后从品牌文件命名的官方套件中获取 Logo 到edit/logos/。在构建其余场景之前,先测试一个场景下的品牌。 - 导入并读取。
ffprobe;一个全分辨率静帧用于镜像检查;$R/transcribe.py source/cam.mov --edit-dir edit --vocab "<script/links 中的每个名称>";$R/pack_transcripts.py;$R/headpose.py对整个录制内容进行处理 →headpose_report.txt(他在行与行之间阅读笔记——低头看稿必须去除)。 - 剪辑。 Cap 修剪 → 移除重拍、填充词(列出供否决)、花絮、静音(硬性规则 3-4)。编写
edl.json(源CAM,1920x1080 @ 30,适合裁剪,grade: "auto",end_hold: 0),$R/render.py edl.json -o edit/base.mp4 --base-only,$R/verify_cuts.py edl.json并修复每个被剪切的词。单独转录每个保留范围以及与其相邻范围的每次拼接;删除任何仍然出现两次的台词、其他录制的片段以及范围边缘的碎片。然后$Y/lookdowns.py --edit-dir edit和$Y/sync_check.py --edit-dir edit(必须显示 OK)。 - 修正的转录。 从逐个范围转录构建
transcripts/CAM.json,将其映射回源时间(整个文件的转录会在拼接处模糊词时间,大约偏差 1 秒),修正名称拼写和误听词,删除被剪切的词。字幕、对话字幕和场景中的词汇都来源于此。 - 章节大纲 → 批准 #1(
references/planning.md§1)。等待。 - 参考浏览。 他提到的所有内容:验证真实来源(文件、研究、帖子——阅读,注意确切数字),
$R/capture.py --readable --phrases,$R/fetch.py logo/photo/icon;一份 Logo/照片单页,确认每个(有一次“徽章”照片结果是一个水壶——查看每个资产)。 - 节拍表 → 批准 #2(
references/planning.md§2)。等待。 - 构建。
- 编写
layout.json(ca
- 编写
…
[因翻译截断]