akari-video 0.1.49 → 0.1.50
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 +1 -1
- package/src/captions-command.mjs +20 -0
- package/src/cli.mjs +2 -0
- package/src/repo-assets.mjs +3 -0
- package/vendor/.akari-capability-sources.json +1 -0
- package/vendor/docs/contract-2026-07-25-project-structure-v0.md +9 -1
- package/vendor/docs/contract-2026-08-18-v1-render-parity.md +1 -0
- package/vendor/docs/contract-2026-08-30-motion-and-keyframes-v0.md +50 -2
- package/vendor/docs/contract-2026-09-05-clip-adjust-v1.md +129 -117
- package/vendor/packages/akari-launcher/package.json +1 -1
- package/vendor/packages/creator-root/src/index.mjs +26 -2
- package/vendor/packages/creator-root/test/create-creator-root.test.mjs +6 -0
- package/vendor/packages/edit-lint/src/edit-lint.mjs +139 -1
- package/vendor/packages/edit-store/lib/adjust-css-visual.d.ts +8 -1
- package/vendor/packages/edit-store/lib/adjust-css-visual.js +15 -3
- package/vendor/packages/edit-store/lib/audio-ownership.d.ts +13 -0
- package/vendor/packages/edit-store/lib/audio-ownership.js +12 -0
- package/vendor/packages/edit-store/lib/audio-schedule.d.ts +3 -0
- package/vendor/packages/edit-store/lib/audio-schedule.js +15 -5
- package/vendor/packages/edit-store/lib/canonical.js +2 -1
- package/vendor/packages/edit-store/lib/edit-store.d.ts +2 -0
- package/vendor/packages/edit-store/lib/edit-v2.d.ts +27 -1
- package/vendor/packages/edit-store/lib/edit-v2.js +20 -4
- package/vendor/packages/edit-store/lib/generated/edit-v2-keys.d.ts +3 -3
- package/vendor/packages/edit-store/lib/generated/edit-v2-keys.js +5 -2
- package/vendor/packages/edit-store/lib/index.d.ts +1 -0
- package/vendor/packages/edit-store/lib/index.js +1 -0
- package/vendor/packages/edit-store/lib/internal-model.d.ts +4 -1
- package/vendor/packages/edit-store/lib/internal-model.js +23 -9
- package/vendor/packages/edit-store/lib/legacy-audio-view.d.ts +1 -0
- package/vendor/packages/edit-store/lib/legacy-audio-view.js +11 -3
- package/vendor/packages/edit-store/lib/timeline-map.js +2 -0
- package/vendor/packages/edit-store/lib/webview-kernel.d.ts +1 -0
- package/vendor/packages/edit-store/lib/webview-kernel.js +72 -19
- package/vendor/packages/frame-engine/package.json +1 -0
- package/vendor/packages/overlay-runtime/README.md +110 -7
- package/vendor/packages/schemas/bin/validate-asset.mjs +14 -84
- package/vendor/packages/schemas/bin/validate-edit.mjs +5 -0
- package/vendor/packages/schemas/edit.schema.json +127 -4
- package/vendor/packages/schemas/engine-capabilities.json +10 -5
- package/vendor/packages/schemas/examples/edit-v2-adjust-fx-group2-range-invalid/edit.json +71 -0
- package/vendor/packages/schemas/examples/edit-v2-adjust-fx-group2-valid/edit.json +71 -0
- package/vendor/packages/schemas/examples/edit-v2-adjust-fx-unknown-id-invalid/edit.json +1 -1
- package/vendor/packages/schemas/examples/edit-v2-caption-animator-unknown-ref-invalid/captions.json +3 -0
- package/vendor/packages/schemas/examples/edit-v2-caption-animator-unknown-ref-invalid/edit.json +28 -0
- package/vendor/packages/schemas/examples/edit-v2-caption-animator-valid/captions.json +3 -0
- package/vendor/packages/schemas/examples/edit-v2-caption-animator-valid/edit.json +28 -0
- package/vendor/packages/schemas/examples/edit-v2-cut-audio-link-duplicate-invalid/edit.json +74 -0
- package/vendor/packages/schemas/examples/edit-v2-cut-audio-link-missing-invalid/edit.json +54 -0
- package/vendor/packages/schemas/examples/edit-v2-cut-audio-link-not-media-invalid/edit.json +51 -0
- package/vendor/packages/schemas/examples/edit-v2-cut-audio-split-valid/edit.json +54 -0
- package/vendor/packages/schemas/examples/edit-v2-cut-audio-true-invalid/edit.json +54 -0
- package/vendor/packages/schemas/intake.schema.json +7 -1
- package/vendor/packages/schemas/test/adjust-fx.test.mjs +8 -1
- package/vendor/packages/schemas/test/adjust-v1.test.mjs +1 -1
- package/vendor/packages/schemas/test/caption-animator.test.mjs +33 -0
- package/vendor/packages/schemas/test/cut-audio-split-vocab.test.mjs +72 -0
- package/vendor/packages/schemas/test/engine-capabilities.test.mjs +30 -4
- package/vendor/packages/schemas/test/fixtures/adjust-fx-cases.mjs +19 -0
- package/vendor/packages/schemas/test/validate-intake.test.mjs +15 -0
- package/vendor/skills/edit-lint/SKILL.md +1 -0
- package/vendor/skills/edit-plan/SKILL.md +21 -13
- package/vendor/skills/edit-plan/approvals-and-generation.md +6 -4
- package/vendor/skills/edit-plan/autonomy.md +67 -0
- package/vendor/skills/edit-plan/execution.md +13 -6
- package/vendor/skills/edit-plan/report-guide.md +6 -0
- package/vendor/skills/edit-plan/workflow.md +2 -2
- package/vendor/skills/overlay-authoring/SKILL.md +1 -0
- package/vendor/templates/project-default/CLAUDE.md +1 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "akari-video",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.50",
|
|
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": {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
|
|
4
|
+
import { resolveLauncherAssets } from "./repo-assets.mjs";
|
|
5
|
+
|
|
6
|
+
export async function runCaptionsCommand(argv, options = {}) {
|
|
7
|
+
const logError = options.error ?? options.logError ?? ((line) => console.error(line));
|
|
8
|
+
const assets = options.assets ?? resolveLauncherAssets();
|
|
9
|
+
if (!assets.captionsScript || !existsSync(assets.captionsScript)) {
|
|
10
|
+
logError("akari captions の実行スクリプトが見つかりません。AKARI Video を再インストールしてください。");
|
|
11
|
+
return { exitCode: 1 };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const spawn = options.spawn ?? spawnSync;
|
|
15
|
+
const result = spawn(process.execPath, [assets.captionsScript, ...argv], {
|
|
16
|
+
stdio: "inherit",
|
|
17
|
+
cwd: options.cwd ?? process.cwd(),
|
|
18
|
+
});
|
|
19
|
+
return { exitCode: typeof result.status === "number" ? result.status : 1 };
|
|
20
|
+
}
|
package/src/cli.mjs
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
triggerBackgroundRefresh
|
|
23
23
|
} from './update-check.mjs';
|
|
24
24
|
import { applySelfUpdate, isRunningFromAppDir, rollbackSelfUpdate } from './self-update.mjs';
|
|
25
|
+
import { runCaptionsCommand } from './captions-command.mjs';
|
|
25
26
|
import { runCaptureCommand } from './capture-command.mjs';
|
|
26
27
|
import { runMediaCommand } from './media-command.mjs';
|
|
27
28
|
import { runWordBookCommand } from './word-book-command.mjs';
|
|
@@ -43,6 +44,7 @@ export async function run(args, options = {}) {
|
|
|
43
44
|
error(`akari ${retiredBrowserCommand} は廃止されました(Chrome は不要になりました)`);
|
|
44
45
|
return { exitCode: 1 };
|
|
45
46
|
}
|
|
47
|
+
if (args[0] === 'captions') return runCaptionsCommand(args.slice(1), options);
|
|
46
48
|
if (args[0] === 'capture') return runCaptureCommand(args.slice(1), options);
|
|
47
49
|
if (args[0] === 'media') return runMediaCommand(args.slice(1), options);
|
|
48
50
|
if (args[0] === 'word-book') return runWordBookCommand(args.slice(1), options);
|
package/src/repo-assets.mjs
CHANGED
|
@@ -33,6 +33,7 @@ const AUDIO_FETCH_SCRIPT_RELATIVE = path.join('packages', 'audio-library-setup',
|
|
|
33
33
|
const ASSET_RESOLVER_CLI_RELATIVE = path.join('packages', 'asset-resolver', 'bin', 'akari-assets.mjs');
|
|
34
34
|
const BEATMAP_SCRIPT_RELATIVE = path.join('packages', 'akari-tools', 'bin', 'beatmap.mjs');
|
|
35
35
|
const PROBE_FRAME_SCRIPT_RELATIVE = path.join('packages', 'akari-tools', 'bin', 'probe-frame.mjs');
|
|
36
|
+
const CAPTIONS_SCRIPT_RELATIVE = path.join('packages', 'akari-tools', 'bin', 'captions.mjs');
|
|
36
37
|
const CAPTURE_SCRIPT_RELATIVE = path.join('packages', 'akari-tools', 'bin', 'capture.mjs');
|
|
37
38
|
const RENDER_WHEN_IDLE_SCRIPT_RELATIVE = path.join('packages', 'akari-tools', 'bin', 'render-when-idle.sh');
|
|
38
39
|
const EYE_BAR_SCRIPT_RELATIVE = path.join('packages', 'akari-tools', 'bin', 'eye-bar.mjs');
|
|
@@ -69,6 +70,7 @@ export function resolveRepoAssets(repoRoot = DEFAULT_REPO_ROOT_CANDIDATE) {
|
|
|
69
70
|
assetResolverCliPath: existsSync(assetResolverCliPath) ? assetResolverCliPath : null,
|
|
70
71
|
beatmapScript: existsSync(beatmapScript) ? beatmapScript : null,
|
|
71
72
|
probeFrameScript: existsSync(probeFrameScript) ? probeFrameScript : null,
|
|
73
|
+
captionsScript: existsSync(path.join(repoRoot, CAPTIONS_SCRIPT_RELATIVE)) ? path.join(repoRoot, CAPTIONS_SCRIPT_RELATIVE) : null,
|
|
72
74
|
captureScript: existsSync(path.join(repoRoot, CAPTURE_SCRIPT_RELATIVE)) ? path.join(repoRoot, CAPTURE_SCRIPT_RELATIVE) : null,
|
|
73
75
|
renderWhenIdleScript: existsSync(renderWhenIdleScript) ? renderWhenIdleScript : null,
|
|
74
76
|
eyeBarScript: existsSync(eyeBarScript) ? eyeBarScript : null,
|
|
@@ -105,6 +107,7 @@ export function resolveLauncherAssets({
|
|
|
105
107
|
probeFrameScript: candidate.probeFrameScript ?? vendor.probeFrameScript,
|
|
106
108
|
// 既存の部分資産 fixture に capture marker が無いため、未解決時だけキー自体を省く。
|
|
107
109
|
...(candidate.captureScript ?? vendor.captureScript ? { captureScript: candidate.captureScript ?? vendor.captureScript } : {}),
|
|
110
|
+
...(candidate.captionsScript ?? vendor.captionsScript ? { captionsScript: candidate.captionsScript ?? vendor.captionsScript } : {}),
|
|
108
111
|
renderWhenIdleScript: candidate.renderWhenIdleScript ?? vendor.renderWhenIdleScript,
|
|
109
112
|
eyeBarScript: candidate.eyeBarScript ?? vendor.eyeBarScript,
|
|
110
113
|
mediaScript: candidate.mediaScript ?? vendor.mediaScript,
|
|
@@ -148,6 +148,7 @@
|
|
|
148
148
|
"skills/declare-audio/what-to-declare.md",
|
|
149
149
|
"skills/edit-lint/SKILL.md",
|
|
150
150
|
"skills/edit-plan/approvals-and-generation.md",
|
|
151
|
+
"skills/edit-plan/autonomy.md",
|
|
151
152
|
"skills/edit-plan/avatar-resolution.md",
|
|
152
153
|
"skills/edit-plan/beat-sync.md",
|
|
153
154
|
"skills/edit-plan/beats.md",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
lifecycle: draft
|
|
3
3
|
created: 2026-07-25
|
|
4
|
-
updated: 2026-
|
|
4
|
+
updated: 2026-09-06
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# project-structure-v0(生成物の置き場所)契約
|
|
@@ -42,6 +42,7 @@ updated: 2026-08-26
|
|
|
42
42
|
| 企画・プラン | `planning/` | スキル + 人間承認 |
|
|
43
43
|
| エージェント中間物・ad-hoc 検証スクリプトと結果 | `.akari/work/` | スキル・エージェント |
|
|
44
44
|
| 検証証跡・レポート(キーフレーム視認 PNG・render-report 等) | `.akari/reports/` | スキル |
|
|
45
|
+
| 絵コンテ(タイムラインの印刷・初回だけ・AI は後から読まない) | `.akari/reports/storyboard/` | スキル |
|
|
45
46
|
| キャッシュ(サムネ・プロキシ等の再生成可能物) | `.akari/cache/` | アプリ・スキル |
|
|
46
47
|
| 納品物 | `exports/` | `render-cut` |
|
|
47
48
|
| 契約サイドカー(既存) | `.akari/`(`sidecars/` `diffs/` `events/` 等) | 既存のまま |
|
|
@@ -242,3 +243,10 @@ updated: 2026-08-26
|
|
|
242
243
|
- 自分がルートである git リポジトリのときだけ動く。親リポジトリの中に置かれたプロジェクトは、
|
|
243
244
|
こちらが管理していないリポジトリの追跡対象を黙って変えないため対象外とする(§3 の
|
|
244
245
|
「強制的にファイルを移動・削除するスクリプトは作らない」と同じ抑制)
|
|
246
|
+
|
|
247
|
+
### 2026-09-06 追記: 絵コンテの置き場(判子は一回 契約 §5.2 / §14-4)
|
|
248
|
+
|
|
249
|
+
絵コンテは `edit.json` / `captions.json` から描くタイムラインの派生ビューで、
|
|
250
|
+
置き場は `.akari/reports/storyboard/`(レポート層 = 削除安全)とする。
|
|
251
|
+
初回だけ描き更新しない・入力側に置かない・AI は後から読まない。直すときはタイムラインを
|
|
252
|
+
直して描き直す。
|
|
@@ -67,6 +67,7 @@ cut = needsGapAwareCutTimeline(edit.cuts)
|
|
|
67
67
|
- **多段合成の意味論**: `computeVideoRuns`(`cut-timeline.mjs`)の winner-take-all スイッチ。
|
|
68
68
|
ある瞬間に最も高い `track` 番号のカットが**画面全体を占有**する(同時アルファ合成ではない)
|
|
69
69
|
— v0 が既定順で行っているのと全く同じモデルで、新しいリッチな合成モデルではない
|
|
70
|
+
上段の静止画は単位元 `transform` でも下段と時間的に交差する(cross-track)場合、natural size と alpha の観点から全画面不透明を証明できないため、投影時に `layers` へ退避する。
|
|
70
71
|
- **音声はカット単位(ラン単位ではない)**: 各カットの `[in,out)` がそれぞれの `at` 位置で
|
|
71
72
|
再生され、`amix` で重ね合わさる。画面はどちらか一方しか映らなくても、音声は両方鳴る
|
|
72
73
|
(v0 の `buildGapAwareCutCommand` の音声ループをそのまま踏襲)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
lifecycle: accepted
|
|
3
3
|
created: 2026-08-30
|
|
4
|
-
updated: 2026-
|
|
4
|
+
updated: 2026-09-06
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# 動きとキーフレーム契約 v0 — 4 段階(プリセット / キーフレーム / アニメーター / コード)と `motion/` 袋
|
|
@@ -132,7 +132,7 @@ media item(cuts)での適用先 = frame-engine base 経路(2026-09-01・is
|
|
|
132
132
|
| キー | 型 | 意味 |
|
|
133
133
|
|---|---|---|
|
|
134
134
|
| `id` | string | アニメーターの id(キーフレームから参照)|
|
|
135
|
-
| `basis` | `chars` / `words` / `lines` / `segments` | 範囲の単位(`segments` =
|
|
135
|
+
| `basis` | `chars` / `words` / `lines` / `segments` | 範囲の単位(`segments` = 文節。v1 の words フォールバックは §4.4)|
|
|
136
136
|
| `shape` | `ramp` / `triangle` / `round` / `smooth` / `square` / `ramp-down` | 範囲の中の影響度カーブ(0..1)|
|
|
137
137
|
| `start` / `end` | number 0..1 | 範囲(単位数に対する比)|
|
|
138
138
|
| `offset` | number | 範囲の平行移動(−1..1)。**動かすのはこれ**(§4.3)|
|
|
@@ -144,13 +144,61 @@ media item(cuts)での適用先 = frame-engine base 経路(2026-09-01・is
|
|
|
144
144
|
- 対象は `telop` / `caption`(分離した行)/ `group` の中のテキスト系アイテム。HTML 部品は L3 か `vars`
|
|
145
145
|
- 既存モーション文法との対応: `--anim-stagger` ≈ `offset` をキーフレームで動かす / `--anim-distance` ≈ `amount.y` / `--anim-easing` ≈ `ease`。既存 CSS 変数はそのまま生きる(L0)。アニメーターは native アイテムの L2
|
|
146
146
|
|
|
147
|
+
**司令塔裁定(2026-09-06)— 単位の位置・影響度・量を確定する**:
|
|
148
|
+
|
|
149
|
+
- 単位数を `count`、0 始まりの単位順序を `u` として、**`pos(u) = (u + 0.5) / count`**(各単位の中央)を割り当てる。`randomize.seed` があるときは**整数ハッシュによる決定論シャッフル**で単位の順序を振ってから pos を割り当てる。`Math.random` / `fract(sin())` は使わない
|
|
150
|
+
- `s = start + offset`、`e = end + offset` とし、影響度は **`w = shape(pos, s, e)`**。`s ≥ e` なら全 shape で `w = 0`。それ以外は次表(`clamp01(v) = max(0, min(1, v))`)
|
|
151
|
+
|
|
152
|
+
| `shape` | 影響度 `w` の式 |
|
|
153
|
+
|---|---|
|
|
154
|
+
| `ramp` | `ramp = clamp01((pos−s)/(e−s))` |
|
|
155
|
+
| `ramp-down` | `1 − ramp` |
|
|
156
|
+
| `triangle` | `1 − \|2·ramp − 1\|`(中央 1 の三角)|
|
|
157
|
+
| `round` | `sin(π·ramp)` |
|
|
158
|
+
| `smooth` | `ramp²(3−2·ramp)` |
|
|
159
|
+
| `square` | `s ≤ pos < e` で 1、それ以外は 0 |
|
|
160
|
+
|
|
161
|
+
- 影響度に `ease` を掛けて **`k = ease(w)`** とする。`ease` は §2.1-(b) の語彙、既定は `linear`。各量への寄与は `amount × k`(scale の適用倍率は次表)
|
|
162
|
+
|
|
163
|
+
| `amount` のキー | 単位・適用量 |
|
|
164
|
+
|---|---|
|
|
165
|
+
| `x` / `y` / `letterSpacing` / `blur` | 出力 px。1920 幅を基準とし、`amount × k × output.width / 1920` に比率換算する(`adjust.fx` と同じ規約)|
|
|
166
|
+
| `rotate` | 度。`amount.rotate × k`。gpu では tile 中心回転 |
|
|
167
|
+
| `scale` | 倍率の**増分**。適用倍率 = `1 + amount.scale × k` |
|
|
168
|
+
| `opacity` | 加算量(宣言値 −1..1)。寄与 = `amount.opacity × k` |
|
|
169
|
+
|
|
147
170
|
### 4.2 合成
|
|
148
171
|
|
|
149
172
|
- 同じプロパティに複数のアニメーターが効くときは §4.1 の加算規則。アニメーターと L1 キーフレームは**独立に合成**(L1 = アイテム全体、L2 = 単位ごとのずれ)
|
|
173
|
+
- **司令塔裁定(2026-09-06)**: `x` / `y` / `rotate` / `letterSpacing` / `blur` は各寄与の加算、`scale` は各適用倍率の乗算。`opacity` は **Σ の後で** `clamp01(1 + Σ(amount.opacity × k))` とし、アニメーターごとにはクランプしない。単位ごとの状態を、アイテム全体の keyframes / motion の状態と独立に合成する(不透明度・倍率は乗算)
|
|
150
174
|
|
|
151
175
|
### 4.3 offset のキーフレーム
|
|
152
176
|
|
|
153
177
|
- 「どの順で」は `offset` を時間で動かして表す。点は L1 と同じ配列(inline or 袋)に `"animator": { "a1": { "offset": -0.25 } }` … `{ "offset": 1 }` として打つ(典型 2 点)。**文字ごとの点は存在しない**
|
|
178
|
+
- **司令塔裁定(2026-09-06)**: `offset` に加えて `start` / `end` も同じキーフレーム点で動かせる。点が無ければ宣言値で静的。`t` はアイテム相対の整数フレーム、補間は §2.1(線形 / easing / hold)に従う
|
|
179
|
+
|
|
180
|
+
### 4.4 v1 の実装状態と制約(2026-09-06)
|
|
181
|
+
|
|
182
|
+
- **gpu に加え、OSR whole-page 出口の DOM 字幕とシェルの出力プレビュー(webview の `#caption-plate`)で実装済み**。いずれも frame-engine の同じ評価器 `captionAnimatorStateAt` を使う。Web UI(preview-server の旧経路)とインスペクター UI は本便の対象外
|
|
183
|
+
- 対象は **captions.json 由来の字幕**。袋 item(`source.kind: "captions"`)の宣言は全 cue、cue item(`source.kind: "caption"`)の宣言はその cue に適用する。§4.1 の telop / group 内テキストのうち caption unit と同じ経路を通らないものは本便の対象外
|
|
184
|
+
- `basis` は `chars`(書記素)/ `words` / `lines` を実装。**`segments` は v1 では words と同じ扱い**とし、edit-lint は `animator.segments-fallback` warning を出す。文節単位は別便
|
|
185
|
+
- **DOM 出口の適用器**は `packages/frame-engine/src/timeline/caption-animator-dom.ts` の `applyCaptionAnimatorDom(root, declaration)`。`declaration` は `animators` / `keyframes` / `cueLocalSeconds` / `cueDurationSec` / `fps` / `outputWidth` を受け取り、任意の `keyframeOffsetSeconds` で袋 item の開始を基準とするキーフレーム時刻を保つ
|
|
186
|
+
- 適用器は root(cue の要素)内の単位要素を列挙する。`chars` は `.akari-caption__char`、`words` は `.akari-caption__tok`(無ければ単語 span)、`lines` は `.akari-caption__line`(行要素の無い `.akari-caption__reveal-group` も行として扱う)。`segments` は words にフォールバックして一度だけ runtime warning を出し、対象の単位要素が無ければ warning を出してその basis を無視する
|
|
187
|
+
- `captionAnimatorStateAt` の評価結果を単位要素の **inline style** に書く。`transform` は `translate(x px, y px) scale(s) rotate(r deg)`、`opacity` は §4.2 のクランプ後の値を既存 opacity に乗算し、`letterSpacing` / `blur` は `letter-spacing` / `filter: blur()` に反映する。span は inline style の `display: inline-block` で transform を有効にする。副作用は inline style に限り、class / DOM 構造は変えない。**animator が無ければ DOM を一切変えない(バイト不変)**
|
|
188
|
+
- OSR は page-builder が cue ごとの animator / keyframes を埋め込み、page-runtime が各フレームの capture 前に適用する。シェルは summary に宣言を供給し、`chars` 宣言時だけ書記素 span を生成して、マスタークロックの tick / seek で同じ適用器を呼ぶ(frame-engine 経路 / DOM `<video>` 経路共通)
|
|
189
|
+
- `letterSpacing` は tile 幾何を変えるため **gpu 出口では無視**する。非ゼロの宣言に runtime warning `animator.letterSpacing-ignored` を出す
|
|
190
|
+
- `blur` も **gpu 出口では無視**する。現行の GPU sprite tile 描画は `filter: blur()` に対応していないため、非ゼロの宣言に runtime warning `animator.blur-ignored` を出す。評価器での量の計算は §4.1〜4.2 の規則どおり
|
|
191
|
+
- **DOM 出口(OSR whole-page / シェルプレビュー)では `letterSpacing` / `blur` とも inline style でそのまま効く**。この 2 量を無視する gpu とは見た目が異なりうる。gpu との一致は「文字が現れる順序と概ねの位置」とし、tile と DOM の描画の細部(アンチエイリアス等)までの一致は求めない
|
|
192
|
+
- 決定論: **同じ出口・同じ入力は同じ画素**(固定 seed・整数演算)。DOM 適用も同じフレームなら同じ DOM となる。animator 無しの出力は**バイト不変**を保つ
|
|
193
|
+
|
|
194
|
+
edit-lint の規則(gpu runtime の量の無視 warning とは別):
|
|
195
|
+
|
|
196
|
+
| 規則名 | severity | 判定 |
|
|
197
|
+
|---|---|---|
|
|
198
|
+
| `animator.non-text-target` | warning | media / filter item に animator を宣言した(描画では無視)|
|
|
199
|
+
| `animator.unknown-ref` | error | キーフレーム点の `animator[id]` がその item の宣言に無い |
|
|
200
|
+
| `animator.duplicate-id` | error | 同じ item の animator id が重複した |
|
|
201
|
+
| `animator.segments-fallback` | warning | `basis: "segments"` を words として扱う |
|
|
154
202
|
|
|
155
203
|
## 5. 「キーフレームに展開」(L0 / L2 → L1・一方通行)
|
|
156
204
|
|
|
@@ -1,117 +1,129 @@
|
|
|
1
|
-
---
|
|
2
|
-
lifecycle: accepted
|
|
3
|
-
date: 2026-09-05
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# edit.json v2 clip adjust v1 契約
|
|
7
|
-
|
|
8
|
-
## 0. 位置づけ
|
|
9
|
-
|
|
10
|
-
v0 の基本補正と LUT に curves / wheels / hue と画素処理の fx を追加する。
|
|
11
|
-
|
|
12
|
-
## 1. 席
|
|
13
|
-
|
|
14
|
-
version 2 visual item の tracks[].items[].adjust。media / html / telop / filter / group / captions / caption の 7 定義共通。audio と shape、version 0 / 1 の cuts[] / layers[] には追加しない。
|
|
15
|
-
|
|
16
|
-
## 2. 語彙仕様 v1
|
|
17
|
-
|
|
18
|
-
`$defs.adjustV1`(v0 の `basic` / `lut` / `sections` は不変。以下を追加。すべて任意・additionalProperties false):
|
|
19
|
-
|
|
20
|
-
- `curves`: object `{ master?, r?, g?, b? }`。各値は `[{ in: number 0..1, out: number 0..1 }]`(minItems 2・maxItems 16・
|
|
21
|
-
各点 additionalProperties false・in / out とも required)。**`in` は狭義単調増加**(schema では表現できないので
|
|
22
|
-
validate-edit / edit-store / edit-lint で検査)。チャンネル identity = ちょうど 2 点 `[{0,0},{1,1}]`(許容 1e-5)。
|
|
23
|
-
- `wheels`: object `{ lift?, gamma?, gain?, offset? }`。各値は object `{ r?, g?, b? }`(number)。範囲:
|
|
24
|
-
lift ±0.25 / gamma ±0.5 / gain ±0.5 / offset ±0.1。省略 = 0(中立)。
|
|
25
|
-
- `hue`: object `{ hue?, sat?, luma? }`。各値は `[{ hue: number 0..1, value: number 0..1 }]`(minItems 1・maxItems 16・
|
|
26
|
-
additionalProperties false・両方 required)。**`hue` は狭義単調増加**。中立 value = 0.5。チャンネル identity =
|
|
27
|
-
省略または全点 `|value-0.5| ≤ 1e-4`。
|
|
28
|
-
- `fx`: 配列(maxItems 8)。各要素は `id` 必須・additionalProperties false。同じ id は 1 回まで。
|
|
29
|
-
配列順が適用順。空配列は書き込み側で除去し、読み取り側は未指定と同じに扱う。
|
|
30
|
-
- `sections`: `basic` / `lut` に加えて `curves` / `wheels` / `hue` / `fx`(boolean・false のときだけバイパス)。
|
|
31
|
-
- **演算順(固定)**: ① basic(v0 §3 の 1〜6)→ ② lut(trilinear・intensity 混合)→ ③ wheels → ④ curves → ⑤ hue → ⑥ fx。
|
|
32
|
-
- ③ wheels: チャンネルごとに `c = v*(1-lift)+lift` → `c = pow(max(0,c), 1/(1+gamma))` → `c *= 1+gain` → `c = clamp01(c+offset)`
|
|
33
|
-
(lift / gamma / gain / offset は当該チャンネルの値・省略 0)。
|
|
34
|
-
- ④ curves: 区分線形。点列を in 昇順に評価し、`x ≤ 最初の in` は最初の out、`x ≥ 最後の in` は最後の out、
|
|
35
|
-
それ以外は挟む 2 点で線形補間、各評価を clamp01。**master を 3 ch に適用してから r / g / b を各 ch に適用**。
|
|
36
|
-
- ⑤ hue: RGB→HSV(`d = max-min`、`d > 1e-4` のときだけ h を計算(`cmax===r: ((g-b)/d+6)%6`・`cmax===g: (b-r)/d+2`・
|
|
37
|
-
else `(r-g)/d+4`・÷6)、`s = cmax > 1e-4 ? d/cmax : 0`、`v = cmax`)→ `shift = (sample(hue, h)-0.5)*2`・
|
|
38
|
-
`h' = (h+shift+1) % 1`・`s' = clamp01(s * sample(sat, h)*2)`・`v' = clamp01(v * sample(luma, h)*2)` → HSV→RGB
|
|
39
|
-
(sector = floor(h'*6) の 6 分割・`c = s'v'`・`x = c(1-|((h'*6) mod 2)-1|)`・`m = v'-c`・各 clamp01)。
|
|
40
|
-
`sample(ch, h)` = 点列を hue 昇順で評価、0 点なら 0.5、1 点ならその value、範囲外は端点、間は線形。
|
|
41
|
-
**h の参照は 3 ch とも変換前の h**(旧実装どおり)。
|
|
42
|
-
- identity 判定(書き込み側の規範): basic 全 0・lut 無し・wheels 全 0・curves 全 ch identity・hue 全 ch identity・fx 無しなら
|
|
43
|
-
`adjust` field 自体を除去(v0 §7 と同じ)。
|
|
44
|
-
- v1(cuts[] / layers[] 文書)には席を作らない(v0 と同じ)。
|
|
45
|
-
- ルックプリセット(D13)は語彙ではない: `presets/looks/index.jsonl`(`{id, kind:"look", name, description, when_to_use}`)+
|
|
46
|
-
`presets/looks/<id>.json` = `{ "id": "<id>", "adjust": { "basic": {…}, "wheels": {…} } }`。`adjust` の中身は `$defs.adjustV1` に
|
|
47
|
-
適合すること(schema テストで担保)。
|
|
48
|
-
|
|
49
|
-
基本補正は exposure ±3 EV、contrast / highlights / shadows / blacks / whites / temperature / tint / vibrance / saturation は ±1。全て任意、既定 0。lut は null または {lut: 空でない文字列, intensity?: 0..1}、intensity 既定 1。各 object は追加キー不可。
|
|
50
|
-
|
|
51
|
-
`fx` のパラメータはすべて任意。括弧内は既定値。
|
|
52
|
-
|
|
53
|
-
| id | パラメータ・範囲(既定値) | 意味 |
|
|
54
|
-
|---|---|---|
|
|
55
|
-
| `vignette` | `amount` −1..1(0.5)、`midpoint` 0..1(0.5)、`roundness` −1..1(0)、`feather` 0..1(0.5) | crop 適用後のローカル 0..1 箱で周辺減光。負の amount は明るくする。roundness は矩形寄り(−1)から縦横比を補正した円(1)へ補間。midpoint は開始位置、feather は遷移幅(0 は段差) |
|
|
56
|
-
| `blur` | `px` 0..50(8) | 半径は出力 px、`px × outputSize.x / 1920
|
|
57
|
-
| `grain` | `amount` 0..1(0.3)、`size` 0.5..4(1) |
|
|
58
|
-
| `sharpen` | `amount` 0..1(0.5) |
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
`
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
`
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
33
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
##
|
|
116
|
-
|
|
117
|
-
|
|
1
|
+
---
|
|
2
|
+
lifecycle: accepted
|
|
3
|
+
date: 2026-09-05
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# edit.json v2 clip adjust v1 契約
|
|
7
|
+
|
|
8
|
+
## 0. 位置づけ
|
|
9
|
+
|
|
10
|
+
v0 の基本補正と LUT に curves / wheels / hue と画素処理の fx を追加する。
|
|
11
|
+
|
|
12
|
+
## 1. 席
|
|
13
|
+
|
|
14
|
+
version 2 visual item の tracks[].items[].adjust。media / html / telop / filter / group / captions / caption の 7 定義共通。audio と shape、version 0 / 1 の cuts[] / layers[] には追加しない。
|
|
15
|
+
|
|
16
|
+
## 2. 語彙仕様 v1
|
|
17
|
+
|
|
18
|
+
`$defs.adjustV1`(v0 の `basic` / `lut` / `sections` は不変。以下を追加。すべて任意・additionalProperties false):
|
|
19
|
+
|
|
20
|
+
- `curves`: object `{ master?, r?, g?, b? }`。各値は `[{ in: number 0..1, out: number 0..1 }]`(minItems 2・maxItems 16・
|
|
21
|
+
各点 additionalProperties false・in / out とも required)。**`in` は狭義単調増加**(schema では表現できないので
|
|
22
|
+
validate-edit / edit-store / edit-lint で検査)。チャンネル identity = ちょうど 2 点 `[{0,0},{1,1}]`(許容 1e-5)。
|
|
23
|
+
- `wheels`: object `{ lift?, gamma?, gain?, offset? }`。各値は object `{ r?, g?, b? }`(number)。範囲:
|
|
24
|
+
lift ±0.25 / gamma ±0.5 / gain ±0.5 / offset ±0.1。省略 = 0(中立)。
|
|
25
|
+
- `hue`: object `{ hue?, sat?, luma? }`。各値は `[{ hue: number 0..1, value: number 0..1 }]`(minItems 1・maxItems 16・
|
|
26
|
+
additionalProperties false・両方 required)。**`hue` は狭義単調増加**。中立 value = 0.5。チャンネル identity =
|
|
27
|
+
省略または全点 `|value-0.5| ≤ 1e-4`。
|
|
28
|
+
- `fx`: 配列(maxItems 8)。各要素は `id` 必須・additionalProperties false。同じ id は 1 回まで。
|
|
29
|
+
配列順が適用順。空配列は書き込み側で除去し、読み取り側は未指定と同じに扱う。
|
|
30
|
+
- `sections`: `basic` / `lut` に加えて `curves` / `wheels` / `hue` / `fx`(boolean・false のときだけバイパス)。
|
|
31
|
+
- **演算順(固定)**: ① basic(v0 §3 の 1〜6)→ ② lut(trilinear・intensity 混合)→ ③ wheels → ④ curves → ⑤ hue → ⑥ fx。
|
|
32
|
+
- ③ wheels: チャンネルごとに `c = v*(1-lift)+lift` → `c = pow(max(0,c), 1/(1+gamma))` → `c *= 1+gain` → `c = clamp01(c+offset)`
|
|
33
|
+
(lift / gamma / gain / offset は当該チャンネルの値・省略 0)。
|
|
34
|
+
- ④ curves: 区分線形。点列を in 昇順に評価し、`x ≤ 最初の in` は最初の out、`x ≥ 最後の in` は最後の out、
|
|
35
|
+
それ以外は挟む 2 点で線形補間、各評価を clamp01。**master を 3 ch に適用してから r / g / b を各 ch に適用**。
|
|
36
|
+
- ⑤ hue: RGB→HSV(`d = max-min`、`d > 1e-4` のときだけ h を計算(`cmax===r: ((g-b)/d+6)%6`・`cmax===g: (b-r)/d+2`・
|
|
37
|
+
else `(r-g)/d+4`・÷6)、`s = cmax > 1e-4 ? d/cmax : 0`、`v = cmax`)→ `shift = (sample(hue, h)-0.5)*2`・
|
|
38
|
+
`h' = (h+shift+1) % 1`・`s' = clamp01(s * sample(sat, h)*2)`・`v' = clamp01(v * sample(luma, h)*2)` → HSV→RGB
|
|
39
|
+
(sector = floor(h'*6) の 6 分割・`c = s'v'`・`x = c(1-|((h'*6) mod 2)-1|)`・`m = v'-c`・各 clamp01)。
|
|
40
|
+
`sample(ch, h)` = 点列を hue 昇順で評価、0 点なら 0.5、1 点ならその value、範囲外は端点、間は線形。
|
|
41
|
+
**h の参照は 3 ch とも変換前の h**(旧実装どおり)。
|
|
42
|
+
- identity 判定(書き込み側の規範): basic 全 0・lut 無し・wheels 全 0・curves 全 ch identity・hue 全 ch identity・fx 無しなら
|
|
43
|
+
`adjust` field 自体を除去(v0 §7 と同じ)。
|
|
44
|
+
- v1(cuts[] / layers[] 文書)には席を作らない(v0 と同じ)。
|
|
45
|
+
- ルックプリセット(D13)は語彙ではない: `presets/looks/index.jsonl`(`{id, kind:"look", name, description, when_to_use}`)+
|
|
46
|
+
`presets/looks/<id>.json` = `{ "id": "<id>", "adjust": { "basic": {…}, "wheels": {…} } }`。`adjust` の中身は `$defs.adjustV1` に
|
|
47
|
+
適合すること(schema テストで担保)。
|
|
48
|
+
|
|
49
|
+
基本補正は exposure ±3 EV、contrast / highlights / shadows / blacks / whites / temperature / tint / vibrance / saturation は ±1。全て任意、既定 0。lut は null または {lut: 空でない文字列, intensity?: 0..1}、intensity 既定 1。各 object は追加キー不可。
|
|
50
|
+
|
|
51
|
+
`fx` のパラメータはすべて任意。括弧内は既定値。
|
|
52
|
+
|
|
53
|
+
| id | パラメータ・範囲(既定値) | 意味 |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| `vignette` | `amount` −1..1(0.5)、`midpoint` 0..1(0.5)、`roundness` −1..1(0)、`feather` 0..1(0.5) | crop 適用後のローカル 0..1 箱で周辺減光。負の amount は明るくする。roundness は矩形寄り(−1)から縦横比を補正した円(1)へ補間。midpoint は開始位置、feather は遷移幅(0 は段差) |
|
|
56
|
+
| `blur` | `px` 0..50(8) | 半径は出力 px、`px × outputSize.x / 1920` を作業テクセルへ換算。分離ガウス H → V の 2 パス(σ = 換算半径 / 2、各パス最大 33 タップ)。大半径は viewport を 1/2^k に縮小し、次パスで双一次拡大。サンプルは crop 内に clamp |
|
|
57
|
+
| `grain` | `amount` 0..1(0.3)、`size` 0.5..4(1) | 作業空間の画素と出力フレーム番号を使う決定論ノイズ。`floor(workPixel / size)` とフレーム番号を整数 hash に渡す。RGB 共通に ±amount×0.15 を加算して輝度を変える。sin による hash は使わない |
|
|
58
|
+
| `sharpen` | `amount` 0..1(0.5) | 作業テクセルの 3×3 平均との差を `rgb + amount × (rgb − average)` で加算し clamp |
|
|
59
|
+
| `glow` | `intensity` 0..1(0.5)、`radius` 0..100 px(20)、`threshold` 0..1(0.7)、`warmth` −1..1(0) | 高輝度部のにじみ。Rec.709 luma が threshold 以上の bright-pass → ガウス H → V → 加算合成の 4 パス。warmth は加算色を暖色 / 寒色へ寄せる |
|
|
60
|
+
| `clarity` | `amount` −1..1(0.3)、`radius` 1..50 px(10) | ガウス H → V → 合成の 3 パス。`rgb + amount × (rgb − gauss(rgb, radius))`。負で柔らかくする |
|
|
61
|
+
| `dehaze` | `amount` −1..1(0.3) | 3×3 dark channel の min で透過率を推定し復元する 1 パス。大気光は白、透過率の下限は 0.1。負は霞を足す |
|
|
62
|
+
| `denoise` | `amount` 0..1(0.3) | 5×5 bilateral の 1 パス。値域 σ = amount × 0.25、空間 σ = 2 作業テクセル |
|
|
63
|
+
| `motion_blur` | `px` 0..100(10)、`angle` −180..180 度(0) | 角度に沿う 17 タップ、全長 px の方向ぼかし(1 パス)。0 度は水平、正角は crop ローカルの下方向へ回転 |
|
|
64
|
+
|
|
65
|
+
第 2 群の radius / px も blur と同じ出力 px 規約(output.width / 1920)で換算する。
|
|
66
|
+
ゼロ強度は identity(glow は intensity、motion_blur は px、他は amount)。radius や threshold は強度判定に使わない。
|
|
67
|
+
|
|
68
|
+
旧 `cuts[].fx` は読み取り互換の語彙であり、`adjust.fx` と無関係。エンジンは従来どおり無視する。
|
|
69
|
+
|
|
70
|
+
## 3. 基本補正の数値契約
|
|
71
|
+
|
|
72
|
+
演算は video-space、すなわち gamma 符号化 sRGB 値のまま行う。scene-linear へ変換しない。
|
|
73
|
+
入力チャンネルを `c = (r, g, b)`、`clamp01(x) = min(1, max(0, x))`、Rec.709 luma を
|
|
74
|
+
`Y(c) = 0.2126r + 0.7152g + 0.0722b` とする。`smoothstep(a,b,x)` は
|
|
75
|
+
`t = clamp01((x-a)/(b-a))`、`t²(3-2t)` である。
|
|
76
|
+
|
|
77
|
+
演算順は固定で、次の順に進める。
|
|
78
|
+
|
|
79
|
+
1. exposure: `c *= 2^exposure`。
|
|
80
|
+
2. white balance: `r *= 1 + temperature*0.18`、`b *= 1 - temperature*0.18`、
|
|
81
|
+
`g *= 1 - tint*0.12` とし、各チャンネルを `clamp01` する。
|
|
82
|
+
3. tone zones: highlights → shadows → whites → blacks の順に処理する。各有効ステップの直前に
|
|
83
|
+
現在の `c` から luma を再計算し、処理後は各チャンネルを `clamp01` する。
|
|
84
|
+
- highlights: `c *= 1 + highlights*smoothstep(0.5,0.9,Y(c))`
|
|
85
|
+
- shadows: `c *= 1 + shadows*(1-smoothstep(0.1,0.5,Y(c)))`
|
|
86
|
+
- whites: `c += whites*smoothstep(0.7,1.0,Y(c))*0.3`
|
|
87
|
+
- blacks: `c += blacks*(1-smoothstep(0.0,0.3,Y(c)))*0.3`
|
|
88
|
+
4. contrast: 各チャンネルを `(c-0.5)*(1+contrast)+0.5` とし、`clamp01` する。pivot は `0.5`。
|
|
89
|
+
5. saturation: 現在の Rec.709 luma を使い、各チャンネルを
|
|
90
|
+
`Y(c) + (c-Y(c))*(1+saturation)` として `clamp01` する。
|
|
91
|
+
6. vibrance: 現在値の `max` と `min` から
|
|
92
|
+
`S = max > 1e-6 ? (max-min)/max : 0`、`amount = vibrance*(1-S)` を求め、各チャンネルを
|
|
93
|
+
`Y(c) + (c-Y(c))*(1+amount)` として `clamp01` する。
|
|
94
|
+
7. 外部 LUT: `lut` が有効なら trilinear sampler で `c` を置換し、`intensity` で identity 入力と
|
|
95
|
+
LUT 出力を線形混合する。
|
|
96
|
+
|
|
97
|
+
定数の正本値は `REC709 = (0.2126, 0.7152, 0.0722)`、`TEMP_COEF = 0.18`、
|
|
98
|
+
`TINT_COEF = 0.12`、`CONTRAST_PIVOT = 0.5` である。基本補正を LUT に bake する消費者は
|
|
99
|
+
`LUT_3D_SIZE 33`、R fastest → G → B、各成分小数 6 桁とし、適用時は trilinear 補間する。
|
|
100
|
+
|
|
101
|
+
## 4. 解決順とバイパス
|
|
102
|
+
|
|
103
|
+
basic → lut → wheels → curves → hue → ⑥ fx(配列順・mask / opacity / blend の前)→ item 合成 → output.look。fx が有効な cut A/B の各側と layer は、crop 窓を作業解像度へ描く prep パスで①〜⑤の `applyAdjust` を適用し、共有する 2 本の ping-pong FBO で効果パスを配列順に実行する。作業寸法は crop のテクセル寸法を出力寸法で上限 clamp し、FBO は最大出力寸法で確保・再利用する。
|
|
104
|
+
|
|
105
|
+
パス数は vignette / grain / sharpen 各 1、blur 2、glow 4、clarity 3、dehaze / denoise / motion_blur 各 1。glow / clarity の合成元には、その効果へ入る直前の画像を再利用テクスチャへ退避する(FBO は増やさない)。後続効果は先行効果の結果を近傍サンプルする。最終結果を元ソースの代わりに合成側で読み、adjust を二重適用しない。mask / opacity / blend はパス列の後で従来どおり適用する。
|
|
106
|
+
|
|
107
|
+
空間処理は LUT に bake しない。fx 無し・空配列・全効果ゼロ強度・sections.fx=false は prep を実行せず従来の直接経路を使い、fx 無しの出力はバイト不変。
|
|
108
|
+
|
|
109
|
+
LUT はスラッシュなしなら presets/luts/<id>/<id>.cube、ありならプロジェクト相対(Windows / POSIX の区切り対応)。sections は false のときだけ該当段をバイパスする。OFF はプレビューと書き出しの両方でバイパスし、保存値は保持してよい。
|
|
110
|
+
|
|
111
|
+
33³、R fastest → G → B、各成分 toFixed(6) の後 Float32 に格納、適用時 trilinear。正規化は範囲 clamp、点列昇順ソート、省略既定の補完。検証器は不正な点列を修復せず拒否する。補間 span < 1e-9 では左点を使用。curves identity は旧実装どおり各差の絶対値 < 1e-5、hue identity は ≤ 1e-4。basic の演算上 identity 許容は 1e-6。
|
|
112
|
+
|
|
113
|
+
注: hue value=1.0 は式 (value-0.5)*2 により +360°(一周)、+180° は value=0.75。旧実装の式を優先する。
|
|
114
|
+
|
|
115
|
+
## 5. 消費側の約束
|
|
116
|
+
|
|
117
|
+
M2-1 時点で新 3 セクションはエンジン未消費(bake 関数は用意・plan 未配線)。2/4 便で配線。GPU / OSR と frame-engine preview は同じ全段 bake とバイパスを使う。DOM fallback は新 3 セクションを CSS 近似できないため適用せず、色調整は近似表示の指標を出し、fx のうち blur だけは CSS `filter: blur()` で近似し、それ以外の fx は適用せず近似表示の指標で開示する。frame-engine active 時は二重適用しない。台帳は adjust の path 単位であり本便では行を増やさない。
|
|
118
|
+
|
|
119
|
+
## 6. lint 分担
|
|
120
|
+
|
|
121
|
+
Schema は閉じた構造・型・範囲・点数・必須キーを検査。validate-edit / edit-store / edit-lint はさらに in / hue の狭義単調増加を検査する。依存ゼロの検証器は意図的重複。edit-lint は adjust.curves.* / adjust.wheels.* / adjust.hue.* の check id と正確な path を返す。
|
|
122
|
+
|
|
123
|
+
## 7. 書き込み側・パネル側の約束
|
|
124
|
+
|
|
125
|
+
全段 identity なら adjust 自体を除去する。読み取り側は identity object を許す。セクション OFF は保存値を失わず戻せる。isItemAdjustIdentity は OFF を考慮する実効判定であり、書き込み側が OFF の値を削除する指示ではない。ルック適用は basic / wheels を丸ごと置換し、lut / curves / hue は保持する。
|
|
126
|
+
|
|
127
|
+
## 8. 非スコープ
|
|
128
|
+
|
|
129
|
+
スプリット比較、エフェクト UI、CSS 近似(blur を除く)、render-cut(ffmpeg 経路)、旧 cuts[].fx の実装、LUT ライブラリ。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "akari-video",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.50",
|
|
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": [
|
|
@@ -218,10 +218,34 @@ const AKARI_MD_STUB = [
|
|
|
218
218
|
'',
|
|
219
219
|
'この作業場(CreatorRoot)の規約・好みを書く場所です。',
|
|
220
220
|
'AKARI Video のエージェントは動画を作る前に、まずこのファイルを読みます。',
|
|
221
|
+
'効く順番: 一言の指示 > その動画の進め方(intake) > この akari.md > 製品の既定。',
|
|
221
222
|
'',
|
|
222
|
-
'##
|
|
223
|
+
'## やり方の既定',
|
|
223
224
|
'',
|
|
224
|
-
'
|
|
225
|
+
'- 何も言わなければ「提案つき」(頼まれたことに加えて良さそうな物をプレビューに入れて見せます。要らなければ消してください。判子は書き出しの 1 回)',
|
|
226
|
+
'- 「そのまま」と言ったら、言った通りに入れて見ずに書き出します。止まるのは「確認して」と言ったときだけ',
|
|
227
|
+
'- 絵コンテは、映像が無い・位置関係や動きを先に決めたい・全体像を先に見たい、のどれかのときだけ作ります',
|
|
228
|
+
'',
|
|
229
|
+
'## 調達の好み(何も言わなければこう解釈する)',
|
|
230
|
+
'',
|
|
231
|
+
'| 仕事 | 既定 | 補足 |',
|
|
232
|
+
'|---|---|---|',
|
|
233
|
+
'| B ロール | (未記入) | |',
|
|
234
|
+
'| 図解・テロップ | (未記入) | |',
|
|
235
|
+
'| ナレーション | (未記入) | |',
|
|
236
|
+
'| BGM・効果音 | (未記入) | |',
|
|
237
|
+
'| 文字起こし | (未記入) | |',
|
|
238
|
+
'| 人物の実写 | (未記入) | |',
|
|
239
|
+
'',
|
|
240
|
+
'- 表に無い仕事に初めて当たったら、エージェントは 1 問だけ聞いて、答えをこの表に 1 行足すことを申し出ます。二度目は聞きません',
|
|
241
|
+
'',
|
|
242
|
+
'## 見た目の既定',
|
|
243
|
+
'',
|
|
244
|
+
'(画角・字幕の位置と書体・テロップの口調・書き出しサイズなど。未記入なら製品の既定)',
|
|
245
|
+
'',
|
|
246
|
+
'## 聞かれて答えたこと(エージェントが追記する)',
|
|
247
|
+
'',
|
|
248
|
+
'(まだありません)',
|
|
225
249
|
''
|
|
226
250
|
].join('\n');
|
|
227
251
|
|
|
@@ -37,6 +37,12 @@ test('createCreatorRoot: 契約 §3 の正準構造を生成する', async () =>
|
|
|
37
37
|
|
|
38
38
|
const akariMd = await readFile(join(target, 'akari.md'), 'utf8');
|
|
39
39
|
assert.match(akariMd, /好み/);
|
|
40
|
+
assert.match(akariMd, /^## やり方の既定$/m);
|
|
41
|
+
assert.match(akariMd, /^## 調達の好み(何も言わなければこう解釈する)$/m);
|
|
42
|
+
assert.match(akariMd, /^## 見た目の既定$/m);
|
|
43
|
+
assert.match(akariMd, /^## 聞かれて答えたこと(エージェントが追記する)$/m);
|
|
44
|
+
assert.ok(akariMd.includes('効く順番: 一言の指示 > その動画の進め方(intake) > この akari.md > 製品の既定。'));
|
|
45
|
+
assert.ok(akariMd.includes('- 表に無い仕事に初めて当たったら、エージェントは 1 問だけ聞いて、答えをこの表に 1 行足すことを申し出ます。二度目は聞きません'));
|
|
40
46
|
assert.match(await readFile(join(target, 'CLAUDE.md'), 'utf8'), /akari\.md/);
|
|
41
47
|
assert.match(await readFile(join(target, 'AGENTS.md'), 'utf8'), /akari\.md/);
|
|
42
48
|
|