akari-video 0.1.72 → 0.1.74
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/README.md +6 -2
- package/package.json +1 -1
- package/src/cli.mjs +9 -1
- package/src/kits.mjs +24 -25
- package/src/store-command.mjs +12 -6
- package/vendor/docs/contract-2026-07-13-asset-library.md +8 -4
- package/vendor/docs/contract-2026-08-02-creator-root-v1.md +6 -2
- package/vendor/docs/contract-2026-09-02-asset-reference-model.md +55 -5
- package/vendor/docs/contract-2026-09-13-generation-v0.md +56 -9
- package/vendor/packages/akari-launcher/README.md +6 -2
- package/vendor/packages/akari-launcher/package.json +1 -1
- package/vendor/packages/asset-resolver/README.md +30 -5
- package/vendor/packages/asset-resolver/bin/akari-assets.mjs +13 -4
- package/vendor/packages/asset-resolver/src/bundle.mjs +3 -5
- package/vendor/packages/asset-resolver/src/installed.mjs +39 -29
- package/vendor/packages/asset-resolver/src/library.mjs +24 -35
- package/vendor/packages/asset-resolver/src/resolve.mjs +11 -9
- package/vendor/packages/asset-resolver/src/state.mjs +3 -1
- package/vendor/packages/asset-resolver/test/installed-assets.test.mjs +1 -1
- package/vendor/packages/asset-resolver/test/library-migration.test.mjs +49 -0
- package/vendor/packages/audio-library-setup/README.md +6 -2
- package/vendor/packages/audio-library-setup/bin/beat-grid.mjs +6 -5
- package/vendor/packages/audio-library-setup/bin/declare-helper.mjs +2 -2
- package/vendor/packages/audio-library-setup/bin/fetch-akari-sounds.mjs +5 -4
- package/vendor/packages/audio-library-setup/bin/gallery-helper.mjs +2 -2
- package/vendor/packages/audio-library-setup/bin/register-drop-folder.mjs +3 -2
- package/vendor/packages/audio-library-setup/bin/review-sfx-mapping.mjs +6 -5
- package/vendor/packages/audio-library-setup/bin/suggest-bgm.mjs +7 -6
- package/vendor/packages/audio-library-setup/bin/suggest-sfx.mjs +6 -6
- package/vendor/packages/audio-library-setup/declare-server.mjs +7 -20
- package/vendor/packages/audio-library-setup/gallery-server.mjs +7 -14
- package/vendor/packages/audio-library-setup/shared/library-roots.mjs +33 -0
- package/vendor/packages/audio-library-setup/test/library-location.test.mjs +68 -0
- package/vendor/packages/creator-root/src/index.mjs +295 -1
- package/vendor/packages/creator-root/test/library-migration.test.mjs +229 -0
- package/vendor/packages/edit-lint/src/edit-lint.mjs +4 -4
- package/vendor/packages/edit-lint/src/library-reference.mjs +33 -16
- package/vendor/packages/edit-store/lib/edit-v2-item-write.d.ts +1 -0
- package/vendor/packages/edit-store/lib/edit-v2-item-write.js +117 -10
- package/vendor/packages/edit-store/lib/generation-meta.d.ts +40 -2
- package/vendor/packages/edit-store/lib/generation-meta.js +21 -1
- package/vendor/packages/schemas/fixtures/generation-meta/generating-placeholder.json +61 -0
- package/vendor/packages/schemas/fixtures/generation-meta/planned-next.json +85 -0
- package/vendor/packages/schemas/fixtures/generation-meta/still-next.json +106 -0
- package/vendor/packages/schemas/generation-meta.schema.json +150 -0
- package/vendor/packages/schemas/test/generation-meta.test.mjs +12 -1
- package/vendor/skills/akari/SKILL.md +5 -0
- package/vendor/skills/declare-audio/SKILL.md +8 -3
- package/vendor/skills/declare-audio/after-save.md +7 -2
- package/vendor/skills/declare-audio/launch.md +8 -4
- package/vendor/skills/edit-plan/beat-sync.md +7 -3
- package/vendor/skills/edit-plan/expression-selection.md +5 -2
- package/vendor/skills/edit-plan/report-guide.md +6 -2
- package/vendor/skills/harvest-asset/SKILL.md +7 -2
- package/vendor/skills/setup-audio-library/SKILL.md +7 -2
- package/vendor/skills/setup-audio-library/assisted-fetch.md +6 -2
- package/vendor/skills/setup-audio-library/drop-folder.md +6 -2
- package/vendor/skills/setup-audio-library/first-party.md +6 -2
- package/vendor/skills/setup-audio-library/gallery.md +7 -4
- package/vendor/skills/setup-audio-library/store-unlock.md +5 -1
- package/vendor/skills/setup-library/fetch-and-validate.md +5 -1
- package/vendor/templates/project-default/AGENTS.md +6 -2
- package/vendor/templates/project-default/CLAUDE.md +6 -2
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# akari-launcher(`akari` コマンド)
|
|
2
2
|
|
|
3
|
+
ライブラリの置き場は既定で作業場の `library/`。作業場が無いときは従来の `~/.akari/assets/` を使う。
|
|
4
|
+
`akari-assets list`(または `akari assets list`)の先頭行で実際の置き場を確認する。
|
|
5
|
+
以下の `<ライブラリの置き場>` はその表示先を指し、音源はその下の `audio/` に入る。
|
|
6
|
+
|
|
3
7
|
「UI に依存したくない。opencode 単体でも、どんなディレクトリでも始められるように」を
|
|
4
8
|
実現する薄いラッパー CLI。npm パッケージ名は `akari-video`、提供するコマンド名は `akari`
|
|
5
9
|
(npm の `akari` は別プロダクトが取得済みのため。オーナー裁定 2026-07-21 §8-2)。
|
|
@@ -24,7 +28,7 @@ akari
|
|
|
24
28
|
├─ 4. 公式音源ライブラリ(AKARI Sounds)の初回セットアップ(src/sounds-setup.mjs):
|
|
25
29
|
│ 未導入かつ TTY のとき生涯 1 回だけ [Y/n](既定 Yes)を聞き、Yes なら
|
|
26
30
|
│ packages/audio-library-setup/bin/fetch-akari-sounds.mjs で一括ダウンロード。
|
|
27
|
-
│ n は marker
|
|
31
|
+
│ n は marker(<ライブラリの置き場>/audio/.akari-sounds-declined.json)を書いて以後
|
|
28
32
|
│ 聞かない。再入口は `akari sounds`。失敗しても起動は止めない
|
|
29
33
|
│
|
|
30
34
|
└─ 5. 最後に opencode を exec する
|
|
@@ -48,7 +52,7 @@ DL・sha256 検証・適用まで実行。それ以外(npm グローバル / g
|
|
|
48
52
|
`akari store <connect|status|install|download|disconnect>`(AKARI Store 連携。マイページで発行した
|
|
49
53
|
接続トークンを `~/.akari/store-credentials.json`(0600)に保存し、購入済み一覧の確認と
|
|
50
54
|
配布物の取得ができる。`install <productId> [--from <zip>]` は購入パックを展開し、`PACK.json` の
|
|
51
|
-
収載素材を
|
|
55
|
+
収載素材を `<ライブラリの置き場>/installed.json` へ登録する。`--from` は開発・オフライン導入時に手元の
|
|
52
56
|
zip を使う。`src/store-command.mjs`)/
|
|
53
57
|
`akari assets <list|fetch|sync|...>`(素材カタログの一覧・取得・同期。
|
|
54
58
|
`packages/asset-resolver` の CLI への薄い委譲で、カタログ合成・entitlements 判定・
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "akari-video",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.74",
|
|
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": {
|
package/src/cli.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { detectProjectState } from './project-state.mjs';
|
|
|
7
7
|
import { findClaudeExecutable, findExecutable, findOpencodeExecutable } from './path-lookup.mjs';
|
|
8
8
|
import { loadTaskLabels } from './task-labels.mjs';
|
|
9
9
|
import { describeForceReinstall, describeInstalledVersions, describeIntake, claudeMissingGuidance, opencodeMissingGuidance, describeUpdateCacheFallback, describeUpdateCommand, describeVersionStatus, formatUpdateNotice } from './messages.mjs';
|
|
10
|
-
import { resolveEffectiveProjectRoot } from './first-run.mjs';
|
|
10
|
+
import { defaultLoadCreatorRootModule, resolveEffectiveProjectRoot } from './first-run.mjs';
|
|
11
11
|
import { maybeShowAssetIntroNotice } from './sounds-setup.mjs';
|
|
12
12
|
import {
|
|
13
13
|
checkForUpdateSync,
|
|
@@ -82,6 +82,14 @@ export async function run(args, options = {}) {
|
|
|
82
82
|
projectRoot = await resolveEffectiveProjectRoot({ projectRoot, env, platform, now, log, assets, autoConfirm, options });
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
try {
|
|
86
|
+
const creatorRoot = await defaultLoadCreatorRootModule(assets);
|
|
87
|
+
const migration = await creatorRoot?.migrateAssetLibrary({ env, platform, automatic: true, notify: log });
|
|
88
|
+
for (const failure of migration?.failures ?? []) log(`素材の移行を再試行します: ${failure.message}`);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
log(`素材の移行を再試行します: ${error.message}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
85
93
|
let state = detectProjectState(projectRoot);
|
|
86
94
|
|
|
87
95
|
if (!state.scaffolded) {
|
package/src/kits.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { pathToFileURL } from 'node:url';
|
|
1
2
|
import { spawnSync } from 'node:child_process';
|
|
2
3
|
import { createHash } from 'node:crypto';
|
|
3
4
|
import {
|
|
@@ -7,6 +8,12 @@ import {
|
|
|
7
8
|
import path from 'node:path';
|
|
8
9
|
|
|
9
10
|
import { resolveLauncherAssets } from './repo-assets.mjs';
|
|
11
|
+
const creatorRootModulePath = resolveLauncherAssets().creatorRootModulePath;
|
|
12
|
+
const creatorRoot = creatorRootModulePath ? await import(pathToFileURL(creatorRootModulePath).href) : null;
|
|
13
|
+
function resolveAssetLibraryRoots(env) {
|
|
14
|
+
if (!creatorRoot) throw new Error('creator-root が見つからないため素材の置き場を解決できません。AKARI Video を再インストールしてください。');
|
|
15
|
+
return creatorRoot.resolveAssetLibraryRoots(env);
|
|
16
|
+
}
|
|
10
17
|
|
|
11
18
|
const KITS_SCHEMA = 'akari-installed-kits/v0';
|
|
12
19
|
const INSTALLED_ASSETS_SCHEMA = 'akari-installed-assets/v0';
|
|
@@ -152,16 +159,8 @@ export function linkKitAssets(kitDir, manifest, home, options = {}) {
|
|
|
152
159
|
} else {
|
|
153
160
|
warnings.push(`素材 ${asset.category}/${asset.id} の検査ツールが見つからないため検査をスキップしました。`);
|
|
154
161
|
}
|
|
155
|
-
const destination = path.join(
|
|
156
|
-
const
|
|
157
|
-
const kitSubdir = path.relative(productRoot, kitDir);
|
|
158
|
-
const result = replaceSymlink(source, destination, {
|
|
159
|
-
...options,
|
|
160
|
-
relativeTarget: path.join(
|
|
161
|
-
'..', '..', 'assets', 'store', manifest.id, kitSubdir,
|
|
162
|
-
'assets', asset.category, asset.id
|
|
163
|
-
)
|
|
164
|
-
});
|
|
162
|
+
const destination = path.join(resolveAssetLibraryRoots({ ...(options.env ?? process.env), AKARI_HOME: home }).write, asset.category, asset.id);
|
|
163
|
+
const result = replaceSymlink(source, destination, options);
|
|
165
164
|
if (result.status === 'occupied') {
|
|
166
165
|
warnings.push(`既存の実ディレクトリを保持しました: ${destination}`);
|
|
167
166
|
} else if (result.status === 'permission-denied') {
|
|
@@ -174,8 +173,8 @@ export function linkKitAssets(kitDir, manifest, home, options = {}) {
|
|
|
174
173
|
return { linked, items, warnings };
|
|
175
174
|
}
|
|
176
175
|
|
|
177
|
-
function readInstalledAssetsIndex(home) {
|
|
178
|
-
const indexPath = path.join(
|
|
176
|
+
function readInstalledAssetsIndex(home, env = process.env) {
|
|
177
|
+
const indexPath = path.join(resolveAssetLibraryRoots({ ...env, AKARI_HOME: home }).write, 'installed.json');
|
|
179
178
|
if (!existsSync(indexPath)) return { schema: INSTALLED_ASSETS_SCHEMA, packs: {} };
|
|
180
179
|
const index = JSON.parse(readFileSync(indexPath, 'utf8'));
|
|
181
180
|
if (index?.schema !== INSTALLED_ASSETS_SCHEMA
|
|
@@ -185,38 +184,38 @@ function readInstalledAssetsIndex(home) {
|
|
|
185
184
|
return index;
|
|
186
185
|
}
|
|
187
186
|
|
|
188
|
-
function writeInstalledAssetsIndex(home, index) {
|
|
189
|
-
const indexPath = path.join(
|
|
187
|
+
function writeInstalledAssetsIndex(home, index, env = process.env) {
|
|
188
|
+
const indexPath = path.join(resolveAssetLibraryRoots({ ...env, AKARI_HOME: home }).write, 'installed.json');
|
|
190
189
|
mkdirSync(path.dirname(indexPath), { recursive: true });
|
|
191
190
|
const temporary = `${indexPath}.tmp-${process.pid}`;
|
|
192
191
|
writeFileSync(temporary, `${JSON.stringify(index, null, 2)}\n`, { mode: 0o600 });
|
|
193
192
|
renameSync(temporary, indexPath);
|
|
194
193
|
}
|
|
195
194
|
|
|
196
|
-
export function registerKitAssets(home, manifest, kitDir, items) {
|
|
195
|
+
export function registerKitAssets(home, manifest, kitDir, items, env = process.env) {
|
|
197
196
|
const root = path.resolve(kitDir);
|
|
198
|
-
const storeRoot = path.join(
|
|
197
|
+
const storeRoot = path.join(resolveAssetLibraryRoots({ ...env, AKARI_HOME: home }).write, 'store', manifest.id);
|
|
199
198
|
if (root !== storeRoot && !root.startsWith(`${storeRoot}${path.sep}`)) {
|
|
200
199
|
throw new Error(`キット素材の root が展開先の外を指しています: ${root}`);
|
|
201
200
|
}
|
|
202
|
-
const index = readInstalledAssetsIndex(home);
|
|
201
|
+
const index = readInstalledAssetsIndex(home, env);
|
|
203
202
|
index.packs[manifest.id] = {
|
|
204
203
|
version: manifest.version,
|
|
205
204
|
installedAt: new Date().toISOString(),
|
|
206
205
|
root,
|
|
207
206
|
items
|
|
208
207
|
};
|
|
209
|
-
writeInstalledAssetsIndex(home, index);
|
|
208
|
+
writeInstalledAssetsIndex(home, index, env);
|
|
210
209
|
return items;
|
|
211
210
|
}
|
|
212
211
|
|
|
213
|
-
function unregisterKitAssets(home, productId) {
|
|
214
|
-
const indexPath = path.join(
|
|
212
|
+
function unregisterKitAssets(home, productId, env = process.env) {
|
|
213
|
+
const indexPath = path.join(resolveAssetLibraryRoots({ ...env, AKARI_HOME: home }).write, 'installed.json');
|
|
215
214
|
if (!existsSync(indexPath)) return;
|
|
216
|
-
const index = readInstalledAssetsIndex(home);
|
|
215
|
+
const index = readInstalledAssetsIndex(home, env);
|
|
217
216
|
if (!Object.hasOwn(index.packs, productId)) return;
|
|
218
217
|
delete index.packs[productId];
|
|
219
|
-
writeInstalledAssetsIndex(home, index);
|
|
218
|
+
writeInstalledAssetsIndex(home, index, env);
|
|
220
219
|
}
|
|
221
220
|
|
|
222
221
|
export function linkKitSkills(kitDir, manifest, home, options = {}) {
|
|
@@ -276,20 +275,20 @@ export function writeKitsLedger(home, entry) {
|
|
|
276
275
|
return ledger;
|
|
277
276
|
}
|
|
278
277
|
|
|
279
|
-
export function removeKit(home, productId) {
|
|
278
|
+
export function removeKit(home, productId, env = process.env) {
|
|
280
279
|
const ledger = readKitsLedger(home);
|
|
281
280
|
const entry = ledger.kits.find((kit) => kit.id === productId);
|
|
282
281
|
if (!entry) return false;
|
|
283
282
|
for (const name of entry.skills ?? []) removeOwnedSymlink(path.join(home, 'kits', 'plugin', 'skills', name), entry.kitDir);
|
|
284
283
|
for (const asset of entry.assets ?? []) {
|
|
285
|
-
removeOwnedSymlink(path.join(
|
|
284
|
+
for (const root of resolveAssetLibraryRoots({ ...env, AKARI_HOME: home }).read) removeOwnedSymlink(path.join(root, asset.category, asset.id), entry.kitDir);
|
|
286
285
|
}
|
|
287
286
|
ledger.kits = ledger.kits.filter((kit) => kit.id !== productId);
|
|
288
287
|
const ledgerPath = path.join(home, 'kits', 'installed.json');
|
|
289
288
|
const temporary = `${ledgerPath}.tmp-${process.pid}`;
|
|
290
289
|
writeFileSync(temporary, `${JSON.stringify(ledger, null, 2)}\n`, { mode: 0o600 });
|
|
291
290
|
renameSync(temporary, ledgerPath);
|
|
292
|
-
unregisterKitAssets(home, productId);
|
|
291
|
+
unregisterKitAssets(home, productId, env);
|
|
293
292
|
return true;
|
|
294
293
|
}
|
|
295
294
|
|
package/src/store-command.mjs
CHANGED
|
@@ -20,6 +20,12 @@ import {
|
|
|
20
20
|
} from './store-device-connect.mjs';
|
|
21
21
|
import { readOwnVersion } from './update-check.mjs';
|
|
22
22
|
import { resolveLauncherAssets } from './repo-assets.mjs';
|
|
23
|
+
const creatorRootModulePath = resolveLauncherAssets().creatorRootModulePath;
|
|
24
|
+
const creatorRoot = creatorRootModulePath ? await import(pathToFileURL(creatorRootModulePath).href) : null;
|
|
25
|
+
function resolveAssetLibraryRoots(env) {
|
|
26
|
+
if (!creatorRoot) throw new Error('creator-root が見つからないため素材の置き場を解決できません。AKARI Video を再インストールしてください。');
|
|
27
|
+
return creatorRoot.resolveAssetLibraryRoots(env);
|
|
28
|
+
}
|
|
23
29
|
import {
|
|
24
30
|
checkRequires,
|
|
25
31
|
enableHint,
|
|
@@ -154,8 +160,7 @@ function flattenPackContents(pack, packRoot) {
|
|
|
154
160
|
}
|
|
155
161
|
|
|
156
162
|
function registerInstalledPack(env, productId, packPath) {
|
|
157
|
-
const
|
|
158
|
-
const indexPath = path.join(home, 'assets', 'installed.json');
|
|
163
|
+
const indexPath = path.join(resolveAssetLibraryRoots(env).write, 'installed.json');
|
|
159
164
|
const packRoot = path.dirname(packPath);
|
|
160
165
|
const pack = readJsonFile(packPath);
|
|
161
166
|
if ((typeof pack?.version !== 'string' && typeof pack?.version !== 'number')) {
|
|
@@ -319,7 +324,7 @@ export async function runStoreCommand(args, options = {}) {
|
|
|
319
324
|
log('使い方: akari store uninstall <productId>');
|
|
320
325
|
return { exitCode: 1 };
|
|
321
326
|
}
|
|
322
|
-
if (!removeKit(resolveAkariHome(env), productId)) {
|
|
327
|
+
if (!removeKit(resolveAkariHome(env), productId, env)) {
|
|
323
328
|
log(`導入済みの拡張キットが見つかりません: ${productId}`);
|
|
324
329
|
return { exitCode: 1 };
|
|
325
330
|
}
|
|
@@ -430,7 +435,7 @@ export async function runStoreCommand(args, options = {}) {
|
|
|
430
435
|
log('パック内に declarations.json が見つかりませんでした。zip の中身を確認してください。');
|
|
431
436
|
return { exitCode: 1 };
|
|
432
437
|
}
|
|
433
|
-
const destDir = path.join(
|
|
438
|
+
const destDir = path.join(resolveAssetLibraryRoots(env).write, 'audio');
|
|
434
439
|
mkdirSync(destDir, { recursive: true });
|
|
435
440
|
const dest = path.join(destDir, 'declarations.json');
|
|
436
441
|
if (existsSync(dest)) {
|
|
@@ -445,7 +450,7 @@ export async function runStoreCommand(args, options = {}) {
|
|
|
445
450
|
}
|
|
446
451
|
|
|
447
452
|
// 既知の導入手順が無い商品は素材置き場に展開して README を案内
|
|
448
|
-
const destDir = path.join(
|
|
453
|
+
const destDir = path.join(resolveAssetLibraryRoots(env).write, 'store', productId);
|
|
449
454
|
rmSync(destDir, { recursive: true, force: true });
|
|
450
455
|
cpSync(extractDir, destDir, { recursive: true });
|
|
451
456
|
const readme = findFile(destDir, 'README.md');
|
|
@@ -531,6 +536,7 @@ export async function runStoreCommand(args, options = {}) {
|
|
|
531
536
|
|
|
532
537
|
const hadInstalledKit = readKitsLedger(home).kits.length > 0;
|
|
533
538
|
const assetLinks = linkKitAssets(kitDir, manifest, home, {
|
|
539
|
+
env,
|
|
534
540
|
assets: options.assets,
|
|
535
541
|
spawnSyncImpl: options.spawnSync,
|
|
536
542
|
platform: options.platform
|
|
@@ -541,7 +547,7 @@ export async function runStoreCommand(args, options = {}) {
|
|
|
541
547
|
for (const blocker of skillLinks.blockers) log(`導入できません: ${blocker}`);
|
|
542
548
|
return { exitCode: 1 };
|
|
543
549
|
}
|
|
544
|
-
registerKitAssets(home, manifest, kitDir, assetLinks.items);
|
|
550
|
+
registerKitAssets(home, manifest, kitDir, assetLinks.items, env);
|
|
545
551
|
writeKitsLedger(home, {
|
|
546
552
|
id: manifest.id,
|
|
547
553
|
version: manifest.version,
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# 素材ライブラリ契約 v0
|
|
2
2
|
|
|
3
|
+
ライブラリの置き場は既定で作業場の `library/`。作業場が無いときは従来の `~/.akari/assets/` を使う。
|
|
4
|
+
`akari-assets list`(または `akari assets list`)の先頭行で実際の置き場を確認する。
|
|
5
|
+
以下の `<ライブラリの置き場>` はその表示先を指し、音源はその下の `audio/` に入る。
|
|
6
|
+
|
|
3
7
|
- 日付: 2026-07-13
|
|
4
8
|
- 状態: 設計確定
|
|
5
9
|
- 前提: 本体(エンジン)は合成だけ。素材とその知識は全部外側に置く
|
|
@@ -215,7 +219,7 @@ catalog に載せる素材は、取得元のライセンスが CC0 相当(帰
|
|
|
215
219
|
|---|---|---|
|
|
216
220
|
| `local` | `<プロジェクト>/assets/` | そのプロジェクトのみ |
|
|
217
221
|
| `shared` | プロジェクトから上位へ辿った各ディレクトリの `.akari/assets/`(2026-07-25 第三裁定で確定) | そのディレクトリ配下の全プロジェクト(事業・組織単位。複数層可) |
|
|
218
|
-
| `user` |
|
|
222
|
+
| `user` | `<ライブラリの置き場>/`(2026-07-25 第三裁定で確定) | そのマシンの全プロジェクト |
|
|
219
223
|
| `builtin` | 本リポの `assets/` | 製品出荷デフォルト |
|
|
220
224
|
| `catalog` | 本リポの `catalog/`(remote) | 取得して任意の層へ入庫 |
|
|
221
225
|
|
|
@@ -241,7 +245,7 @@ catalog に載せる素材は、取得元のライセンスが CC0 相当(帰
|
|
|
241
245
|
~~**確定裁定(2026-07-25 再裁定): プロジェクト外の置き場所は `~/.akari-video/` をベースに
|
|
242
246
|
統一する。** 初期案保留(旧「`.akari-video/` は初期案」項)はこれで解消。~~
|
|
243
247
|
|
|
244
|
-
|
|
248
|
+
**履歴(2026-07-25 第三裁定): 当時の user 素材は `~/.akari/` 直下だった。2026-09-21 から素材は作業場 `library/` に移行し、マシン状態のみ `~/.akari/` に残す。**
|
|
245
249
|
`~/.akari/` 直下には他ソフトウェアの既存物が併存する場合があるため、共存規約
|
|
246
250
|
(本節末尾を参照)を必ず守る。
|
|
247
251
|
|
|
@@ -250,7 +254,7 @@ catalog に載せる素材は、取得元のライセンスが CC0 相当(帰
|
|
|
250
254
|
|
|
251
255
|
確定事項(2026-07-25 第三裁定で更新。カッコ内は第二裁定時点の値):
|
|
252
256
|
|
|
253
|
-
- `user` 層:
|
|
257
|
+
- `user` 層: `<ライブラリの置き場>/`(第二裁定時点: `~/.akari-video/assets/`)
|
|
254
258
|
- `shared` 層: 上位ディレクトリの `.akari/assets/`(第二裁定時点: `.akari-video/assets/`)
|
|
255
259
|
- レシピ: `~/.akari/recipes/`(recipe v0 の現行表記のまま・変更不要。出所は
|
|
256
260
|
`docs/contract-2026-07-25-recipe-v0.md` §2 に追記)
|
|
@@ -380,7 +384,7 @@ catalog に載せる素材は、取得元のライセンスが CC0 相当(帰
|
|
|
380
384
|
- **カテゴリを増やさない**のが本改訂の要点である。新しい主題(ホワイトボード、ノート風、付箋…)は
|
|
381
385
|
既存カテゴリ + tags で表す。カテゴリ追加を提案するときは「既存 6 つのどの形にも当てはまらない
|
|
382
386
|
配布・消費のされ方か」を先に示す
|
|
383
|
-
- `audio` を `media`
|
|
387
|
+
- `audio` を `media` に畳む案は見送った。`<ライブラリの置き場>/audio/`(user 層)に実データがあり、
|
|
384
388
|
リポ外のユーザー資産の移設を伴うため。`audio` と `broll` は消費経路(音声トラック / 映像トラック)が
|
|
385
389
|
異なるので、形の軸としても分けたままで筋が通る
|
|
386
390
|
- 移行時の実績: `assets/` 3 件・`catalog/` 3 件のディレクトリ移動と `category` 値の書き換え、
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# creator-root-v1(作業場)契約
|
|
2
2
|
|
|
3
|
+
ライブラリの置き場は既定で作業場の `library/`。作業場が無いときは従来の `~/.akari/assets/` を使う。
|
|
4
|
+
`akari-assets list`(または `akari assets list`)の先頭行で実際の置き場を確認する。
|
|
5
|
+
以下の `<ライブラリの置き場>` はその表示先を指し、音源はその下の `audio/` に入る。
|
|
6
|
+
|
|
3
7
|
- 日付: 2026-08-02
|
|
4
8
|
- 状態: **v1 ドラフト・要オーナーレビュー**(設計方針はオーナー承認済み 2026-08-02。
|
|
5
9
|
判断根拠・出典調査は非公開の内部記録で管理する)
|
|
@@ -41,8 +45,8 @@ AKARI Video がマシン上に持ってよい場所は次の 3 つ**だけ**で
|
|
|
41
45
|
- マシン状態の実パスは**既存実装の規約を追認**する(`~/.akari/` = 更新キャッシュ・接続マーカー・
|
|
42
46
|
可搬 Node runtime 等 / 資格情報は `~/.config/akari-video/credentials.env`)。新たな隠し場所を増やさない
|
|
43
47
|
- 原則: マシン状態には**ユーザーの内容物(作品・素材・記憶)を置かない**。
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
旧音源ライブラリの例外は 2026-09-21 の移行で回収した。素材は作業場 `library/` へ移し、
|
|
49
|
+
マシン設定の `library-location.json` に置き場を固定する(作業場なし・同期フォルダは移さない)。
|
|
46
50
|
|
|
47
51
|
- **secrets(API キー・トークン類)はマシン設定にのみ置く**。作業場は可視・バックアップ・
|
|
48
52
|
同期対象なので、secrets を混ぜてはならない
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# contract — 素材の参照モデル v0(共有ライブラリ参照の台帳と解決規則)
|
|
2
2
|
|
|
3
|
+
ライブラリの置き場は既定で作業場の `library/`。作業場が無いときは従来の `~/.akari/assets/` を使う。
|
|
4
|
+
`akari-assets list`(または `akari assets list`)の先頭行で実際の置き場を確認する。
|
|
5
|
+
以下の `<ライブラリの置き場>` はその表示先を指し、音源はその下の `audio/` に入る。
|
|
6
|
+
|
|
3
7
|
- 状態: 実装済み(機械層のみ。シェル UI の採用は後続)
|
|
4
8
|
- 決定日: 2026-09-02
|
|
5
9
|
- 実装: `packages/asset-resolver`(記帳・実体化)/ `packages/render-cut`・`packages/edit-lint`(解決)
|
|
@@ -7,7 +11,7 @@
|
|
|
7
11
|
## 1. 目的
|
|
8
12
|
|
|
9
13
|
カタログ素材をプロジェクトごとに実体コピーすると、同じ素材が何度もダウンロード・複製されて
|
|
10
|
-
|
|
14
|
+
プロジェクトが肥大する。実体は**マシン単位の共有ライブラリ**(`<ライブラリの置き場>/<category>/<id>/`)に
|
|
11
15
|
1 部だけ置き、プロジェクトには**参照だけを記録**できるようにする。
|
|
12
16
|
|
|
13
17
|
## 2. 設計の要点
|
|
@@ -25,11 +29,11 @@
|
|
|
25
29
|
edit.json の version とは無関係。
|
|
26
30
|
- **解決規則**: 宣言されたプロジェクト相対パスが `assets/<category>/<id>/<rest>` の形で、
|
|
27
31
|
(1) プロジェクト実体が存在せず、(2) 台帳に `{category, id}` があるとき、
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
`resolveAssetLibraryRoots().read` の順(新しい置き場 → 従来の置き場)にフォールバックする。
|
|
33
|
+
解決先は各ルートで字句・realpath containment を満たす正規ファイルで
|
|
30
34
|
あること(`..` 等の脱出は fail-closed で拒否)。
|
|
31
35
|
- render-cut は解決した入力を render inputs 記録に `scope: "library"` として残す
|
|
32
|
-
(既存 `scope: "akari"` と同列の additive
|
|
36
|
+
(既存 `scope: "akari"` と同列の additive 記録)。採用した実ルートを `library_root` に保存して後段でも検査する。edit-lint は解決できる参照を欠落と報告せず、
|
|
33
37
|
台帳にあるが実体が無い参照は「共有ライブラリ参照(未取得)」として欠落報告する。
|
|
34
38
|
- render-cut / edit-lint は依存ゼロ CLI のため、解決ロジックは各パッケージ内に**同一実装を重複**して
|
|
35
39
|
持つ(`src/library-reference.mjs`)。挙動同一性は両テストの同一ケース表で担保する。
|
|
@@ -47,7 +51,53 @@ akari-assets bundle --project <dir> [--dry-run]
|
|
|
47
51
|
bundle は台帳の各参照をキャッシュから `assets/<category>/<id>/` へ実体化して台帳から除去する。
|
|
48
52
|
未取得の参照は resolve(取得)を試み、取得できないものは台帳に残して部分成功(exit 非 0)で報告する。冪等。
|
|
49
53
|
|
|
50
|
-
## 4.
|
|
54
|
+
## 4. 書き出しエンジンの配信
|
|
55
|
+
|
|
56
|
+
OSR / GPU の共通配信サーバーは、render-cut が解決した入力のうち `scope: "library"` の
|
|
57
|
+
全件を許可表として受け取る。映像だけでなく、音・静止画・オーバーレイ内の素材も対象。
|
|
58
|
+
キーは宣言パス `assets/<category>/<id>/<rest>`(区切りは `/`)、値は
|
|
59
|
+
`{ absolute: <実体の絶対パス>, library_root: <採用ルート> }`。
|
|
60
|
+
配信側は置き場の探索や台帳からの再解決を行わない。
|
|
61
|
+
|
|
62
|
+
ffmpeg の計画には、同じ render inputs の解決結果で素材パス欄だけを絶対パスへ置き換えた
|
|
63
|
+
edit の写しを渡す。BGM・SFX・ナレーション・分離音声・レイヤー音声の入力と尺の probe が対象。
|
|
64
|
+
映像ソースの cut 音声は既存の解決済み capabilities を使い、contact sheet は書き出した動画を読む。
|
|
65
|
+
元の edit.json、配信用の宣言パス、receipt の入力パスは書き換えない。
|
|
66
|
+
|
|
67
|
+
別プロセスへの受け渡しには
|
|
68
|
+
`<projectRoot>/.akari/render-tmp/media-references-<render-cut の PID>.json` を使う。
|
|
69
|
+
表の形式は `{ "token": "<合言葉>", "references": { "<宣言パス>": { "absolute": "<実体の絶対パス>", "library_root": "<採用ルート>" } } }`。
|
|
70
|
+
render-cut は実行ごとに `crypto.randomBytes(32)` の合言葉を hex 文字列として生成し、
|
|
71
|
+
同じ値を環境変数 `AKARI_RENDER_MEDIA_REFERENCES_TOKEN` に設定してから書き出しを起動する。
|
|
72
|
+
この変数は Electron 子プロセスへ継承される。終了時は `finally` で元の値へ戻し、元が未定義なら削除する。
|
|
73
|
+
合言葉はログ・エラー文・render.json に出さない。
|
|
74
|
+
render-cut は子プロセスの起動前に排他的に作成し、OSR / GPU(GPU から OSR への再試行を含む)の
|
|
75
|
+
終了時に `finally` で成功・失敗とも削除する。Electron は親 PID からパスを決め、サーバー生成時に
|
|
76
|
+
一度だけ読む。別 CLI の並行実行は表を共有しない。プロセス内の使用中パス集合で
|
|
77
|
+
同じプロジェクトの重複実行(ネスト呼び出しを含む)を拒否する。集合に無い自 PID の既存表は、
|
|
78
|
+
クラッシュや PID 再利用による残存表として削除してから排他的に作り直す。
|
|
79
|
+
使用中の記録は作成・書き出し・後片付けの失敗時にも解除する。他 PID の表は回収しない。
|
|
80
|
+
ファイル経由の表は、環境変数が無い・空、表の token が文字列でない、UTF-8 バイト長が異なる、
|
|
81
|
+
または `crypto.timingSafeEqual` で一致しない場合は一切使わない。token の無い旧形式や壊れた JSON も空の表として扱う。
|
|
82
|
+
これにより単体 CLI など render-cut を通らない起動では、プロジェクトに植え込まれた表から外部ファイルを配信しない。
|
|
83
|
+
配信 API の明示引数 `mediaReferences` がある場合は従来どおりそちらを優先し、
|
|
84
|
+
表が無い場合や認証できない場合はプロジェクト内だけを配信する。
|
|
85
|
+
|
|
86
|
+
`/media/<宣言パス>` は次の順で検査する。
|
|
87
|
+
|
|
88
|
+
1. デコード後に `..` セグメント(`/` と `\` の両区切り)を含む要求は 403。
|
|
89
|
+
2. プロジェクト内の実体があれば優先する。字句・realpath の両方でプロジェクト内に収まることを
|
|
90
|
+
検査し、symlink による脱出は 403、正規ファイルでなければ 404。
|
|
91
|
+
3. プロジェクトに実体が無い場合のみ、許可表の完全一致キーを調べる。表に無いファイルは
|
|
92
|
+
ライブラリ配下に存在しても 404。
|
|
93
|
+
4. 表の実体が採用ルート内にあることを字句で確認し、さらに実体と採用ルートを毎回 realpath で
|
|
94
|
+
解決して包含を再検査する。脱出は 403、欠落・非正規ファイルは 404。
|
|
95
|
+
5. 許可した実体は既存のファイル配信を使い、通常取得は 200、Range 取得は 206 とする。
|
|
96
|
+
|
|
97
|
+
台帳にあっても置き場に無い必須素材は、従来の render inputs / 計画段階のエラーで停止する。
|
|
98
|
+
配信ページの 404 を待ってから失敗させない。
|
|
99
|
+
|
|
100
|
+
## 5. スコープ外(後続)
|
|
51
101
|
|
|
52
102
|
- シェル UI の採用(取り込みフローの reference 既定化・プロジェクト面の「参照」バッジ・
|
|
53
103
|
プレビュー経路のフォールバック)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# 生成 v0 契約 — 仮枠クリップ・9 スロット・meta.json・能力カタログ・状態
|
|
2
2
|
|
|
3
|
-
> 正本の写し(2026-09-13
|
|
3
|
+
> 正本の写し(2026-09-13・2026-09-21 改訂)・技術部分のみ。内部正本の §1〜§9 と §11 を公開向けに収録する。
|
|
4
|
+
> 節番号の対応: 本書 §1〜§9 = 内部正本 §1〜§9、本書 §10(コマ保存)= 内部正本 §11。
|
|
4
5
|
|
|
5
6
|
## 1. 継ぎ目(仮枠とタイムライン)
|
|
6
7
|
|
|
@@ -10,6 +11,9 @@
|
|
|
10
11
|
4. 「動画にする」は同じ item の `source.path` を mp4 に書き換える**差し替え**であり、item id・トラック・尺は変わらない(§7)
|
|
11
12
|
5. 絵コンテはタイムラインの印刷(9/6 §5)。生成の入力にしない
|
|
12
13
|
6. plan.json の仮枠役(`confidence` / `fill`)は退役。`plan-comments.json` の `pass: "scaffold"` の対象は `slot` から **clip id** へ
|
|
14
|
+
7. **空の枠**(2026-09-21): 仮枠ツール(F)で空いているところに描いた枠は、prompt 未記入の**文字カード png** を素材に持つ media item(絵のないクリップを文字カード png で表す規則の延長)。0.5 秒刻み・端に吸着・隣に食い込まない・0.5 秒未満にしない。専用トラックは作らない(どのトラックにも置ける)
|
|
15
|
+
8. **すき間から作る枠**(2026-09-21): すき間をクリック →「あいだを生成」で、すき間の位置と長さの枠を置く。前のクリップの最後のコマ・次のクリップの最初のコマを抽出して両端(②③)に入れる。動画からの抽出は 1 コマを `assets/captures/` へ書き出す(§10)
|
|
16
|
+
9. 枠は**生成前から尺と場所を持ち、生成物は同じ item に入る**(4 の延長)。メディアパネルは経由しない(タイムライン正本)
|
|
13
17
|
|
|
14
18
|
## 2. 9 スロット(生成入力の正規形)
|
|
15
19
|
|
|
@@ -66,9 +70,38 @@
|
|
|
66
70
|
2. `status: generating` かつ `started_at` から `stale_after_s` 超 = **stale**。シェルは「応答なし・再取得」を出す。既定 900 秒
|
|
67
71
|
3. 状態の遷移は undo に入れない。**差し替え(§7)だけ** edit-store の undo に 1 手として入る
|
|
68
72
|
4. `history[]` は消さない。失敗も残す
|
|
69
|
-
5. `kind: "still"` は `inputs.reference_images` に `--image=` の 1 枚(Codex)か複数枚(Nano Banana Pro)。`kind: "frames"`
|
|
73
|
+
5. `kind: "still"` は `inputs.reference_images` に `--image=` の 1 枚(Codex)か複数枚(Nano Banana Pro)。`kind: "frames"` はパラパラ(別契約)
|
|
70
74
|
6. `result.expanded_prompt` は provider が書き換えた prompt。較正では **送った prompt ではなく expanded を評価対象**に添える
|
|
71
75
|
|
|
76
|
+
### 3-2. 動画予定の下書き `next`(2026-09-21)
|
|
77
|
+
|
|
78
|
+
mp4 がまだ無い「動画予定」は、**仮枠の素材の meta**(静止画なら `<still>.meta.json`、空の枠なら文字カードの meta)の中に `next` ブロックで持つ。
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"version": 1, "kind": "still", "status": "done", // 静止画自身の記録はそのまま
|
|
83
|
+
"…": "…",
|
|
84
|
+
"next": {
|
|
85
|
+
"kind": "video", "status": "planned",
|
|
86
|
+
"model": { "id": "fal:h3-i2v" },
|
|
87
|
+
"inputs": { "prompt": "…", "first_frame": { "path": "…", "sha256": "…" }, "last_frame": null,
|
|
88
|
+
"reference_images": [], "reference_videos": [], "reference_audios": [],
|
|
89
|
+
"camera": null, "seed": null, "extra": {}, "frames_or_refs": "frames" },
|
|
90
|
+
"output": { "duration_s": 5, "resolution": "768P", "aspect": null, "audio_out": null },
|
|
91
|
+
"updated_at": "…"
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
1. **読み手の判定**: `next.kind === "video"` かつ `next.status === "planned"` = 「動画予定」。`next` が無い静止画 = 「画像のまま」= 完成品。文字カード(meta 自体が `planned`)で `next` が無いか prompt が空 = 「空の枠」
|
|
97
|
+
2. `next.inputs` は §2 の 9 スロットの下書き。`first_frame` は**そのクリップの絵とは限らない**(前のクリップの最後のコマ・キャプチャ・空 = プロンプトだけ)
|
|
98
|
+
3. **`inputs.frames_or_refs`** = `"frames"` / `"references"`(`next` の下書きだけが持つ欄。§2 ⑦ の `mode` = 元動画のモードとは別物)。最初 / 最後と参照が排他のとき(`frames_and_refs_exclusive: true` の行、または同じ family の i2v 行と ref 行の切替)、**下書きは両側を保持し、送るのは `frames_or_refs` の側だけ**。切り替えで中身を消さない。バリデータはこの欄を見て反対側を送信 body から外し、生成物 meta の `inputs` にはこの欄を書かない(送った側だけが残る)
|
|
99
|
+
4. **送るとき**: CLI は `next`(または `--inputs`)を読み、従来どおり**生成物の隣**に video meta(`generating`)を書く。このとき **`placeholder: { path, sha256, item_id }`** = その item が今指している素材(静止画 / 文字カード)を必ず書く。item への逆引きは `placeholder` が正、`inputs.first_frame.path` は 9/13 時点の meta のための後方互換。`next` は消さない(「同じ入力でもう一度」の元)
|
|
100
|
+
5. **状態の優先**: `placeholder` で結線された生成物 meta が `generating` / stale / `failed` ならそれを描く。無ければ `next` の `planned` を描く。`done` で差し替わった後は mp4 の meta が直接当たる(§7)
|
|
101
|
+
6. `next` の更新は undo に入れない(§3 規則 3 と同じ)。右パネルの編集は即保存
|
|
102
|
+
7. 移行: `.akari/generation/<itemId>.inputs.json` があり `next` が無いときだけ読み、次の保存で `next` へ移す。新規の書き込みはしない
|
|
103
|
+
8. ビート表(`akari generate still --spec`)はビートごとに動画予定(最初だけ / 最初→最後)を指定でき、指定があれば CLI が `next` を書く。指定が無ければ「画像のまま」
|
|
104
|
+
|
|
72
105
|
## 4. 能力カタログ `gen-models.json`(公開リポ `packages/schemas/`)
|
|
73
106
|
|
|
74
107
|
### 4-1. 形(1 行 = 1 エンドポイント)
|
|
@@ -146,21 +179,26 @@ Kling v3 standard i2v / Kling v3 pro i2v / Veo 3.1 first-last / Veo 3.1 referenc
|
|
|
146
179
|
|
|
147
180
|
| 状態 | タイムライン | プレビュー(編集中) | 書き出し |
|
|
148
181
|
|---|---|---|---|
|
|
149
|
-
| `
|
|
150
|
-
|
|
|
151
|
-
|
|
|
182
|
+
| 空の枠(文字カード・`next` なし or prompt 空) | 点線 + 「planned」 | 文字カード + 左上小札 | 文字カードのまま。lint WARN |
|
|
183
|
+
| **動画予定**(`next` = video · planned。§3-2) | **紫の点線 + 上下のフィルムの穴 + 「▶ 動画予定」**。中身は 最初の絵 1 枚 ・ 生成で埋める空き ・ 最後の絵 1 枚(同じ絵を並べない)。プロンプトだけは文字。最後の絵 = 次のクリップの絵なら境目に 🔗 | 左上小札「▶ 動画予定 · <種類>」+ 最後の絵があれば右下の小窓 | 静止画 / 文字カードのまま。小札・小窓 0 px |
|
|
184
|
+
| 静止画 = 画像のまま(`next` なし) | 「静止画」バッジ | 静止画。**小札なし**(完成品) | そのまま |
|
|
185
|
+
| `generating` | 黄の縞 + 進捗バー | **参照の絵をぼかした背景** + シマー + 下端の帯。進捗は擬似でなく provider の状態 | 静止画のまま |
|
|
152
186
|
| stale | 縞 + 「応答なし・再取得」 | 帯に「応答なし」 | 静止画のまま |
|
|
153
187
|
| `done`(動画) | 通常 + コマ帯 + 「生成」由来バッジ | 動画。表示なし | 通常 |
|
|
154
|
-
| `failed` | 朱枠 +
|
|
188
|
+
| `failed` | 朱枠 + 「失敗」+ **「同じ入力でもう一度」** | 静止画 + 朱の小札 | 静止画のまま |
|
|
155
189
|
|
|
156
|
-
-
|
|
190
|
+
- プレビューに付くのは**左上の小札・下端の帯・動画予定の右下の小窓・コマ保存のカメラボタン(§10)だけ**。承認・比較の UI はプレビューに置かない
|
|
191
|
+
- 種類の表示は「プロンプトだけ / 画像から / 最初→最後 / 参照から」。枠を埋めたかで決まり、モード選択の UI は作らない
|
|
192
|
+
- 失敗の「同じ入力でもう一度」はクリップと右パネルの両方に出す
|
|
157
193
|
- **書き出し経路には小札・帯・点線が 0 px**。画素比較で担保(w3-b)
|
|
158
194
|
|
|
159
195
|
## 7. 差し替え規則(done になったとき)
|
|
160
196
|
|
|
161
197
|
### 7-1. 何を書き換えるか
|
|
162
198
|
|
|
163
|
-
同じ item の `sources[].path` を mp4 に。item id・トラック・`at` は不変。静止画の path は `
|
|
199
|
+
同じ item の `sources[].path` を mp4 に。item id・トラック・`at` は不変。静止画の path は生成物 meta の `placeholder`(§3-2)に残る(由来。9/13 時点の meta は `inputs.first_frame`)。**1 手の undo**。
|
|
200
|
+
|
|
201
|
+
**クリップ側の設定は保持する**(2026-09-21)。変形(拡大率・位置・不透明度・反転)と色(LUT・明るさ等)は item の上に重ねる設定であり、差し替えで入れ替わるのは**素材だけ**。逆に、**生成に送る絵は素材のまま**で、クリップの LUT・サイズは送らない(キャプチャを枠に入れた場合は §10-2)。
|
|
164
202
|
|
|
165
203
|
### 7-2. 実尺のずれ
|
|
166
204
|
|
|
@@ -178,7 +216,7 @@ Kling v3 standard i2v / Kling v3 pro i2v / Veo 3.1 first-last / Veo 3.1 referenc
|
|
|
178
216
|
## 8. 費用承認(有償生成のゲート)
|
|
179
217
|
|
|
180
218
|
1. 語彙: 有償生成の承認は「**費用承認**」。「判子」は 9/6 契約どおり書き出しの 1 回にだけ使う
|
|
181
|
-
2. 回数: 1 クリップずつが既定。複数を選んで**合計金額を出して 1
|
|
219
|
+
2. 回数: 1 クリップずつが既定。複数を選んで**合計金額を出して 1 回**は可。「全部を自動で動画にする」は無い。複数選択時の右パネル(対象一覧 + 合計見積 + まとめて費用承認 1 回)を正の UI とする。対象外(画像のまま・空の枠・生成済み)は送らない。見積は送信ボタンの横に常時出す
|
|
182
220
|
3. 見積: `price.by_resolution × duration_s × audio_multiplier`、as_of 付き。`actual_usd` が取れない provider は `estimate` を写して `cost.source: "estimate"`。見積不可(price null)は明示確認で通す
|
|
183
221
|
4. 停止条件は autonomy §4 と同じ(有償 or 外部送信)。Codex 画像生成は無償扱い
|
|
184
222
|
|
|
@@ -187,9 +225,18 @@ Kling v3 standard i2v / Kling v3 pro i2v / Veo 3.1 first-last / Veo 3.1 referenc
|
|
|
187
225
|
| 語 | 意味 |
|
|
188
226
|
|---|---|
|
|
189
227
|
| 仮枠 | 尺と場所を持つ静止画クリップ。完成品でもある |
|
|
228
|
+
| 動画予定 | 仮枠に動画生成の下書き(`next`)が付いた状態。mp4 はまだ無い |
|
|
229
|
+
| 空の枠 | 絵も prompt もまだ無い仮枠(文字カード) |
|
|
230
|
+
| 画像のまま | 動画にしない静止画クリップ。完成品 |
|
|
190
231
|
| 参照動画 | 動きやカメラワークを**真似る元**。貼り込まれない |
|
|
191
232
|
| 元動画 | **続ける・直す元**(extend / edit / motion / frame-edit) |
|
|
192
233
|
| 費用承認 | 有償生成の実行前ゲート |
|
|
193
234
|
| 判子 | 書き出しの 1 回(9/6) |
|
|
194
235
|
| 事実帯 | モデル選択の 1 行(価格・尺・入力・音声・較正)。レーダーの代わり |
|
|
195
236
|
|
|
237
|
+
## 10. コマ保存(キャプチャ)(2026-09-21)
|
|
238
|
+
|
|
239
|
+
1. プレビューの**カメラのアイコンだけのボタン**(文字なし・絵文字にしない)= 今のコマを **見たまま(合成後・LUT とサイズ込み)** で `assets/captures/frame-<t>.png` に保存し、トーストを出す。素材パネルに出る
|
|
240
|
+
2. キャプチャを生成の入力(②③④)に使うときは、**その png が素材**。LUT 込みで撮ったなら込みで送られる(§7-1 の「送る絵は素材のまま」と矛盾しない — 素材がそういう絵である)。UI は枠に入れるとき「見たままのコマ(色・サイズ込み)」と明示する
|
|
241
|
+
3. 「あいだを生成」(§1-8)の前後コマ抽出は**素材の画素**(合成前)を使う。見たままが要るときは人がカメラボタンで撮る
|
|
242
|
+
4. 書き出し経路にボタンは 0 px(§6)
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# akari-launcher(`akari` コマンド)
|
|
2
2
|
|
|
3
|
+
ライブラリの置き場は既定で作業場の `library/`。作業場が無いときは従来の `~/.akari/assets/` を使う。
|
|
4
|
+
`akari-assets list`(または `akari assets list`)の先頭行で実際の置き場を確認する。
|
|
5
|
+
以下の `<ライブラリの置き場>` はその表示先を指し、音源はその下の `audio/` に入る。
|
|
6
|
+
|
|
3
7
|
「UI に依存したくない。opencode 単体でも、どんなディレクトリでも始められるように」を
|
|
4
8
|
実現する薄いラッパー CLI。npm パッケージ名は `akari-video`、提供するコマンド名は `akari`
|
|
5
9
|
(npm の `akari` は別プロダクトが取得済みのため。オーナー裁定 2026-07-21 §8-2)。
|
|
@@ -24,7 +28,7 @@ akari
|
|
|
24
28
|
├─ 4. 公式音源ライブラリ(AKARI Sounds)の初回セットアップ(src/sounds-setup.mjs):
|
|
25
29
|
│ 未導入かつ TTY のとき生涯 1 回だけ [Y/n](既定 Yes)を聞き、Yes なら
|
|
26
30
|
│ packages/audio-library-setup/bin/fetch-akari-sounds.mjs で一括ダウンロード。
|
|
27
|
-
│ n は marker
|
|
31
|
+
│ n は marker(<ライブラリの置き場>/audio/.akari-sounds-declined.json)を書いて以後
|
|
28
32
|
│ 聞かない。再入口は `akari sounds`。失敗しても起動は止めない
|
|
29
33
|
│
|
|
30
34
|
└─ 5. 最後に opencode を exec する
|
|
@@ -48,7 +52,7 @@ DL・sha256 検証・適用まで実行。それ以外(npm グローバル / g
|
|
|
48
52
|
`akari store <connect|status|install|download|disconnect>`(AKARI Store 連携。マイページで発行した
|
|
49
53
|
接続トークンを `~/.akari/store-credentials.json`(0600)に保存し、購入済み一覧の確認と
|
|
50
54
|
配布物の取得ができる。`install <productId> [--from <zip>]` は購入パックを展開し、`PACK.json` の
|
|
51
|
-
収載素材を
|
|
55
|
+
収載素材を `<ライブラリの置き場>/installed.json` へ登録する。`--from` は開発・オフライン導入時に手元の
|
|
52
56
|
zip を使う。`src/store-command.mjs`)/
|
|
53
57
|
`akari assets <list|fetch|sync|...>`(素材カタログの一覧・取得・同期。
|
|
54
58
|
`packages/asset-resolver` の CLI への薄い委譲で、カタログ合成・entitlements 判定・
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "akari-video",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.74",
|
|
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": [
|