akari-video 0.1.39 → 0.1.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akari-video",
3
- "version": "0.1.39",
3
+ "version": "0.1.40",
4
4
  "description": "AKARI Video launcher CLI — start an AI-edited video project from any directory: scaffold, connection check, then hand over to Claude Code (or opencode). AKARI Video を opencode や Claude Code で、どのディレクトリからでも始めるための `akari` ランチャー CLI。接続確認(doctor)→ 未セットアップならプロジェクト雛形を作成 → AI エージェントを起動する。外部 npm 依存ゼロ(Node.js 組み込みモジュールのみ)。",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akari-video",
3
- "version": "0.1.39",
3
+ "version": "0.1.40",
4
4
  "description": "AKARI Video launcher CLI — start an AI-edited video project from any directory: scaffold, connection check, then hand over to Claude Code (or opencode). AKARI Video を opencode や Claude Code で、どのディレクトリからでも始めるための `akari` ランチャー CLI。接続確認(doctor)→ 未セットアップならプロジェクト雛形を作成 → AI エージェントを起動する。外部 npm 依存ゼロ(Node.js 組み込みモジュールのみ)。 [akari-video npm vendor: bin/akari.mjs is reference-only. These CLI entrypoints are not included in the akari-video npm package. Use `akari doctor --json` and run the path reported in `render_cut.path`. Full installations provide it in a monorepo checkout, ~/.akari/app, /Applications/AKARI Video.app/Contents/Resources/packages, or %LOCALAPPDATA%\\Programs\\@akari-videoshell\\resources\\packages.]",
5
5
  "type": "module",
6
6
  "files": [
@@ -2339,6 +2339,25 @@ async function validateOverlays(overlays, timeline, findings, paths) {
2339
2339
  path: relativePath(paths.projectRoot, htmlPath),
2340
2340
  });
2341
2341
  }
2342
+ // テキスト分割断片の CSS animation は [data-akari-active] ゲートの中で宣言する
2343
+ // (skills/overlay-authoring/telop.md「テキスト分割と stagger 規約」)。
2344
+ // getAnimations() のコストはドキュメント全体の animation 総数に比例するため、
2345
+ // ゲート無しの断片が 1 つでも混ざると全体の tick が落ちる。分割はその危険を
2346
+ // 分割数ぶんに増幅する(実測: 1,200 断片 × 8 分割 = 9,600 本で 221ms/tick。
2347
+ // akari-video-internal contract-2026-08-15-telop-motion-grammar-v0 §6)。
2348
+ if (/\bdata-akari-split\s*=/.test(html) && /(^|[^-\w])animation\s*:/.test(html)) {
2349
+ const gated = /\[data-akari-active\][^{}]*\.[^{}]*\{[^{}]*animation\s*:/.test(html);
2350
+ if (!gated) {
2351
+ addFinding(findings, {
2352
+ severity: "error",
2353
+ check: "overlays.split-animation-gate",
2354
+ message:
2355
+ "text-split fragment must declare animations under a [data-akari-active] selector",
2356
+ path: relativePath(paths.projectRoot, htmlPath),
2357
+ });
2358
+ }
2359
+ }
2360
+
2342
2361
  for (const [attribute, expected] of [
2343
2362
  ["data-start", overlay.start],
2344
2363
  ["data-duration", overlay.duration],
@@ -53,8 +53,12 @@ Three.js + glTF シーンを決定的な時刻で描画し(`three-runtime.js`
53
53
  自動でこの順に埋め込む — 同じ順序をホストの `<script>` タグでも守ること)。ランタイム読込後、
54
54
  `font` 省略を許すホストは mount より前に
55
55
  `window.akari.threeRuntime.configure({ defaultFontUrl })` を 1 回呼ぶ
56
- 4. `src/interaction.css` と `src/minimap.css` を `<link>` する
57
- 5. edit.json ロード後、`window.akari.runtime.mount(summary)` を呼ぶ
56
+ 4. テキスト分割断片(`data-akari-split`)を扱うホストは、`src/interaction.js` より前に
57
+ `src/vendor/budoux-ja-bundle.js` `src/text-split.js` の順で読み込む。
58
+ 未読込でも他機能は動くが、日本語の文節分割が精度の落ちる近似になり
59
+ (実測 85% → 65%)、編集時の畳み/再分割も働かない
60
+ 5. `src/motion-vocab.css`(イージング語彙 + 対象別既定尺の単一定義。断片の `var(--ease-*)` / `var(--anim-duration-*)` の解決先)と `src/interaction.css`・`src/minimap.css` を `<link>` する
61
+ 6. edit.json ロード後、`window.akari.runtime.mount(summary)` を呼ぶ
58
62
  (`summary` = `EditSummary`。下記参照)。以降はタイムライン更新のたびに
59
63
  `window.akari.runtime.tick(t, playing)` を呼ぶ
60
64
 
@@ -238,11 +242,15 @@ src/
238
242
  vendor/opentype.js-LICENSE.txt opentype.js の MIT License
239
243
  vendor/matter-js-LICENSE.txt matter-js の MIT License
240
244
  vendor/poly-decomp-LICENSE.txt poly-decomp の MIT License
245
+ vendor/budoux-ja-bundle.js BudouX(日本語の表示単位分割)の単一 IIFE
246
+ vendor/budoux-LICENSE.txt BudouX の Apache License 2.0
247
+ text-split.js data-akari-split の分割 / 畳み / 再分割(v0.5.0〜)
241
248
  three-runtime.js 宣言型 3D scene の load / setTime / render / dispose
242
249
  viewport-units.js 断片 CSS の vw/vh 系単位をステージ(出力サイズ)基準へ書き換え
243
250
  overlay-runtime.js DOM mount/tick と 3D 可視ライフサイクル
244
251
  interaction.js legacy ui/interaction.js を無改変移送
245
252
  interaction.css legacy ui/interaction.css を無改変移送
253
+ motion-vocab.css イージング語彙 + 対象別既定尺(正典。skills/overlay-authoring/motion.md 参照)
246
254
  minimap.js legacy ui/minimap.js を無改変移送
247
255
  minimap.css legacy ui/style.css 206〜234 行(#minimap ブロック)を抽出
248
256
  docs/
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akari-video/overlay-runtime",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "private": true,
5
5
  "description": "Shell-agnostic overlay DOM runtime: mount/tick of edit.json overlays (#overlay-stage), pointer-driven select/drag/resize/edit interaction layer, and zoom minimap. Host-agnostic — see README.md for the window.akari.* adapter contract a hosting shell must provide.",
6
6
  "main": "src/overlay-runtime.js",
@@ -11,7 +11,7 @@
11
11
  "README.md"
12
12
  ],
13
13
  "scripts": {
14
- "check": "node --check src/parts.mjs && node --check src/vendor/three-bundle.js && node --check src/vendor/vendor-3d-text-bundle.js && node --check src/three-runtime.js && node --check src/slot-params.js && node --check src/video-fx.js && node --check src/viewport-units.js && node --check src/overlay-runtime.js && node --check src/interaction.js && node --check src/minimap.js",
14
+ "check": "node --check src/parts.mjs && node --check src/vendor/three-bundle.js && node --check src/vendor/vendor-3d-text-bundle.js && node --check src/three-runtime.js && node --check src/slot-params.js && node --check src/video-fx.js && node --check src/viewport-units.js && node --check src/vendor/budoux-ja-bundle.js && node --check src/text-split.js && node --check src/overlay-runtime.js && node --check src/interaction.js && node --check src/minimap.js",
15
15
  "test": "node --test test-harness/*.test.mjs"
16
16
  }
17
17
  }
@@ -4,7 +4,7 @@
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "scripts": {
7
- "build": "esbuild ../pen-visuals/src/index.ts --bundle --format=esm --outfile=public/pen-visuals.bundle.js --target=chrome122 --platform=browser && esbuild ../overlay-runtime/src/interaction.js --bundle --format=iife --outfile=public/overlay-interaction.bundle.js --target=chrome122 --platform=browser && esbuild ../overlay-runtime/src/interaction.css --bundle --outfile=public/overlay-interaction.css --target=chrome122 && esbuild ../edit-store/src/webview-kernel.ts --bundle --format=esm --outfile=public/edit-kernel.bundle.js --target=chrome122 --platform=browser && esbuild src/frame-engine-client.ts --bundle --format=esm --outfile=public/frame-engine.bundle.js --target=chrome122 --platform=browser",
7
+ "build": "esbuild ../pen-visuals/src/index.ts --bundle --format=esm --outfile=public/pen-visuals.bundle.js --target=chrome122 --platform=browser && esbuild ../overlay-runtime/src/interaction.js --bundle --format=iife --outfile=public/overlay-interaction.bundle.js --target=chrome122 --platform=browser && esbuild ../overlay-runtime/src/interaction.css --bundle --outfile=public/overlay-interaction.css --target=chrome122 && esbuild ../overlay-runtime/src/motion-vocab.css --bundle --outfile=public/overlay-motion-vocab.css --target=chrome122 && esbuild ../edit-store/src/webview-kernel.ts --bundle --format=esm --outfile=public/edit-kernel.bundle.js --target=chrome122 --platform=browser && esbuild src/frame-engine-client.ts --bundle --format=esm --outfile=public/frame-engine.bundle.js --target=chrome122 --platform=browser",
8
8
  "pretest": "npm --prefix ../edit-store run build && npm --prefix ../../apps/shell/extensions/akari-preview run build && npm run build",
9
9
  "test": "node --test test/*.test.mjs",
10
10
  "test:frame-engine-browser": "node --test test/frame-engine-preview-browser.l1.mjs",
@@ -16,15 +16,40 @@
16
16
 
17
17
  ## イージング語彙
18
18
 
19
- | 意図 | CSS 語彙 | 使い方 |
20
- |---|---|---|
21
- | 等速・進捗・連続回転 | `linear` | 速度変化そのものに意味がない動き |
22
- | 入場・減速して止まる | `ease-out` | 画面外から定位置へ入る要素 |
23
- | 退場・加速して去る | `ease-in` | 定位置から画面外へ出る要素 |
24
- | 姿勢 A と B の往復 | `ease-in-out` | カード反転、視線移動、穏やかな遷移 |
25
- | 離散切替 | `steps()` | カウンタの桁、LED、コマ送り風表現 |
19
+ 数値の `cubic-bezier()` を断片に直書きしない。ランタイムの語彙
20
+ (`packages/overlay-runtime/src/motion-vocab.css`。ホストが読み込み、書き出し側は
21
+ rasterize.mjs が同じ内容をシートへ埋め込む)を **名前で** 呼ぶ。
26
22
 
27
- 独自 `cubic-bezier()` named easing で意図を表せない場合だけ使い、CSS 変数化して理由を残す。標準キーワードの定義は [W3C CSS Easing Functions Level 2](https://www.w3.org/TR/css-easing-2/) を参照する。
23
+ | 変数 | 質感 | 使いどころ |
24
+ |---|---|---|
25
+ | `--ease-smooth` | **既定**。すっと出て長く減速 | 入場・移動・サイズ変化の第一候補。未指定の `var(--anim-easing)` はこれになる |
26
+ | `--ease-natural` | 中庸の立ち上がり + 長い減速の尾 | リストの送り、続きものの移動 |
27
+ | `--ease-slowdown` | 初速最大 → 匍匐して止まる | 勢いから静止へ。強い ease-out |
28
+ | `--ease-accelerate` | 深い溜め → 加速して去る | 退場。**直後にカットが来る前提**の動き |
29
+ | `--ease-overshoot` | バネ。目標を大きく越えてから戻る(約 +90%) | 強調の飛び込み・ポップイン |
30
+ | `--ease-overshoot-mid` / `--ease-overshoot-soft` | 同じバネの控えめ段(約 +66% / +32%) | 移動量がやや大きいときの逃がし先 |
31
+ | `--ease-impulse` | 突進して小さく上振れ | 高速スライドイン |
32
+ | `--ease-linear` | 等速 | 進捗・連続回転など、速度変化に意味がない動き |
33
+ | `--ease-snap-out` / `--ease-hard-out` / `--ease-deep-inout` / `--ease-snappy` | 切れ味系の補助語彙 | テロップの歯切れを出したいとき(telop.md) |
34
+
35
+ `--anim-duration` に入れる尺の相場も対象別の変数がある:
36
+
37
+ | 変数 | 値 | 対象 |
38
+ |---|---|---|
39
+ | `--anim-duration-telop` | 500ms | テロップ(1 文字 / 1 文節あたり) |
40
+ | `--anim-duration-shape` | 800ms | 図形・帯・カード |
41
+ | `--anim-duration-group` | 1000ms | ラッパ `<div>` ごと動かすとき |
42
+
43
+ **overshoot / impulse は「小さい移動・スケールのポップ」専用**。越え量は移動量に
44
+ **比例**するため、画面幅級の搬入(数百 px の translate)に掛けると目標を数百 px
45
+ 突き抜けて画面外へ飛ぶ。長距離の搬入は `--ease-smooth` / `--ease-natural`、退場は
46
+ `--ease-accelerate`、ポップ強調(scale 0.7→1、数十 px の移動)にだけ overshoot 系を使う。
47
+ どうしても大きめの移動で使うときは `-mid` / `-soft` へ落とす。
48
+
49
+ CSS 標準キーワード(`ease-out` 等)より上記の語彙を優先する。離散切替(カウンタの桁・
50
+ LED・コマ送り風)だけは標準の `steps()` を使う。語彙で意図を表せない場合に限り
51
+ `cubic-bezier()` を新設し、CSS 変数化して理由を残す。標準キーワードの定義は
52
+ [W3C CSS Easing Functions Level 2](https://www.w3.org/TR/css-easing-2/) を参照する。
28
53
 
29
54
  ## compositor 合成の制約
30
55
 
@@ -92,6 +92,7 @@ YouTube の safe zone も全端末保証ではない。オーガニック投稿
92
92
 
93
93
  - 字幕の出入りは短い opacity / translate を使い、保持中は動かさない。
94
94
  - 1 文字ずつの出現は可読速度とシーク再現性を損ねやすい。必要な演出だけに限定し、文字 DOM は先に確定しておく。
95
+ 日本語で時間差の出現をやるなら 1 文字ではなく**文節単位**にする(下の「テキスト分割と stagger 規約」)。
95
96
  - CSS animation / WAAPI を使い、ランタイムが `currentTime = (t - start) * 1000` を設定できる形にする。
96
97
  - 位置移動の transform は断片内の子要素へ付け、AKARI が所有する外側コンテナの幾何 transform と分離する。
97
98
 
@@ -108,6 +109,83 @@ OUT の `both`(= backwards fill)は**遅延中に OUT の開始値(`opacit
108
109
  - チェック: 断片の冒頭数フレームをシークし、IN の開始値(opacity 0 / 画面外)から始まることを目視する
109
110
  - この罠は IN/OUT の 2 段に限らず一般化できる(3 段以上の連鎖、点滅ループの片端省略など)。`motion.md`「複数アニメーションを同一プロパティへ連鎖させるときの暗黙 0% 上書き」を参照
110
111
 
112
+ ## テキスト分割と stagger 規約(2026-08-15)
113
+
114
+ 文字・単語・文節ごとに時間差で出す演出は、**断片が分割済みで出荷し、
115
+ stagger は CSS の `calc()` で表現する**。断片に `<script>` は書かない。
116
+
117
+ ```html
118
+ <div class="foo__line" data-akari-split="bunsetsu"
119
+ ><span class="akari-u" style="--i:0">今日は</span
120
+ ><span class="akari-u" style="--i:1">とても</span
121
+ ><span class="akari-u" style="--i:2">いい</span
122
+ ><span class="akari-u" style="--i:3">天気ですね</span></div>
123
+ ```
124
+
125
+ ```css
126
+ .foo__line{
127
+ --anim-duration: var(--anim-duration-telop, 500ms); /* 1 要素の尺(対象別の相場は motion.md) */
128
+ --anim-stagger: 150ms; /* ずらし */
129
+ --anim-easing: var(--ease-snap-out); /* 語彙は motion.md「イージング語彙」。未指定なら smooth */
130
+ }
131
+ /* ★ [data-akari-active] ゲートの中で宣言する(下の「性能」参照) */
132
+ [data-akari-active] .foo__line .akari-u{
133
+ animation: foo__in var(--anim-duration) var(--anim-easing) both paused;
134
+ animation-delay: calc(var(--i) * var(--anim-stagger));
135
+ }
136
+ @keyframes foo__in{
137
+ from{ opacity:0; transform: translateY(var(--anim-distance, 50px)); }
138
+ to { opacity:1; transform: none; }
139
+ }
140
+ ```
141
+
142
+ - **`animation-delay: calc(var(--i) * var(--anim-stagger))` の 1 行がすべて**。
143
+ どの `@keyframes`(= どの演出)にも同じ形で stagger が掛かる。
144
+ 演出ごとに遅延を書き並べない
145
+ - **ツマミは CSS 変数**にする。`edit.json` の `vars` から上書きできる
146
+ - **`--i` は 0 始まりの通し番号**。`--n` に総数が入る(ランタイムが振る)
147
+
148
+ ### 分割単位(`data-akari-split`)
149
+
150
+ | 値 | 単位 | 使いどころ |
151
+ |---|---|---|
152
+ | `bunsetsu` | 文節(日本語の表示単位) | **日本語テロップの既定** |
153
+ | `chars` | 1 文字 | 演出用。可読速度を損ねるので多用しない |
154
+ | `words` | 単語 | 欧文向け。**日本語では分かち書きしないので機能しない** |
155
+ | `lines` | 行 | 行単位で送る |
156
+ | `none` | 分割しない | — |
157
+
158
+ 日本語の文節分割は BudouX(`src/vendor/budoux-ja-bundle.js`・Apache-2.0)で行う。
159
+ `Intl.Segmenter` 単体の単語分割は助詞がバラけるため使わない
160
+ (`今日 | は | とても | いい | 天気 | です | ね` になる)。
161
+
162
+ ### ランタイムの担当(断片は書かなくてよい)
163
+
164
+ `data-mirror="text"` と同じく、DOM 操作はランタイムが持つ:
165
+
166
+ - **mount 時**: 宣言はあるが未分割の要素を分割する(出荷漏れの安全網・冪等)
167
+ - **編集開始時**: 分割を素のテキストへ畳む(`<span>` のまま contenteditable にすると
168
+ 打鍵で span が割れる・キャレットが単位境界で飛ぶ)
169
+ - **編集確定時**: 確定したテキストで分割し直し、`--i` を振り直す。
170
+ 保存される HTML は**分割済みの状態**(書き出しは断片の HTML をそのまま使うため)
171
+
172
+ 必要ランタイム: **0.5.0 以降**。素材の `meta.json` に
173
+ `min_overlay_runtime_version: "0.5.0"` を宣言する。
174
+
175
+ ### 性能 — `[data-akari-active]` ゲートは必須(実測)
176
+
177
+ 分割は 1 断片の CSS animation を分割数ぶんに増やす。ゲートが無いと即死する:
178
+
179
+ | 条件 | 現存 animation | 1 tick |
180
+ |---|---:|---:|
181
+ | ゲート有り・1,200 断片 × 16 分割・可視 60 | 960 | **0.023ms** |
182
+ | ゲート無し・1,200 断片 × 8 分割 | 9,600 | **221ms** |
183
+ | ゲート無し・上記 + 可視 60 | 9,600 | **11,783ms** |
184
+
185
+ `getAnimations()` のコストは「ドキュメント全体に現存する CSS animation の総数」に
186
+ 比例する。ゲートの中で宣言すれば非可視分は現存しないので、**分割そのものは無害**。
187
+ ゲートを忘れた断片が 1 つあるだけで全体が落ちる。
188
+
111
189
  ## 多層テキスト断片と data-mirror 規約(2026-08-06)
112
190
 
113
191
  同一テキストを太さ違いの `-webkit-text-stroke` 等で複数層重ねる断片(多重縁取り・ずらし影・裏打ち・二段押し出し等)は、編集対象を 1 層に決めないと打ち替えが層間でズレる。層間の同期は overlay-runtime(`packages/overlay-runtime/`)側の機能で行う。