1仕組みと動作原理
実装アプローチは「AEの手法をフレームごとの決定論的レンダラーとして再構築する」こと:1つの解析クロックがplate、matte、各グリフを同時に描画し、コンポジション全体でCSSアニメーションを使用しません(レンダラーが任意の位置へシーク可能である必要があるため)。
One clock paints plate, matte and every glyph. Nothing is a CSS animation.
カメラは真の3Dではなく解析的投影です:各カットはcz(軸方向のドリー)とpx/py(画面シフト)を持ち、すべてのレイヤーは「参照カメラ下の参照スクリーン座標」に存在します。投影式 screen = C + (ref − C)·D0/(D0 − cz) + (px,py) を用い、テキストは15 fpsでステップ送りされカメラも同時にサンプリングされ、7重のゴーストモーションブラーが重ねられます。
as a deterministic per-frame painter for HyperFrames. One analytic clock: CAM3D.render(t) writes every style.
「AEらしさ」はハードウェア性能ではなく、3つの厳格なタイミング規律によって実現されます:テキストを15 fpsにポスタリゼーション(連動するカメラも同時にサンプリング)、7重のゴーストモーションブラー、そしてplateとmatteが毎フレーム動作すること。
Text is posterized (camera AND own animation sampled at 15 fps) with 7-ghost motion blur; the plate/matte move every frame with a directional Gaussian from camera speed.
タイムライン自体はテンプレートに固定されません:セリフに応じてモデルがリアルタイムに4〜6ビートを選択し、文ごとに1グループに分割します。固定されるのは描画コントラクト(15 fpsグリッド、字幕の0.2秒先行、ENTRY変位、深度シャドウ/被写界深度(DOF)計算式)です。
Pick 4–6 beats. Split each spoken clause into its own group.
素材パイプラインは1回限りのprepで処理されます:portion(音声ソース)、反射パディングを施したplate-tall(急激なカメラのパンやドリー時のエッジ露出防止)、同フレームのalpha matte(person.webm)を切り出し、**3者の解像度/フレームレート/総フレーム数を個別に照合**して一致しなければ直ちに exit 1 します。これが「タイムラインの厳密な固定」の根拠となります。
[ "$tn" -eq "$pn" ] && [ "$mn" -eq "$pn" ] || fail "frame counts differ: portion $pn, plate $tn, matte $mn"
フォントメトリクスは生成可能なデータテーブルとして外部化されます:font-metrics.pyがfontToolsを使用して各グリフのアドバンス(em)とline-height 1のベースラインを読み取り、バリアブルフォントは指定された軸で事前インスタンス化されます。エンジンはこの値に基づいて各グリフを独自に配置し(CSSカーニングを無効化)、ブラウザがフォントサイズに応じてopszを適用し幅がずれるのを防ぐため、バリアブル軸はCSS内でも固定する必要があります。
Writes `window.CAM3D_METRICS = {adv: {key: {char: em}}, base: {key: em}}`.
カメラモーションカーブはフィッティングによるものではなく、チュートリアル映像からフレーム単位で計測されたテーブルです:tables.jsにcamA(19フレームのウィップイン+クロール)、camB(引き/安定化/プッシュ)、wipe先端のx座標およびイン入りの残り比率が保存され、30 fpsのフレームインデックスとH/1080に応じたスケーリングが適用されます。
/* tables.js — measured motion tables (skill camera-3d-captions). Frame-indexed at 30 fps; px values are for a 1080-tall frame (scale by H/1080);
手描きスタイルはスキル間での再利用です:インストール済みのp5-paint-animationエンジンを利用して各単語をwrite-onスプライトシートとしてレンダリングします(build-sprites.pyがsubprocessで同エンジンのrender-anim.mjsを呼び出し、フレームディレクトリ読み込み後に削除)。そのため、このスタイルには別スキルのセットアップが前提条件となります。
**Hand-drawn style (optional):** needs the `p5-paint-animation` skill installed and set up (its setup downloads pinned puppeteer, Chrome for Testing, p5 and p5.brush). `build-sprites.py` runs it headlessly; frames are written to that skill's `out/` and removed afterwards.
2コア機能
3外部依存関係
| Kind | Dependency / Endpoint |
|---|---|
| cli | HyperFrames CLI(钉死 0.8.62,经 npx 从 npm 取) |
| cli | ffmpeg / ffprobe(切分、反射补边、探帧率与帧数、最后编码) |
| package | Python3 + fonttools/brotli/numpy/pillow(字体度量与手绘精灵图) |
| network | 抠像模型首次运行下载(人物分割权重 ~170 MB,本地推理) |
| network | GSAP 3.14.2(合成在预览/渲染时由页面加载;参考片 HTML 也引用同一 CDN) |
| package | 跨 skill 依赖:p5-paint-animation 的渲染引擎(仅手绘风格需要;用 render-anim.mjs 生成精灵图) |
| cli | 素材来源:用户自备 take 视频、自备字体(需自行确认嵌入许可)、以及用户自己本地跑的词级转录器 |
4推奨統制措置と判定根拠
- scripts/: ローカルスクリプトまたはコマンドの実行: bash scripts/prep-take.sh <take> <start> <dur> <assets>(ffmpeg/ffprobeのサブプロセス;
- 网络端点: 外部ネットワークアクセスの宣言: registry.npmjs.org:コマンド実行ごとにnpx経由で[email protected]を取得(バージョン固定;latestには非追従)
- 本地工作目录: ファイルの読み書きと成果物の出力: プロジェクト内の assets/:portion.mp4、plate-tall.mp4、person.webm、metrics.js、hand/*.png および
5二重目の独立検証
- [ok] skill 自身是否读凭据(黄/橙分界的关键) — 全目录 process.env / os.environ 只命中 build-sprites.py 的 P5_ENGINE(p5 引擎目录路径);无 API key、token、cookie、keychain、.env 读取。因此按范式的橙档第一条不成立,落黄。
- [ok] 「外部资源」逐条回查调用点 — [email protected] 在 SKILL.md 与 prep-take.sh(HF="[email protected]")两处一致;ffmpeg/ffprobe 在 prep-take.sh 的 ffmpeg/probe() 内可验;fontTools 在 font-metrics.py import 段;GSAP CDN 在 worked-film.html 与 SKILL.md 的 Render time 条;p5 引擎调用在 build-sprites.py 的 subprocess.run(cwd=engine)。
- [ok] prep 阶段的三者对齐自检是否真会失败退出(不是装饰性文字) — prep-take.sh 定义 fail(){ echo ... >&2; exit 1; },并对 plate 尺寸、matte 尺寸、三者的帧率与帧数各写了一条比较分支,任一不符即 exit 1;成功路径打印 'prep-take: plate and matte aligned with the portion ($pn frames @ $pr)'。
- [ok] 手绘风格是否真的复用 p5-paint-animation 引擎,且临时帧会被清理 — build-sprites.py 用 subprocess.run(['node','render-anim.mjs', ...], cwd=engine) 渲染临时 sketch(写在 tempfile 目录,落在自己的 temp 而非引擎内),读引擎 out/_frames_<name>.anim/ 的 PNG 后调用 shutil.rmtree(fdir, ignore_errors=True);与 SKILL.md『frames are written to that skill's out/ and removed afterwards』一致。
- [discrepancy] worked-film.html 能否按 SKILL 的 Build 步骤原样打开(参考片的可运行性声明) — SKILL.md 只说 'its media is not included',但参考片的 <head>/<body> 还引用了 assets/o2o-data.js(注释写 'window.O2O here = assets/kit/tables.js')与 assets/Inter-Variable.woff2、assets/InterTight-900.woff2 等字体文件;o2o-data.js 与这两个 woff2 均不在包内(全量清单已确认)。按 SKILL 的『Copy assets/kit/{cam3d.js,tables.js,finish.js} and metrics.js into the project's assets/』操作仍缺 o2o-data.js,参考片不能原样运行——读者须自行把 tables.js 改名/桥接成 window.O2O 并自带字体。该出入对 pin commit 有效。
- [ok] 15 fps 网格与 0.2 s 提前量是否真在实现里(而不是只写在文档) — cam3d.js 顶部 var W = 1440, H = 1080, CX = 720, CY = 540, FPS = 30, POST = 15, K = 7;,并有 post(t) = Math.floor(t * POST + 1e-4) / POST;SKILL.md 给出 fr(t) = 2·round((t − 0.2)·15)(×2 即 30 fps 渲染下的 15 fps 映射),两处自洽。
- [unlocatable] 『带 grade 与多重影渲染约 2× 成本』的量化声明 — SKILL.md 的 Limits 段写 'Rendering with the grade and many ghost layers costs about 2× a plain render.',包内没有基准脚本或计时数据可复现该倍数;本次为只读侦查且不得运行渲染,故仅作为文档声明记录,不作为已核事实使用。
6結論
70cf48e51fa89f4e…