diff --git a/AGENTS.md b/AGENTS.md index 9987d85..0fa4cac 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,7 +9,7 @@ 0. **定档位和导演模式**:先确定这支片子的努力程度(effort):`quick`、`standard` 还是 `studio`;再看人要亲自拍板哪些事(导演模式)。规则见"努力程度"和"导演模式"两节。后面每一步做多少、在哪里停,都按这两样来。`quick` 直接照"quick 路径卡"做。 1. **判断类型**:用下面的路由表,读对应的 `video-types/*.md`(其中的"Prompt 增量块"留到想完立意再读)。一个视频可能横跨两类(例如"论文讲解"做成竖屏短视频),就两份都读,以主类型为准。 - - **一句话需求是常态**:389 支社区 Opus 5.5 作品里,完整提示词的中位数不到 30 个词,四分之一直接套用同一句 showreel 提示词(见 `cases/opus55-gallery.md`)。收到一句话时,先想立意(第 4 步),再用类型文档的默认值补全 BRIEF 里剩下的项;把关卡 ① 的审阅页写短,最多问 3 个真正影响制作的问题,不要反过来追问一长串。 + - **一句话需求是常态**:389 支社区 Opus 5.5 作品里,完整提示词的中位数不到 30 个词,四分之一直接套用同一句 showreel 提示词(见 `cases/opus55-gallery.md`)。收到一句话时,先想立意(第 4 步),再用类型文档的默认值补全 BRIEF 里剩下的项;把关卡 ① 的审阅页写短,最多问 3 个真正影响制作的问题,不要反过来追问一长串。规格(画幅、分辨率、帧率、时长、在哪看)按 `playbook/01-pipeline.md` 的"规格"补:`bin/vh new` 填好"在哪看"和分辨率(HyperFrames 类型还有画幅),帧率和时长照那里的表。只有需求没说发在哪、而它又会改变画幅或字号下限时(例如一支横屏产品片,没说发 B 站还是抖音),才当成一个问题问;说了平台,就按下面的对应关系定"在哪看"。 2. **读流程和自查**:读 `playbook/01-pipeline.md` 和 `playbook/02-verification.md`;涉及配音或音乐时,再读 `playbook/04-audio.md`。 3. **建项目**:运行 `bin/vh new `,它会建好 `projects/<日期>-/`,复制模板,并把该类型的 prompt 块填进 BRIEF(类型的默认做法,立意定了再取舍);手绘类还会复制引擎、装好依赖。其他引擎的初始化方式见 `engines/README.md`。 4. **先想立意,再看案例和参考**:建完项目,先把材料里只属于它的数字、原话、物件列进 NOTES.md 的素材清单,自己想 5–8 个点子;这时先不看 BRIEF 末尾的 TYPE 块、`styles/`、`recipes/` 和案例,免得点子往看过的东西上靠。然后再看下面这些参考,用它们补强,收敛成 2–3 张立意卡(做法见 `playbook/12-ideation.md`,例子见 `cases/oneshot-five.md`)。人已经给了立意,就记进 BRIEF,不再出卡,最多附一个备选。参考:打开类型文档"可参考的案例"和"社区 skill 参考"两节列出的文件;需要看真实代码时读 `references/repos/` 里的源码。本仓库自己做过的片子在 `showcase/`,各带 BRIEF、STORYBOARD、NOTES 和源码,是最直接的样板。分镜时,镜头怎么动、全片节奏怎么排,先查 `recipes/`:按意图和能量筛(`bin/vh recipes list`),把选中的配方 id 写进 STORYBOARD 的"配方"列,写代码前读配方全文。 @@ -41,7 +41,7 @@ | 立意 | 自己想 3 个一句话点子,挑 1 个,写一行理由 | 关卡 ① 给 2–3 张立意卡,每张配一帧画面 | 同左,每张配一段 10–20 s 的草图(look-dev) | | 风格 | 从立意推出来,可以借 `styles/` 的 1 个预设,写明理由 | 写在每张立意卡的"画面"一行(专属,或借一个预设);选卡就一起定了,人可以在回复里换 | 同左;每张卡的草图就是那种风格的小样,借来的预设人想看时在 E0 补小样 | | 分镜 | 简表:镜头、时长、reads | 完整 STORYBOARD + 分镜预览图 | 同左 + animatic | -| 自查 | 整片一张联系表、一张手机联系表、前 2 s 的 strip,20 条清单速查一遍 | 每个场景:联系表、关键动作 strip、局部 crop;20 条清单 | 同左,再加手机尺寸测试、循环接缝、无损帧确定性、静默故障扫描 | +| 自查 | 整片一张联系表、一张按目标屏缩的联系表、前 2 s 的 strip,20 条清单速查一遍 | 每个场景:联系表、关键动作 strip、局部 crop;20 条清单 | 同左,再加目标屏尺寸测试、循环接缝、无损帧确定性、静默故障扫描 | | 独立评审(打分层) | 不做 | 1 轮:全新上下文的 reviewer 打 8 项分(含立意),修最差的 3 处 | ≥ 3 轮,8 项都 ≥ 8 才出片;达不到就带着分数进关卡 ③ | | 声音 | 可以没有,或一段配乐 / 配音加基础混音 | 配乐或配音 + 关键动作音效 + 按视频类型的混音 profile(`bin/vh mix … profile=`)+ `bin/vh qa` | 同左 + 每个动作的拟音和声像 + 最终混音 cue check + 混音报告(`bin/vh qa mix`)没有硬失败 | | 渲染与交付 | draft 画质即可,一个 mp4 | 正式画质 mp4 + 联系表 | 同左 + 网页版、GIF、封面,按需出 9:16 | @@ -57,7 +57,7 @@ - 硬规则 1(每一帧是 t 的纯函数)、5(事实照抄原文)、7(不在文件里写 key); - 片中不出现数字静音(管有声片;用户要的无声片不带音轨,不适用); - 全屏闪白每秒不超过 3 次; -- 字号不低于清单下限; +- 字号不低于 BRIEF"在哪看"那一档的下限(`playbook/03-motion-design.md` §4); - 素材许可要记清; - `TASTE_CHECKLIST.md` 里标【底线】的条目:安全框、读时、字号、字不被光烧白、reads 不被盖掉、循环接缝、分镜里声明的卡点、没有占位和编造; - 出片前跑一次 `bin/vh check`。 @@ -71,7 +71,7 @@ effort 管 agent 自己查得多细,导演模式管人拍板哪些事,两个开关互不影响:"quick 出片,但钩子我定""做成精品,风格和封面我来定"都说得通。 - **怎么定**:用户在对话里说的 > BRIEF 的 `Director:` 行 > LOCAL.md 的默认 > 档位默认,人点名的永远优先。例如 `Director: hook=own, character=own, theme=own, packaging=own, rest=delegate`;人说"配音配乐定稿前也停一下",就加 `stop=E3`。 -- **能点名的事**:`concept` 立意、`outline` 大纲、`style` 风格、`character` 主角、`theme` 主旋律、`voice` 配音、`script` 旁白稿、`hook` 钩子、`storyboard` 分镜、`rhythm` 剪辑节奏、`packaging` 标题和封面。每件最早在哪一站能定、给人看什么、以后再改要花多少,见 `playbook/01-pipeline.md` 的"导演模式"。 +- **能点名的事**:`concept` 立意、`spec` 规格(画幅、分辨率、帧率、时长、在哪看)、`outline` 大纲、`style` 风格、`character` 主角、`theme` 主旋律、`voice` 配音、`script` 旁白稿、`hook` 钩子、`storyboard` 分镜、`rhythm` 剪辑节奏、`packaging` 标题和封面。每件最早在哪一站能定、给人看什么、以后再改要花多少,见 `playbook/01-pipeline.md` 的"导演模式"。 - **每件事三种拍板方式**: - `own`:agent 出选项、附推荐,停下来等人选; - `review`:agent 出一个结果,放进下一页(没有下一页就随交付给),不为它单独停,人不说话就算通过; @@ -88,7 +88,7 @@ effort 管 agent 自己查得多细,导演模式管人拍板哪些事,两个 2. **建项目和立意**:`bin/vh new --effort quick`。先写 3 个一句话立意,挑一个(`playbook/12-ideation.md` 第 7 节最后一条),再读 BRIEF 末尾的 TYPE 块,决定留哪些默认。风格从立意推出来,合适的话借一个预设:`bin/vh style apply `(`bin/vh style list` 挑),它的 `STYLE_PRESET.md` 会带进项目,写代码前读一遍。立意和风格各写一行理由进 `DECISIONS.md`;改了哪些口味默认,交付时一并列出。 3. **写**:补齐 BRIEF;分镜只写简表(镜头、时长、reads);然后写场景代码。HyperFrames 写完一段,用 `npx hyperframes snapshot --at <秒> --describe false` 看几个关键时刻。 4. **出片**:HyperFrames 先 `export HYPERFRAMES_SKIP_SKILLS=1 DO_NOT_TRACK=1`,再 `npx hyperframes render --quality draft --output out/draft.mp4`;手绘类用 `node render.mjs --clip --out=out/draft.mp4`。 -5. **自查一遍**:`bin/vh sheet out/draft.mp4` 看整片联系表,对着 `TASTE_CHECKLIST.md` 的 20 条速查;有字就跑 `bin/vh readcheck`。再看两样(命令见 `playbook/02-verification.md` 的"手机测试"):一张手机尺寸的联系表,必读字在手机上读不读得出(横屏片的 44 px 在 360 px 宽的联系表上只有约 8 px,读数、标签别贴着下限);前 2 s 的逐帧 strip,开头是不是第 0 帧就在动、有没有让人停下来的东西。`quick` 没有 reviewer,这两样最容易漏(`docs/research/06-concept-first-ab.md`)。 +5. **自查一遍**:`bin/vh sheet out/draft.mp4` 看整片联系表,对着 `TASTE_CHECKLIST.md` 的 20 条速查;有字就跑 `bin/vh readcheck`。再看两样(命令见 `playbook/02-verification.md` 的"手机测试"):一张按目标屏缩的联系表(BRIEF 的 `Watch on`:phone、feed 缩到 360 px 宽,desktop 缩到 640),必读字读不读得出,读数、标签别贴着下限;前 2 s 的逐帧 strip,开头是不是第 0 帧就在动、有没有让人停下来的东西。`quick` 没有 reviewer,这两样最容易漏(`docs/research/06-concept-first-ab.md`)。 6. **声音**(要的话):`bin/vh music` 或 `bin/vh tts`,再 `bin/vh mix`、`bin/vh qa`、`bin/vh mux`。 7. **交付**:`bin/vh check` 必跑;交 mp4 路径、联系表,以及自己最不满意的 1–2 处。 diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ff1690..a1de055 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ ## Unreleased +**Spec up front: where it is watched sets the text-size floor; 4K is a render setting** +- Why: research note 06 left open whether the 44 px floor, written for 1080 wide, should scale for landscape. The maintainer's answer: it depends on where the film is watched, a phone or a computer, and a landscape 4K film on a computer does not need text scaled up in proportion; and the spec (resolution, 4K or 1080p, and so on) should be set at the start, guided or defaulted. +- **Where it is watched**: the BRIEF has `Watch on: phone | feed | desktop` (a vertical phone; a landscape film in a phone feed, not rotated; a computer, or a phone turned sideways) and `Resolution: 1080p | 4k`. `bin/vh new` fills both from the type and frame (portrait and square → phone, landscape → desktop, landscape memes → feed, editing → phone; 1080p) and takes `--watch` and `--res` (`4K` and `2160p` are aliases); it refuses `--res 4k` for the hand-drawn engine, which has no 4K output, and targets that contradict the frame (feed for a vertical or square frame, phone for a landscape one). CI covers defaults, flags, the alias and each refusal's message. +- **Text-size floors by target** (`playbook/03-motion-design.md` §4, TASTE_CHECKLIST #6), in 1080p composition px: phone 84 / 44 / captions 65, desktop 84 / 44 / 48, feed 150 / 80 / 115, chosen so secondary text lands at about 15 px on a phone in both phone tiers and 15–23 px in desktop (a phone turned sideways shows a 16:9 film about 640–760 px wide, limited by its height; a default computer player about 850–1000). On-screen size depends on the text's share of the frame, not the resolution, so 4K is written at 1080p and rendered at 2× (HyperFrames `render --resolution 4k`, `portrait-4k` or `square-4k` to match the frame; Manim `-qk --fps 30`; 2D canvases sized and scaled by `devicePixelRatio` and Three.js `setPixelRatio`, `engines/README.md`; a frame or two of the 4K render cropped to check sharpness); a film for a feed should rather get its own vertical cut. +- **Readability by target**: the scoring dimension 手机可读 becomes 目标屏可读; the quick self-check, `playbook/02`'s phone test (360 px for phone and feed, 640 px for desktop, with a desktop command) and playbook 12 §6 follow. +- **Spec as a decision**: `playbook/01-pipeline.md` gets a spec section with defaults per type, a platform-to-target mapping (vertical, 1:1, 4:5 → phone; landscape on 抖音, 视频号, 小红书, 微博, X → feed; B站, YouTube, a website → desktop) and when to ask (only when no platform is named and it would change the frame or the floor), a `spec` row at gate ①; `spec` is a nameable decision in director mode (CLAUDE.md, DECISIONS template, both READMEs); CLAUDE.md's floor list points to the tiered floor. + **Style swatches can be Blender scenes; a 29th style, tabletop-miniature (桌面微缩剧场)** - Why: every swatch is drawn on a canvas, and none looks like a lit, physical set. Taking apart a community film (Kevin Ngo's piano short, made with Python and rendered in Blender) gave a stop-motion miniature grammar whose look rests on path-traced light and real depth of field, so the swatch renderer needed a Blender path. Blender 5.2.2 is now installed on the maintainer's Mac. - `styles/_swatch/`: a style folder with `swatch.py` instead of `swatch.js` renders in Blender (Cycles). `blender_render.py` runs the scene's `build(env)` once per process and `apply(t, env)` before every frame, setting properties directly (no keyframes, no handlers, so no motion blur, which suits stop-motion). It writes PNG frames, and `render.sh` encodes them into the same 1080p BT.709 `hf.mp4` the HyperFrames path makes, so the frame checks, music, foley, mix, `bin/vh qa`, encode, poster and contact sheet are shared. New `render.sh` options for Blender scenes: `--frames 149,90,12` (with `--png`: only those frames, in that order) and `--stamp`. diff --git a/CLAUDE.md b/CLAUDE.md index b69b697..df44679 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,7 +6,7 @@ 0. **定档位和导演模式**:先确定这支片子的努力程度(effort):`quick`、`standard` 还是 `studio`;再看人要亲自拍板哪些事(导演模式)。规则见"努力程度"和"导演模式"两节。后面每一步做多少、在哪里停,都按这两样来。`quick` 直接照"quick 路径卡"做。 1. **判断类型**:用下面的路由表,读对应的 `video-types/*.md`(其中的"Prompt 增量块"留到想完立意再读)。一个视频可能横跨两类(例如"论文讲解"做成竖屏短视频),就两份都读,以主类型为准。 - - **一句话需求是常态**:389 支社区 Opus 5.5 作品里,完整提示词的中位数不到 30 个词,四分之一直接套用同一句 showreel 提示词(见 `cases/opus55-gallery.md`)。收到一句话时,先想立意(第 4 步),再用类型文档的默认值补全 BRIEF 里剩下的项;把关卡 ① 的审阅页写短,最多问 3 个真正影响制作的问题,不要反过来追问一长串。 + - **一句话需求是常态**:389 支社区 Opus 5.5 作品里,完整提示词的中位数不到 30 个词,四分之一直接套用同一句 showreel 提示词(见 `cases/opus55-gallery.md`)。收到一句话时,先想立意(第 4 步),再用类型文档的默认值补全 BRIEF 里剩下的项;把关卡 ① 的审阅页写短,最多问 3 个真正影响制作的问题,不要反过来追问一长串。规格(画幅、分辨率、帧率、时长、在哪看)按 `playbook/01-pipeline.md` 的"规格"补:`bin/vh new` 填好"在哪看"和分辨率(HyperFrames 类型还有画幅),帧率和时长照那里的表。只有需求没说发在哪、而它又会改变画幅或字号下限时(例如一支横屏产品片,没说发 B 站还是抖音),才当成一个问题问;说了平台,就按下面的对应关系定"在哪看"。 2. **读流程和自查**:读 `playbook/01-pipeline.md` 和 `playbook/02-verification.md`;涉及配音或音乐时,再读 `playbook/04-audio.md`。 3. **建项目**:运行 `bin/vh new `,它会建好 `projects/<日期>-/`,复制模板,并把该类型的 prompt 块填进 BRIEF(类型的默认做法,立意定了再取舍);手绘类还会复制引擎、装好依赖。其他引擎的初始化方式见 `engines/README.md`。 4. **先想立意,再看案例和参考**:建完项目,先把材料里只属于它的数字、原话、物件列进 NOTES.md 的素材清单,自己想 5–8 个点子;这时先不看 BRIEF 末尾的 TYPE 块、`styles/`、`recipes/` 和案例,免得点子往看过的东西上靠。然后再看下面这些参考,用它们补强,收敛成 2–3 张立意卡(做法见 `playbook/12-ideation.md`,例子见 `cases/oneshot-five.md`)。人已经给了立意,就记进 BRIEF,不再出卡,最多附一个备选。参考:打开类型文档"可参考的案例"和"社区 skill 参考"两节列出的文件;需要看真实代码时读 `references/repos/` 里的源码。本仓库自己做过的片子在 `showcase/`,各带 BRIEF、STORYBOARD、NOTES 和源码,是最直接的样板。分镜时,镜头怎么动、全片节奏怎么排,先查 `recipes/`:按意图和能量筛(`bin/vh recipes list`),把选中的配方 id 写进 STORYBOARD 的"配方"列,写代码前读配方全文。 @@ -38,7 +38,7 @@ | 立意 | 自己想 3 个一句话点子,挑 1 个,写一行理由 | 关卡 ① 给 2–3 张立意卡,每张配一帧画面 | 同左,每张配一段 10–20 s 的草图(look-dev) | | 风格 | 从立意推出来,可以借 `styles/` 的 1 个预设,写明理由 | 写在每张立意卡的"画面"一行(专属,或借一个预设);选卡就一起定了,人可以在回复里换 | 同左;每张卡的草图就是那种风格的小样,借来的预设人想看时在 E0 补小样 | | 分镜 | 简表:镜头、时长、reads | 完整 STORYBOARD + 分镜预览图 | 同左 + animatic | -| 自查 | 整片一张联系表、一张手机联系表、前 2 s 的 strip,20 条清单速查一遍 | 每个场景:联系表、关键动作 strip、局部 crop;20 条清单 | 同左,再加手机尺寸测试、循环接缝、无损帧确定性、静默故障扫描 | +| 自查 | 整片一张联系表、一张按目标屏缩的联系表、前 2 s 的 strip,20 条清单速查一遍 | 每个场景:联系表、关键动作 strip、局部 crop;20 条清单 | 同左,再加目标屏尺寸测试、循环接缝、无损帧确定性、静默故障扫描 | | 独立评审(打分层) | 不做 | 1 轮:全新上下文的 reviewer 打 8 项分(含立意),修最差的 3 处 | ≥ 3 轮,8 项都 ≥ 8 才出片;达不到就带着分数进关卡 ③ | | 声音 | 可以没有,或一段配乐 / 配音加基础混音 | 配乐或配音 + 关键动作音效 + 按视频类型的混音 profile(`bin/vh mix … profile=`)+ `bin/vh qa` | 同左 + 每个动作的拟音和声像 + 最终混音 cue check + 混音报告(`bin/vh qa mix`)没有硬失败 | | 渲染与交付 | draft 画质即可,一个 mp4 | 正式画质 mp4 + 联系表 | 同左 + 网页版、GIF、封面,按需出 9:16 | @@ -54,7 +54,7 @@ - 硬规则 1(每一帧是 t 的纯函数)、5(事实照抄原文)、7(不在文件里写 key); - 片中不出现数字静音(管有声片;用户要的无声片不带音轨,不适用); - 全屏闪白每秒不超过 3 次; -- 字号不低于清单下限; +- 字号不低于 BRIEF"在哪看"那一档的下限(`playbook/03-motion-design.md` §4); - 素材许可要记清; - `TASTE_CHECKLIST.md` 里标【底线】的条目:安全框、读时、字号、字不被光烧白、reads 不被盖掉、循环接缝、分镜里声明的卡点、没有占位和编造; - 出片前跑一次 `bin/vh check`。 @@ -68,7 +68,7 @@ effort 管 agent 自己查得多细,导演模式管人拍板哪些事,两个开关互不影响:"quick 出片,但钩子我定""做成精品,风格和封面我来定"都说得通。 - **怎么定**:用户在对话里说的 > BRIEF 的 `Director:` 行 > LOCAL.md 的默认 > 档位默认,人点名的永远优先。例如 `Director: hook=own, character=own, theme=own, packaging=own, rest=delegate`;人说"配音配乐定稿前也停一下",就加 `stop=E3`。 -- **能点名的事**:`concept` 立意、`outline` 大纲、`style` 风格、`character` 主角、`theme` 主旋律、`voice` 配音、`script` 旁白稿、`hook` 钩子、`storyboard` 分镜、`rhythm` 剪辑节奏、`packaging` 标题和封面。每件最早在哪一站能定、给人看什么、以后再改要花多少,见 `playbook/01-pipeline.md` 的"导演模式"。 +- **能点名的事**:`concept` 立意、`spec` 规格(画幅、分辨率、帧率、时长、在哪看)、`outline` 大纲、`style` 风格、`character` 主角、`theme` 主旋律、`voice` 配音、`script` 旁白稿、`hook` 钩子、`storyboard` 分镜、`rhythm` 剪辑节奏、`packaging` 标题和封面。每件最早在哪一站能定、给人看什么、以后再改要花多少,见 `playbook/01-pipeline.md` 的"导演模式"。 - **每件事三种拍板方式**: - `own`:agent 出选项、附推荐,停下来等人选; - `review`:agent 出一个结果,放进下一页(没有下一页就随交付给),不为它单独停,人不说话就算通过; @@ -85,7 +85,7 @@ effort 管 agent 自己查得多细,导演模式管人拍板哪些事,两个 2. **建项目和立意**:`bin/vh new --effort quick`。先写 3 个一句话立意,挑一个(`playbook/12-ideation.md` 第 7 节最后一条),再读 BRIEF 末尾的 TYPE 块,决定留哪些默认。风格从立意推出来,合适的话借一个预设:`bin/vh style apply `(`bin/vh style list` 挑),它的 `STYLE_PRESET.md` 会带进项目,写代码前读一遍。立意和风格各写一行理由进 `DECISIONS.md`;改了哪些口味默认,交付时一并列出。 3. **写**:补齐 BRIEF;分镜只写简表(镜头、时长、reads);然后写场景代码。HyperFrames 写完一段,用 `npx hyperframes snapshot --at <秒> --describe false` 看几个关键时刻。 4. **出片**:HyperFrames 先 `export HYPERFRAMES_SKIP_SKILLS=1 DO_NOT_TRACK=1`,再 `npx hyperframes render --quality draft --output out/draft.mp4`;手绘类用 `node render.mjs --clip --out=out/draft.mp4`。 -5. **自查一遍**:`bin/vh sheet out/draft.mp4` 看整片联系表,对着 `TASTE_CHECKLIST.md` 的 20 条速查;有字就跑 `bin/vh readcheck`。再看两样(命令见 `playbook/02-verification.md` 的"手机测试"):一张手机尺寸的联系表,必读字在手机上读不读得出(横屏片的 44 px 在 360 px 宽的联系表上只有约 8 px,读数、标签别贴着下限);前 2 s 的逐帧 strip,开头是不是第 0 帧就在动、有没有让人停下来的东西。`quick` 没有 reviewer,这两样最容易漏(`docs/research/06-concept-first-ab.md`)。 +5. **自查一遍**:`bin/vh sheet out/draft.mp4` 看整片联系表,对着 `TASTE_CHECKLIST.md` 的 20 条速查;有字就跑 `bin/vh readcheck`。再看两样(命令见 `playbook/02-verification.md` 的"手机测试"):一张按目标屏缩的联系表(BRIEF 的 `Watch on`:phone、feed 缩到 360 px 宽,desktop 缩到 640),必读字读不读得出,读数、标签别贴着下限;前 2 s 的逐帧 strip,开头是不是第 0 帧就在动、有没有让人停下来的东西。`quick` 没有 reviewer,这两样最容易漏(`docs/research/06-concept-first-ab.md`)。 6. **声音**(要的话):`bin/vh music` 或 `bin/vh tts`,再 `bin/vh mix`、`bin/vh qa`、`bin/vh mux`。 7. **交付**:`bin/vh check` 必跑;交 mp4 路径、联系表,以及自己最不满意的 1–2 处。 diff --git a/README.md b/README.md index d6040a9..43f7bd2 100644 --- a/README.md +++ b/README.md @@ -188,7 +188,7 @@ Not every film deserves the full treatment. One switch controls how much effort |---|---|---|---| | For | trying a direction, drafts, casual posts | most real videos | launch films, flagship pieces | | Stops to ask you | never; it just renders | at the outline, storyboard and first draft | the same three, plus a rendered sketch of each concept and a full-length animatic | -| Checks its own work | one contact sheet for the whole film | frames and sound, section by section | plus phone size, determinism and a full audio check | +| Checks its own work | one contact sheet for the whole film | frames and sound, section by section | plus target-screen size, determinism and a full audio check | | Outside reviewer | none | 1 round | at least 3 rounds, all 8 scores at 8+ | | A 30 s film takes about | 10–30 min | 1–2 h | 3 h or more | @@ -196,7 +196,7 @@ Just say "quick draft" or "make it studio quality" in your request, or start the ### You choose what you decide -Effort sets how hard the agent checks its own work; director mode sets what you decide yourself. Each of eleven decisions (concept, outline, script, style, hook, main character, theme music, storyboard, edit rhythm, voice, title and cover) can be yours to **own** (it shows you options and waits), yours to **review** (it shows you the result and carries on unless you object), or **delegated** (it decides and writes down why in `DECISIONS.md`). Every stop is, by default, a local page from `bin/vh review`: at most three decisions on the first screen, each with a recommendation and a one-line reply, then pictures, the animatic and music you can play in the browser. `standard` and `studio` still stop at the concept and outline, storyboard and first draft. +Effort sets how hard the agent checks its own work; director mode sets what you decide yourself. Each of twelve decisions (concept, spec, outline, script, style, hook, main character, theme music, storyboard, edit rhythm, voice, title and cover) can be yours to **own** (it shows you options and waits), yours to **review** (it shows you the result and carries on unless you object), or **delegated** (it decides and writes down why in `DECISIONS.md`). Every stop is, by default, a local page from `bin/vh review`: at most three decisions on the first screen, each with a recommendation and a one-line reply, then pictures, the animatic and music you can play in the browser. `standard` and `studio` still stop at the concept and outline, storyboard and first draft. > **Deep involvement:** a 90 s explainer on how satellites avoid collisions, studio quality. I'll pick the hook, the main character, the theme melody, and the title and cover; decide the rest yourself. diff --git a/README.zh-CN.md b/README.zh-CN.md index ed1b4ad..6e10d3d 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -188,7 +188,7 @@ bin/vh new promo launch-film --style cutout-jazz # 建项目时直接带上一 |---|---|---|---| | 适合 | 试方向、草稿、随手发 | 大多数正式视频 | 发布片、旗舰内容 | | 停下来问你 | 不问,直接出片 | 大纲、分镜、初版三次 | 三次,外加每个立意的真渲草图和全片灰模预演 | -| 自己检查 | 整片一张联系表 | 每一段都看帧、测声音 | 再加手机尺寸、确定性、音频全检 | +| 自己检查 | 整片一张联系表 | 每一段都看帧、测声音 | 再加目标屏尺寸、确定性、音频全检 | | 找人打分 | 不找 | 1 轮 | 至少 3 轮,8 项都要 8 分 | | 30 秒的片子大概要 | 10–30 分钟 | 1–2 小时 | 3 小时以上 | @@ -196,7 +196,7 @@ bin/vh new promo launch-film --style cutout-jazz # 建项目时直接带上一 ### 哪些事你来拍板 -努力程度管 agent 自己查多细,导演模式管哪些事由你拍板。立意、大纲、旁白稿、风格、钩子、主角、主旋律、分镜、剪辑节奏、配音、标题和封面,这十一件事每件都可以设成 **own**(出几个选项,等你挑)、**review**(出一个结果给你看,你不说话就算通过)或 **delegate**(它自己定,理由写进 `DECISIONS.md`)。每次停下来,默认给你一个本地页面(`bin/vh review`):第一屏最多三件要你定的事,每件带推荐和一句回复写法,下面是能在浏览器里直接看、直接听的图、animatic 和配乐。`standard` 和 `studio` 照样在立意和大纲、分镜、初版三处停。 +努力程度管 agent 自己查多细,导演模式管哪些事由你拍板。立意、规格、大纲、旁白稿、风格、钩子、主角、主旋律、分镜、剪辑节奏、配音、标题和封面,这十二件事每件都可以设成 **own**(出几个选项,等你挑)、**review**(出一个结果给你看,你不说话就算通过)或 **delegate**(它自己定,理由写进 `DECISIONS.md`)。每次停下来,默认给你一个本地页面(`bin/vh review`):第一屏最多三件要你定的事,每件带推荐和一句回复写法,下面是能在浏览器里直接看、直接听的图、animatic 和配乐。`standard` 和 `studio` 照样在立意和大纲、分镜、初版三处停。 > **深度参与**:做一支 90 秒的知识视频,讲卫星怎么避免相撞,要精品。钩子、主角、主旋律、标题和封面我来定,其余你定。 diff --git a/bin/vh b/bin/vh index af402f9..a5f1ae3 100755 --- a/bin/vh +++ b/bin/vh @@ -8,7 +8,7 @@ # make # types list video types and their docs # effort [quick|standard|studio] how much iteration, review and polish each level means (CLAUDE.md "努力程度") -# new [--style ] [--effort quick|standard|studio] [--aspect 16:9|9:16|1:1] [--dir ] +# new [--style ] [--effort quick|standard|studio] [--aspect 16:9|9:16|1:1] [--watch phone|feed|desktop] [--res 1080p|4k] [--dir ] # create projects/- from templates (+ engine: p5 for handdrawn/mv, HyperFrames for short/promo/data/meme); # --aspect: short/promo/data/meme only; --dir (or $OVH_PROJECTS): make it in /- outside the harness # style list | [--draft] | gallery [--mp4] | check style library: list presets, render a 5 s swatch, build styles/gallery.jpg @@ -259,18 +259,23 @@ PY } cmd_new() { - [ $# -ge 2 ] || { echo "usage: bin/vh new [--style ] [--effort quick|standard|studio] [--aspect 16:9|9:16|1:1] [--dir ]"; cmd_types; exit 1; } - local type=$1 slug=$2 doc style="" effort="" aspect="" res="" parent="" wh=""; doc=$(type_doc "$type") || { echo "unknown type: $type"; cmd_types; exit 1; } + [ $# -ge 2 ] || { echo "usage: bin/vh new [--style ] [--effort quick|standard|studio] [--aspect 16:9|9:16|1:1] [--watch phone|feed|desktop] [--res 1080p|4k] [--dir ]"; cmd_types; exit 1; } + local type=$1 slug=$2 doc style="" effort="" aspect="" res="" parent="" wh="" watch="" outres=""; doc=$(type_doc "$type") || { echo "unknown type: $type"; cmd_types; exit 1; } shift 2 while [ $# -gt 0 ]; do case "$1" in --style) style=${2:?--style needs a preset (bin/vh style list)}; shift 2 ;; --effort) effort=${2:?--effort needs quick, standard or studio}; shift 2 ;; --aspect) aspect=${2:?--aspect needs 16:9, 9:16 or 1:1}; shift 2 ;; --dir) parent=${2:?--dir needs a folder: the project goes in /-}; shift 2 ;; + --watch) watch=${2:?--watch needs phone, feed or desktop}; shift 2 ;; + --res) outres=${2:?--res needs 1080p or 4k}; shift 2 ;; *) echo "unknown option: $1"; exit 1 ;; esac; done [ -z "$style" ] || [ -f "$ROOT/styles/$style/STYLE.md" ] || { echo "unknown style: $style"; cmd_style list; exit 1; } case "${effort:-standard}" in quick|standard|studio) ;; *) echo "unknown effort: $effort (quick | standard | studio)"; exit 1 ;; esac + case "$watch" in ""|phone|feed|desktop) ;; *) echo "unknown --watch: $watch (phone: a vertical phone · feed: landscape in a phone feed, not rotated · desktop: a computer, or a phone turned sideways)"; exit 1 ;; esac + case "$outres" in ""|1080p) ;; 4k|4K|2160p) outres=4k ;; *) echo "unknown --res: $outres (1080p | 4k)"; exit 1 ;; esac + if [ "$outres" = 4k ]; then case "$type" in handdrawn|mv) echo "--res 4k: the hand-drawn engine (ClaudeAnimationBase) has no 4K output yet; use 1080p, or another engine (engines/README.md)"; exit 1 ;; esac; fi if [ -n "$aspect" ]; then # HyperFrames types scaffold at any of the three; the other engines set their size themselves case "$aspect" in 16:9|landscape) res=landscape; aspect=16:9 ;; 9:16|portrait) res=portrait; aspect=9:16 ;; 1:1|square) res=square; aspect=1:1 ;; *) echo "unknown aspect: $aspect (16:9 | 9:16 | 1:1)"; exit 1 ;; esac @@ -279,6 +284,14 @@ cmd_new() { fi case "$type" in short) res=${res:-portrait} ;; promo|data|meme) res=${res:-landscape} ;; esac case "$res" in portrait) wh=1080x1920 ;; square) wh=1080x1080 ;; landscape) wh=1920x1080 ;; esac + if [ -z "$watch" ]; then # where it is mostly watched sets the text-size floor (playbook/03 §4); the frame gives the default + case "$res:$type" in portrait:*|square:*|:edit) watch=phone ;; landscape:meme) watch=feed ;; *) watch=desktop ;; esac + fi + local frame=$res; case "$type" in math|paper) frame=${frame:-landscape} ;; esac # Manim renders landscape + case "$watch:$frame" in # a frame and a target that contradict each other (the feed floor is for a 1920-wide frame) + feed:portrait|feed:square) echo "--watch feed is for a landscape film shown in a phone feed; a ${aspect:-vertical} frame is already --watch phone"; exit 1 ;; + phone:landscape) echo "--watch phone is for a vertical or square frame; a landscape film watched on a phone is --watch feed (in a feed, not rotated) or desktop (turned sideways)"; exit 1 ;; + esac local base dir; base=$(projects_base "$parent") mkdir -p "$base" || { echo "cannot create $base"; exit 1; } base=$(cd "$base" && pwd); dir="$base/$(date +%F)-$slug" @@ -300,6 +313,7 @@ b = open(brief).read().replace(" - Director: default - Output: {W}x{H}, {fps} fps, exactly {N}s ({frames} frames) +- Watch on: {watch} +- Resolution: {res} - Engine: {HyperFrames | Remotion | Manim CE | ClaudeAnimationBase (p5.brush) | other} - Platform / audience: {where it plays, who watches, sound-on or muted} - Language: {zh-CN | en}, narration: {TTS voice | user recording | song | none} diff --git a/templates/DECISIONS.md b/templates/DECISIONS.md index 75aa7b5..90d1c1c 100644 --- a/templates/DECISIONS.md +++ b/templates/DECISIONS.md @@ -9,6 +9,7 @@ Director: {照抄 BRIEF 的 Director 行;没写就写"按 {effort} 的默认"} | 决定 | 谁拍板 | 状态 | 在哪看 | |---|---|---|---| | concept 立意 | {own / review / delegate} | {待定 / 已定(关卡 ①)} | {REVIEW.md 关卡 ①;立意卡在 out/review/gate-1.html} | +| spec 规格 | | | {BRIEF 的 Spec 几行} | | outline 大纲 | | | | | style 风格 | | | | | character 主角 | | | | diff --git a/templates/TASTE_CHECKLIST.md b/templates/TASTE_CHECKLIST.md index 35508fe..39159bc 100644 --- a/templates/TASTE_CHECKLIST.md +++ b/templates/TASTE_CHECKLIST.md @@ -36,7 +36,7 @@ ffmpeg -i out.mp4 -vf "blackdetect=d=0.3,freezedetect=d=1.5" -af silencedetect=d **文字** 5. 【底线】需要观众读完的文字:同屏超过 8 个英文词,或中文每行超过 16 字(竖屏 72px 时 11 字)?停得不够久?从字完整显示、动画停下那一刻算起,没人念的画面文字(标题、标注、数字卡)要停 max(2.5s, 汉字数 ÷ 4.5 + 其他非空白字符数 ÷ 15 + 1.5s);跟着配音走的字幕条每条 ≥ 1.8s,中文不超过 9 字/秒、英文不超过 20 字符/秒。有时间表就用 `tools/readcheck.py` 逐条算(两条规则为什么不同,见 `playbook/03-motion-design.md` §2)。读的那段时间里,字还在 decode 乱码,或被运动模糊抹花?(真实 UI 截图里的文字、背景纹理文字只要求"看得出是什么",不要求读完) -6. 【底线】字号低于下限(1080 宽主标题 84px / 辅助 44px;竖屏字幕 65px)?按最终成片里的实际大小量:镜头推近后以推近后为准,而且推近后字不能发虚(被放大的元素挂着 CSS `will-change` 时,浏览器会把小尺寸的位图直接放大);Manim 等不以 px 定义字号的引擎,从 1080p 成片的 crop 上量像素。GIF 预览不在考核范围内。 +6. 【底线】字号低于 BRIEF `Watch on` 那一档的下限(`playbook/03-motion-design.md` §4,1080p 合成里的 px:phone 主标题 84 / 辅助 44 / 字幕 65,desktop 84 / 44 / 48,feed 150 / 80 / 115;出 4K 照常按 1080p 写,渲染时放大)?按最终成片里的实际大小量:镜头推近后以推近后为准,而且推近后字不能发虚(被放大的元素挂着 CSS `will-change` 时,浏览器会把小尺寸的位图直接放大);Manim 等不以 px 定义字号的引擎,从 1080p 成片的 crop 上量像素。GIF 预览不在考核范围内。 7. 用了不止一个无衬线族?用斜体做强调?每个词都在强调? 8. 有写着剧情的牌子、标签、说明文字,而本可以用画面演出来? @@ -84,7 +84,7 @@ ffmpeg -i out.mp4 -vf "blackdetect=d=0.3,freezedetect=d=1.5" -af silencedetect=d |---|---|---| | 立意 | 选定的立意落到画面上没有:一句话说得出吗?换个题材还成立吗(还成立就只是风格)?形式在讲内容吗?看完会转述哪一个画面?`playbook/12-ideation.md` 第 5 节 | 1 fps 联系表 + BRIEF 的立意一行 | | hook | 前 2 s 有没有让人停下来的东西(运动、反差、问题)? | 0–2 s 的逐帧 strip | - | 手机可读 | 缩到手机大小,必读字还读得出、主体还认得出吗? | 每格 360 px 宽的手机联系表 | + | 目标屏可读 | 按 BRIEF 的 `Watch on` 缩到那块屏幕的大小,必读字还读得出、主体还认得出吗? | 目标屏联系表:phone、feed 每格 360 px 宽,desktop 每格 640 px 宽 | | 运动质量 | 缓动、重量、跟随、切点衔接像不像专业动效? | 关键动作和转场的 strip | | 变化 | 每 2–4 s 有没有新东西:新构图、新运动或新信息?立意本身要慢的片子(书信体、沉思、单镜头),问的是每一次停留有没有新的含义,不按秒数 | 1 fps 联系表 | | 构图与完成度 | 焦点、留白、对齐、细节有没有打磨到位? | 联系表 + crop | diff --git a/tools/ci.sh b/tools/ci.sh index 5e890b9..c717db0 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -212,7 +212,19 @@ decision_checks() { OVH_PROJECTS="$t/env" vh new math ci-env >/dev/null 2>&1 && [ -f "$(ls -d "$t"/env/*-ci-env 2>/dev/null)/BRIEF.md" ] && ok "OVH_PROJECTS sets where projects go" || bad "OVH_PROJECTS ignored" vh new math ci-x --aspect 16:9 >/dev/null 2>&1; rc=$?; [ $rc = 1 ] && ok "new --aspect is refused for a non-HyperFrames type" || bad "new math --aspect exited $rc" vh new short ci-x --aspect 4:3 >/dev/null 2>&1; rc=$?; [ $rc = 1 ] && ok "new --aspect rejects 4:3" || bad "new --aspect 4:3 exited $rc" + a=$(vh new handdrawn ci-x --res 4k 2>&1); rc=$?; [ $rc = 1 ] && case "$a" in *"no 4K output"*) true ;; *) false ;; esac && ok "new --res 4k is refused for the hand-drawn engine" || bad "new handdrawn --res 4k exited $rc: $a" + a=$(vh new short ci-x --watch tv 2>&1); rc=$?; [ $rc = 1 ] && case "$a" in *"unknown --watch"*) true ;; *) false ;; esac && ok "new --watch rejects an unknown target" || bad "new --watch tv exited $rc: $a" + a=$(vh new short ci-x --watch feed 2>&1); rc=$?; [ $rc = 1 ] && case "$a" in *"already --watch phone"*) true ;; *) false ;; esac && ok "new refuses a feed target for a vertical frame" || bad "new short --watch feed exited $rc: $a" + a=$(vh new promo ci-x --watch phone 2>&1); rc=$?; [ $rc = 1 ] && case "$a" in *"--watch feed"*) true ;; *) false ;; esac && ok "new refuses a phone target for a landscape frame" || bad "new promo --watch phone exited $rc: $a" + vh new math ci-x --watch phone >/dev/null 2>&1; rc=$?; [ $rc = 1 ] && ok "new refuses a phone target for a Manim (landscape) type" || bad "new math --watch phone exited $rc" [ -z "$(ls -d "$ROOT"/projects/*-ci-x 2>/dev/null)" ] || bad "a refused new left a project behind" + # new: where it is watched and the output resolution land in the BRIEF (defaults from the frame, flags override) + if grep -q '^- Watch on: desktop' "$p/BRIEF.md" && grep -q '^- Resolution: 1080p' "$p/BRIEF.md" \ + && OVH_PROJECTS="$t/w" vh new math ci-w --watch feed --res 4k >/dev/null 2>&1 \ + && grep -q '^- Watch on: feed' "$(ls -d "$t"/w/*-ci-w)/BRIEF.md" && grep -q '^- Resolution: 4k' "$(ls -d "$t"/w/*-ci-w)/BRIEF.md" \ + && OVH_PROJECTS="$t/w2" vh new edit ci-e --res 4K >/dev/null 2>&1 && grep -q '^- Watch on: phone' "$(ls -d "$t"/w2/*-ci-e)/BRIEF.md" \ + && grep -q '^- Resolution: 4k' "$(ls -d "$t"/w2/*-ci-e)/BRIEF.md"; then ok "new writes Watch on and Resolution into the BRIEF (defaults, flags, the 4K alias)" + else bad "new: Watch on / Resolution missing or wrong in the BRIEF"; fi # style apply: attach, replace, re-apply without stacking; by name under OVH_PROJECTS vh style apply blueprint "$p" >/dev/null && vh style apply ink-wash "$p" >/dev/null && OVH_PROJECTS="$t/elsewhere" vh style apply ink-wash ci-dir >/dev/null if [ "$(grep -c '^## Style preset' "$p/BRIEF.md")" = 1 ] && grep -q '^## Style preset: ink-wash' "$p/BRIEF.md" && [ "$(grep -c '本项目以风格预设' "$p/STYLE.md")" = 1 ] \