akari-video 0.1.42 → 0.1.44
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/vendor/.akari-capability-sources.json +1 -0
- package/vendor/docs/contract-2026-08-28-gpu-export-v0.md +1 -1
- package/vendor/packages/akari-launcher/package.json +1 -1
- package/vendor/packages/gpu-export/README.ja.md +1 -1
- package/vendor/packages/gpu-export/README.md +1 -1
- package/vendor/packages/overlay-runtime/README.md +3 -0
- package/vendor/packages/schemas/bin/validate-asset.mjs +38 -1
- package/vendor/packages/schemas/test/validate-glass-asset.test.mjs +56 -0
- package/vendor/skills/overlay-authoring/SKILL.md +1 -0
- package/vendor/skills/overlay-authoring/glass.md +93 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "akari-video",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.44",
|
|
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": {
|
|
@@ -167,6 +167,7 @@
|
|
|
167
167
|
"skills/harvest-asset/SKILL.md",
|
|
168
168
|
"skills/manage-connections/SKILL.md",
|
|
169
169
|
"skills/overlay-authoring/3d.md",
|
|
170
|
+
"skills/overlay-authoring/glass.md",
|
|
170
171
|
"skills/overlay-authoring/motion.md",
|
|
171
172
|
"skills/overlay-authoring/SKILL.md",
|
|
172
173
|
"skills/overlay-authoring/table.md",
|
|
@@ -423,7 +423,7 @@ v3 は、宣言型 Three.js scene の HTML 部分にある CSS animation / trans
|
|
|
423
423
|
`threeRuntime.render(container, t)` へ直接渡し、scene 内部の animation、動画 texture、ready 判定は
|
|
424
424
|
変更しない。登場表現を従来の文法へ解析できる場合は理由 `three-scene-entrance-curve`、解析できない場合は
|
|
425
425
|
計算済みスタイルを実測する理由 `three-scene-entrance-sampled` とする。解析不能だけを理由に fail-closed
|
|
426
|
-
にはしない。CSS animation のない宣言型 3D
|
|
426
|
+
にはしない。CSS animation のない宣言型 3D は他の条件を持たない場合は理由 `three-scene-canvas-direct` のままとし、`advanced-css` や CSS 3D 幾何を伴う場合は composite 経路(`three-scene-sampled-composite`)で断片全体を転写する。
|
|
427
427
|
|
|
428
428
|
curve モードは従来どおり、対になった `[data-akari-active] .root, [data-no-timeline] .root` selector、
|
|
429
429
|
1 本・2 endpoint の keyframe、既知の timing、非負 delay、iteration 1、normal direction、`both` または
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "akari-video",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.44",
|
|
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": [
|
|
@@ -79,7 +79,7 @@ sheet / DOM 間のカスタムプロパティ補間パリティを実測する
|
|
|
79
79
|
composite の入口外条件は `three-sampled-condition:<条件名>` を報告します。方式 A の
|
|
80
80
|
`three-sampled-chain-css:<プロパティ>` ガードは残します。manifest は `entranceMode`、receipt は
|
|
81
81
|
`curve` / `sampled` / `composite` mode、sampling 費用、composite の DOM 要素数と canvas 中継・DOM 層費用の
|
|
82
|
-
p50/p95 を記録します。CSS animation のない scene
|
|
82
|
+
p50/p95 を記録します。CSS animation のない scene は他の条件を持たない場合は従来どおり `three-scene-canvas-direct` とし、`advanced-css` や CSS 3D 幾何を伴う場合は composite 経路(`three-scene-sampled-composite`)で断片全体を転写します。
|
|
83
83
|
|
|
84
84
|
`render-cut --engine auto` は macOS / Windows で GPU を候補にし、プロジェクト全体が適格なら GPU、
|
|
85
85
|
不適格なら OSR を使います。Linux の `auto` は legacy のままで、`--engine gpu` を明示した場合だけ
|
|
@@ -87,7 +87,7 @@ Extending `preserve3dOrderConflicts` to sibling pairs can re-enable this shape i
|
|
|
87
87
|
continue to pass with a warning (measured parity 0.6374).
|
|
88
88
|
Manifests record `entranceMode`, and receipts record
|
|
89
89
|
`curve` / `sampled` / `composite`, sampling cost, plus composite DOM-element and p50/p95 copy/DOM-layer costs.
|
|
90
|
-
Scenes without CSS animation remain `three-scene-canvas-direct
|
|
90
|
+
Scenes without CSS animation remain `three-scene-canvas-direct` when no other conditions are present; scenes with `advanced-css` or CSS 3D geometry transfer the entire fragment through the composite path (`three-scene-sampled-composite`).
|
|
91
91
|
|
|
92
92
|
`render-cut --engine auto` considers GPU export on macOS and Windows, using it when the complete
|
|
93
93
|
project is eligible and otherwise using OSR. On Linux, `auto` remains legacy and GPU export is
|
|
@@ -53,6 +53,9 @@ Three.js + glTF シーンを決定的な時刻で描画し(`three-runtime.js`
|
|
|
53
53
|
自動でこの順に埋め込む — 同じ順序をホストの `<script>` タグでも守ること)。ランタイム読込後、
|
|
54
54
|
`font` 省略を許すホストは mount より前に
|
|
55
55
|
`window.akari.threeRuntime.configure({ defaultFontUrl })` を 1 回呼ぶ
|
|
56
|
+
ガラス宣言を扱うホストは `src/glass-runtime.js` を `src/overlay-runtime.js` より前に読み込む。
|
|
57
|
+
`backdrop` は断片相対。ホストは `htmlPath` を配信 URL で渡すか、宣言の `backdrop` を配信 URL に解決する。
|
|
58
|
+
preview-server は素材同梱の `runtime/glass-runtime.js` を読み込む。
|
|
56
59
|
4. テキスト分割断片(`data-akari-split`)を扱うホストは、`src/interaction.js` より前に
|
|
57
60
|
`src/vendor/budoux-ja-bundle.js` → `src/text-split.js` の順で読み込む。
|
|
58
61
|
未読込でも他機能は動くが、日本語の文節分割が精度の落ちる近似になり
|
|
@@ -416,12 +416,42 @@ function validateFiles() {
|
|
|
416
416
|
}
|
|
417
417
|
}
|
|
418
418
|
|
|
419
|
+
if (Array.isArray(meta?.requires) && meta.requires.includes("glass-runtime")) {
|
|
420
|
+
for (const filePath of payloadFiles) {
|
|
421
|
+
const name = relativeToAsset(filePath).replaceAll("\\", "/");
|
|
422
|
+
if (name === "fragment.html" || /^variants\/[^/]+\.html$/i.test(name)) validateGlassDeclaration(filePath);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
419
425
|
for (const filePath of payloadFiles) {
|
|
420
426
|
if (/\.(?:html?|css|svg|m?js|cjs)$/i.test(filePath)) validateLocalReferences(filePath);
|
|
421
427
|
else if (/\.gltf$/i.test(filePath)) validateGltfReferences(filePath);
|
|
422
428
|
}
|
|
423
429
|
}
|
|
424
430
|
|
|
431
|
+
function validateGlassDeclaration(filePath) {
|
|
432
|
+
const source = fs.readFileSync(filePath, "utf8").replace(/<!--[\s\S]*?-->/gu, "");
|
|
433
|
+
const pattern = /<script\b(?=[^>]*\btype\s*=\s*(?:"application\/json"|'application\/json'))(?=[^>]*\bdata-akari-glass-scene\b)[^>]*>([\s\S]*?)<\/script\s*>/giu;
|
|
434
|
+
const declarations = [...source.matchAll(pattern)];
|
|
435
|
+
if (!declarations.length) fail(`${relativeToAsset(filePath)} に data-akari-glass-scene 宣言が見つかりません`);
|
|
436
|
+
const elements = source.replace(/<script\b[^>]*>[\s\S]*?<\/script\s*>/giu, "").replace(/<style\b[^>]*>[\s\S]*?<\/style\s*>/giu, "");
|
|
437
|
+
if (declarations.length && !/<[a-z][^>]*\sdata-akari-glass(?=\s|=|\/?>)/iu.test(elements)) {
|
|
438
|
+
fail(`${relativeToAsset(filePath)}: 宣言があるのにガラス面が無い`);
|
|
439
|
+
}
|
|
440
|
+
for (const match of declarations) {
|
|
441
|
+
let descriptor;
|
|
442
|
+
try { descriptor = JSON.parse(match[1]); }
|
|
443
|
+
catch (error) { fail(`data-akari-glass-scene の JSON を読めません: ${messageOf(error)}`); continue; }
|
|
444
|
+
if (!isPlainObject(descriptor)) { fail("data-akari-glass-scene は JSON object である必要があります"); continue; }
|
|
445
|
+
if (descriptor.backdrop === undefined) continue;
|
|
446
|
+
const backdrop = descriptor.backdrop;
|
|
447
|
+
if (typeof backdrop !== "string" || !backdrop.trim() || /^[a-z][a-z\d+.-]*:|^[\/\\]/iu.test(backdrop) || backdrop.includes("\\")) {
|
|
448
|
+
fail("data-akari-glass-scene.backdrop は相対パスである必要があります");
|
|
449
|
+
continue;
|
|
450
|
+
}
|
|
451
|
+
validateReference(filePath, backdrop);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
425
455
|
// data-akari-3d-scene 宣言が model を持たず、かつ非空の texts[] を持つときだけ glb を任意化する
|
|
426
456
|
// (overlay-runtime/src/three-runtime.js の readDescriptor と同じ判定。texts[] も model も
|
|
427
457
|
// 無い宣言・宣言を読めない場合は従来どおり glb を必須のまま扱う=安全側デフォルト)。
|
|
@@ -496,7 +526,14 @@ function validateLocalReferences(filePath) {
|
|
|
496
526
|
/\.load(?:Async)?\s*\(\s*["']([^"']+)["']/gi,
|
|
497
527
|
];
|
|
498
528
|
for (const pattern of patterns) {
|
|
499
|
-
for (const match of source.matchAll(pattern))
|
|
529
|
+
for (const match of source.matchAll(pattern)) {
|
|
530
|
+
// new URL(url, base) is a dynamic JS constructor, not CSS url().
|
|
531
|
+
// Limit this correction to glass packs; keep literal CSS and JS loaders checked.
|
|
532
|
+
if (pattern === patterns[1] && meta?.requires?.includes("glass-runtime")
|
|
533
|
+
&& /\.(?:m?js|cjs)$/i.test(filePath) && match[0].startsWith("URL(")
|
|
534
|
+
&& /\bnew\s*$/u.test(source.slice(0, match.index))) continue;
|
|
535
|
+
references.add(match[1].trim());
|
|
536
|
+
}
|
|
500
537
|
}
|
|
501
538
|
|
|
502
539
|
for (const match of source.matchAll(/\bimport\s+(?:[^"']*?\s+from\s+)?["']([^"']+)["']/gi)) {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
3
|
+
import { cpSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync, rmSync } from 'node:fs';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import test from 'node:test';
|
|
7
|
+
|
|
8
|
+
const cli = new URL('../bin/validate-asset.mjs', import.meta.url);
|
|
9
|
+
const declaration = (value) => `<script type="application/json" data-akari-glass-scene>${JSON.stringify(value)}</script>`;
|
|
10
|
+
function fixture(t) {
|
|
11
|
+
const root = mkdtempSync(join(tmpdir(), 'akari-glass-asset-'));
|
|
12
|
+
t.after(() => rmSync(root, { recursive: true, force: true }));
|
|
13
|
+
const dir = join(root, 'overlay/lower-third-clean');
|
|
14
|
+
cpSync(new URL('./fixtures/asset/valid-library/overlay/lower-third-clean', import.meta.url), dir, { recursive: true });
|
|
15
|
+
const meta = JSON.parse(readFileSync(join(dir, 'meta.json')));
|
|
16
|
+
meta.requires = ['glass-runtime'];
|
|
17
|
+
writeFileSync(join(dir, 'meta.json'), JSON.stringify(meta));
|
|
18
|
+
for (const sub of ['variants', 'runtime', 'backgrounds']) mkdirSync(join(dir, sub));
|
|
19
|
+
writeFileSync(join(dir, 'backgrounds/bg.png'), 'image');
|
|
20
|
+
writeFileSync(join(dir, 'sample-press.mp4'), 'sample');
|
|
21
|
+
cpSync(new URL('../../overlay-runtime/src/glass-runtime.js', import.meta.url), join(dir, 'runtime/glass-runtime.js'));
|
|
22
|
+
writeFileSync(join(dir, 'fragment.html'), `<div data-akari-glass>${declaration({ backdrop: 'backgrounds/bg.png' })}</div>`);
|
|
23
|
+
writeFileSync(join(dir, 'variants/press.html'), `<div data-akari-glass>${declaration({ backdrop: '../backgrounds/bg.png' })}</div>`);
|
|
24
|
+
return dir;
|
|
25
|
+
}
|
|
26
|
+
const run = (dir) => spawnSync(process.execPath, [cli.pathname, dir], { encoding: 'utf8' });
|
|
27
|
+
|
|
28
|
+
test('glass pack variants, runtime, backgrounds and sample mp4 pass', (t) => {
|
|
29
|
+
const result = run(fixture(t));
|
|
30
|
+
assert.equal(result.status, 0, result.stderr);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('glass declaration validation rejects malformed JSON, missing surfaces and bad references', (t) => {
|
|
34
|
+
const dir = fixture(t);
|
|
35
|
+
for (const [html, error] of [
|
|
36
|
+
[declaration({}), /ガラス面が無い/],
|
|
37
|
+
['<div data-akari-glass>' + declaration([]) + '</div>', /JSON object/],
|
|
38
|
+
...['https://example.com/bg.png', 'data:image/png;base64,AA==', 'missing.png', '/tmp/bg.png', '../outside.png', 42].map((backdrop) => [`<div data-akari-glass>${declaration({ backdrop })}</div>`, /相対パス|見つかりません|ディレクトリ外/]),
|
|
39
|
+
['<div data-akari-glass><script type="application/json" data-akari-glass-scene>{</script></div>', /JSON を読めません/],
|
|
40
|
+
]) {
|
|
41
|
+
writeFileSync(join(dir, 'variants/press.html'), html);
|
|
42
|
+
const result = run(dir);
|
|
43
|
+
assert.equal(result.status, 1, html);
|
|
44
|
+
assert.match(result.stderr, error);
|
|
45
|
+
}
|
|
46
|
+
writeFileSync(join(dir, 'variants/press.html'), `<div data-akari-glass>${declaration({})}</div>`);
|
|
47
|
+
assert.equal(run(dir).status, 0, 'backdrop is optional');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('quoted JS asset loaders still detect missing pack assets', (t) => {
|
|
51
|
+
const dir = fixture(t);
|
|
52
|
+
writeFileSync(join(dir, 'runtime/missing.js'), 'const image = new URL("missing.png", document.baseURI);');
|
|
53
|
+
assert.match(run(dir).stderr, /missing.png/);
|
|
54
|
+
writeFileSync(join(dir, 'runtime/missing.js'), 'const css = `background: url(missing-style.png)`;');
|
|
55
|
+
assert.match(run(dir).stderr, /missing-style.png/);
|
|
56
|
+
});
|
|
@@ -38,6 +38,7 @@ description: AKARI Video のオーバーレイ HTML、字幕、表・グラフ
|
|
|
38
38
|
- 字幕・テロップの日本語組版、可読性、配置: [telop.md](telop.md)
|
|
39
39
|
- 表・グラフの HTML/CSS 構成とアニメーション: [table.md](table.md)
|
|
40
40
|
- Three.js + glTF、動画テクスチャ、3D 性能: [3d.md](3d.md)
|
|
41
|
+
- ガラス屈折の宣言、入れ子、ツマミ、静止背景: [glass.md](glass.md)
|
|
41
42
|
- 決定的モーション、イージング、compositor 制約: [motion.md](motion.md)
|
|
42
43
|
- サムネイルの型、デザイン語彙、生成経路、HTML スクショ: [thumbnail.md](thumbnail.md)
|
|
43
44
|
- 人物切り抜き、HEVC alpha、text-behind-person: [text-behind-person.md](text-behind-person.md)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Glass refraction authoring
|
|
2
|
+
|
|
3
|
+
## 経路の振り分け(まずここを判定)
|
|
4
|
+
|
|
5
|
+
ガラス屈折は同梱の `glass-runtime.js` に任せ、断片は宣言と CSS だけを書く。
|
|
6
|
+
ホストは `glass-runtime.js` を `overlay-runtime.js` より前に読み込む。
|
|
7
|
+
任意 script、CDN、html2canvas、独自 rAF を断片に持ち込まない。
|
|
8
|
+
|
|
9
|
+
## 現在の実装ゲート
|
|
10
|
+
|
|
11
|
+
背景は **(a) 静止画**のみ。`backdrop` は断片ファイルからの相対パス。
|
|
12
|
+
3D の `model` は edit.json 相対なので、基準ディレクトリを混同しない。
|
|
13
|
+
ホストは断片相対をプロジェクト入力に束縛し、プレビューでは localhost の配信 URL、
|
|
14
|
+
書き出しでは画像 data URI に解決する。宣言には http(s): / data: を直接書かない。
|
|
15
|
+
|
|
16
|
+
(b) 下のトラックと同じ動画を渡す方式、(c) engine が合成直下の under-frame を供給する方式は次段。
|
|
17
|
+
現状のガラスが写すのは宣言した画像であり、下の動画を自動で取り込むものではない。
|
|
18
|
+
背景省略は検証上許されるが、通常のホストは `render(..., {})` なので画像の明示が必要。
|
|
19
|
+
|
|
20
|
+
## 宣言型 fragment スキーマ
|
|
21
|
+
|
|
22
|
+
単一ルート内に非実行 JSON 宣言を 1 個と `[data-akari-glass]` 要素を 1 個以上置く。
|
|
23
|
+
canvas はランタイムが作る。面に position、寸法、px 単位の角丸を与え、文字は canvas より前面に置く。
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<div class="glass-card">
|
|
27
|
+
<style>
|
|
28
|
+
.glass-card__surface {
|
|
29
|
+
position: relative; width: var(--button-width, 280px); height: var(--button-height, 90px);
|
|
30
|
+
border-radius: var(--button-radius, 36px);
|
|
31
|
+
--glass-tint: var(--lg-tint, 0.06);
|
|
32
|
+
--glass-blur: var(--lg-blur, 2.5);
|
|
33
|
+
--glass-edge-intensity: var(--lg-lens, 0.035);
|
|
34
|
+
--glass-rim-intensity: calc(var(--lg-lens, 0.035) * 3.7);
|
|
35
|
+
--glass-rim-distance: var(--lg-lens-width, 0.6);
|
|
36
|
+
--glass-ripple: var(--lg-ripple, 0);
|
|
37
|
+
}
|
|
38
|
+
.glass-card__label { position: relative; z-index: 1; color: var(--lg-text-color, #fff); }
|
|
39
|
+
</style>
|
|
40
|
+
<div class="glass-card__surface" data-akari-glass><span class="glass-card__label">再生する</span></div>
|
|
41
|
+
<script type="application/json" data-akari-glass-scene>{"backdrop":"backgrounds/rooftop.jpg"}</script>
|
|
42
|
+
</div>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`variants/press.html` から同じ背景を参照するなら `../backgrounds/rooftop.jpg`。
|
|
46
|
+
素材の meta.json は `requires: ["glass-runtime"]` を宣言する。
|
|
47
|
+
|
|
48
|
+
## 入れ子
|
|
49
|
+
|
|
50
|
+
`[data-akari-glass]` の中に別の `[data-akari-glass]` を置くと、親の canvas を子が屈折させる。
|
|
51
|
+
描画順は document order の親 → 子。親 canvas の代わりに背景画像を子へ再投入しない。
|
|
52
|
+
子は親より濁りやすいので tint を確認する。円は正方形とし、角丸は % ではなく px にする。
|
|
53
|
+
|
|
54
|
+
## ツマミ — 生値と製品レシピ
|
|
55
|
+
|
|
56
|
+
ランタイムは `--glass-*` を読む。製品断片が `--lg-*` から写す二層構造で、
|
|
57
|
+
動画側の `overlays[].vars` では基本的に `--lg-*` を調整する。
|
|
58
|
+
以下は PoC の製品レシピ既定値。生値の既定とは区別する。
|
|
59
|
+
|
|
60
|
+
| 変数 | 既定 | 意味 |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| `--lg-tint` | 0.06(原作 0.2) | 白グラデの混合。大きいほど濁る |
|
|
63
|
+
| `--lg-blur` | 2.5(原作 5) | ぼかし |
|
|
64
|
+
| `--lg-lens` | 0.035(原作 edge 0.01) | 縁の屈折。rim は 3.7 倍へ写す |
|
|
65
|
+
| `--lg-lens-width` | 0.6(原作 0.8) | レンズ帯の減衰。小さいほど広い |
|
|
66
|
+
| `--lg-ripple` | 0(原作 0.1) | 縁の波紋 |
|
|
67
|
+
| `--lg-scale` | 1(drag は 2) | 寸法・文字・影・経路の倍率 |
|
|
68
|
+
| `--lg-press-at` / `--lg-press-step` | 1s / 0.7s | i 番目の押下 = at + i × step |
|
|
69
|
+
| `--lg-drag-scale` | 1.07 | 掴んだときの倍率 |
|
|
70
|
+
| `--lg-text-color` / `--lg-font` / `--lg-shadow` / `--lg-flash` / `--anim` | #fff / system-ui / 1 / 1 / 1 | 文字・書体・影・フラッシュ・アニメ省略 |
|
|
71
|
+
|
|
72
|
+
`--glass-warp` / `--glass-base-intensity` / `--glass-base-distance` /
|
|
73
|
+
`--glass-edge-distance` / `--glass-corner-boost` は生値を継承して微調整できる。
|
|
74
|
+
予約変数 `--x` / `--y` / `--scale` / `--rotate` を自前用途に使わない。
|
|
75
|
+
|
|
76
|
+
## 決定的モーションと禁止事項
|
|
77
|
+
|
|
78
|
+
ホストが CSS/WAAPI を localSeconds にシークし、その後
|
|
79
|
+
`glassRuntime.render(container, localSeconds, {})` を呼ぶ。初期化中は
|
|
80
|
+
`inspect(container).status` を 10 ms ごとに確認し、ready / error を待つ。
|
|
81
|
+
非表示・unmount 時は `dispose(container)` で GPU リソースを返す。
|
|
82
|
+
|
|
83
|
+
任意 script、wall-clock、未 seed 乱数、`backdrop-filter` は禁止。
|
|
84
|
+
ripple は既定 0 とし、意図なく上げて縁を波打たせない。
|
|
85
|
+
掴む動きと離す動きの transform アニメを同一要素で競合させず、1 本へまとめるか層を分ける。
|
|
86
|
+
|
|
87
|
+
## 検証と落とし穴
|
|
88
|
+
|
|
89
|
+
同時刻を往復シークして PNG の md5 を比較する。9:16(1080×1920)でも
|
|
90
|
+
背景を center / cover で敷き、面内と下の背景の位置が一致することを確認する。
|
|
91
|
+
GLSL の cover 写像、premultiplied alpha 出力、親 → 子の順序は変えない。
|
|
92
|
+
ランタイムをインライン化するホストは `inlineScript()` で `</script` をエスケープする。
|
|
93
|
+
`validate-asset` で背景の存在とガラス面を検査し、ガラス宣言なしの 2D / 3D シートも比較する。
|