akari-video 1.5.0-beta.1 → 1.5.0-beta.2

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": "1.5.0-beta.1",
3
+ "version": "1.5.0-beta.2",
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,9 +1,11 @@
1
1
  import fs from 'node:fs/promises';
2
+ import os from 'node:os';
2
3
  import path from 'node:path';
3
4
  import { pathToFileURL } from 'node:url';
4
5
 
5
6
  import { resolveLauncherAssets } from './repo-assets.mjs';
6
7
  import { cliText } from './i18n.mjs';
8
+ import { findExecutable } from './path-lookup.mjs';
7
9
 
8
10
  const usage = (lang) => cliText('cli.new.help.usage', {}, lang);
9
11
  const languageTagPattern = /^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$/;
@@ -11,6 +13,7 @@ const languageTagPattern = /^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$/;
11
13
  function parseArguments(args) {
12
14
  let target;
13
15
  let template;
16
+ let from;
14
17
  let lang;
15
18
 
16
19
  for (let index = 0; index < args.length; index += 1) {
@@ -22,6 +25,13 @@ function parseArguments(args) {
22
25
  }
23
26
  template = value;
24
27
  index += 1;
28
+ } else if (argument === '--from') {
29
+ const value = args[index + 1];
30
+ if (!value || value.startsWith('--')) {
31
+ throw new Error(`${usage()}\n${cliText('cli.new.error.fromMissing', {})}`);
32
+ }
33
+ from = value;
34
+ index += 1;
25
35
  } else if (argument === '--lang') {
26
36
  const value = args[index + 1];
27
37
  if (!value || !languageTagPattern.test(value)) {
@@ -41,7 +51,7 @@ function parseArguments(args) {
41
51
  if (target === undefined) {
42
52
  throw new Error(usage());
43
53
  }
44
- return { target, template, lang };
54
+ return { target, template, from, lang };
45
55
  }
46
56
 
47
57
  async function directoryHasFile(directory, relativeFile) {
@@ -53,6 +63,28 @@ async function directoryHasFile(directory, relativeFile) {
53
63
  }
54
64
  }
55
65
 
66
+ async function resolvePlaybookDir(from, { cwd, targetDir, assets, env = process.env }) {
67
+ const explicit = path.resolve(cwd, from);
68
+ if (await directoryHasFile(explicit, 'playbook.json')) return explicit;
69
+ if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(from)) return null;
70
+ if (assets.creatorRootModulePath) {
71
+ const { resolveCreatorRoot } = await import(pathToFileURL(assets.creatorRootModulePath).href);
72
+ const root = await resolveCreatorRoot({ cwd, env });
73
+ if (root?.error) throw root.error;
74
+ const relative = root && path.relative(root.rootDir, targetDir);
75
+ const segments = relative?.split(path.sep) ?? [];
76
+ const fromTarget = segments[0] === 'channels' ? segments[1] : null;
77
+ const channel = fromTarget && root?.manifest?.channels?.includes(fromTarget)
78
+ ? fromTarget : root?.manifest?.channels?.[0];
79
+ if (root && channel) {
80
+ const candidate = path.join(root.rootDir, 'channels', channel, 'playbooks', from);
81
+ if (await directoryHasFile(candidate, 'playbook.json')) return candidate;
82
+ }
83
+ }
84
+ const local = path.join(env.AKARI_HOME || path.join(os.homedir(), '.akari'), 'playbooks', from);
85
+ return await directoryHasFile(local, 'playbook.json') ? local : null;
86
+ }
87
+
56
88
  export async function runNewCommand(args, options = {}) {
57
89
  const text = (key, params) => cliText(key, params);
58
90
  const log = options.log ?? ((line) => console.log(line));
@@ -62,6 +94,7 @@ export async function runNewCommand(args, options = {}) {
62
94
 
63
95
  if (args.includes('--help') || args.includes('-h')) {
64
96
  log(usage());
97
+ log(text('cli.new.help.fromUsage'));
65
98
  return { exitCode: 0 };
66
99
  }
67
100
 
@@ -73,9 +106,18 @@ export async function runNewCommand(args, options = {}) {
73
106
  return { exitCode: 1 };
74
107
  }
75
108
 
76
- const { target, template, lang } = parsed;
109
+ const { target, template, from, lang } = parsed;
77
110
  const targetDir = path.resolve(cwd, target);
78
111
  const templateDir = template ? path.resolve(cwd, template) : assets.templateDir;
112
+ let playbookDir;
113
+ if (from) {
114
+ try { playbookDir = await resolvePlaybookDir(from, { cwd, targetDir, assets, env: options.env }); }
115
+ catch (error) { logError(error.message); return { exitCode: 1 }; }
116
+ if (!playbookDir) {
117
+ logError(text('cli.new.error.fromNotFound', { from }));
118
+ return { exitCode: 1 };
119
+ }
120
+ }
79
121
 
80
122
  if (!templateDir) {
81
123
  logError(text('cli.new.error.templateUnavailable'));
@@ -107,9 +149,21 @@ export async function runNewCommand(args, options = {}) {
107
149
 
108
150
  try {
109
151
  const createProject = options.createProject ?? await defaultCreateProject(assets.scaffoldModulePath);
110
- const result = await createProject(targetDir, templateDir, hasSkills
152
+ const scaffoldOptions = hasSkills
111
153
  ? { skillsSourceDir, schemasSourceDir: hasSchemas ? schemasSourceDir : undefined }
112
- : {});
154
+ : {};
155
+ let applied;
156
+ if (playbookDir) {
157
+ const scaffold = options.scaffold ?? await import(pathToFileURL(assets.scaffoldModulePath).href);
158
+ const env = options.env ?? process.env;
159
+ scaffoldOptions.beforeCommit = async (destination) => {
160
+ applied = await scaffold.applyPlaybook({ projectDir: destination, playbookDir,
161
+ hasTool: (name) => Boolean(findExecutable(name, env.PATH ?? process.env.PATH ?? '', process.platform,
162
+ env.PATHEXT ?? process.env.PATHEXT)) });
163
+ return applied;
164
+ };
165
+ }
166
+ const result = await createProject(targetDir, templateDir, scaffoldOptions);
113
167
  if (lang) {
114
168
  const intakePath = path.join(targetDir, '.akari', 'intake.json');
115
169
  const intake = JSON.parse(await fs.readFile(intakePath, 'utf8'));
@@ -123,7 +177,12 @@ export async function runNewCommand(args, options = {}) {
123
177
  log(text('cli.new.result.skills', { status: hasSkills ? text('cli.new.label.included', { path: skillsSourceDir }) : text('cli.new.label.skipped') }));
124
178
  log(`git: ${result.git.action}`);
125
179
  log(text('cli.new.result.report', { path: result.reportPath }));
126
- return { exitCode: 0, result };
180
+ if (applied) {
181
+ log(text('cli.new.result.fromApplied', { path: applied.playbookJsonPath }));
182
+ log(text('cli.new.result.sheet', { path: applied.sheetPath }));
183
+ for (const tool of applied.missingTools) log(text('cli.new.warning.toolMissing', { tool }));
184
+ }
185
+ return { exitCode: 0, result, applied };
127
186
  } catch (error) {
128
187
  logError(error instanceof Error ? error.message : String(error));
129
188
  return { exitCode: 1 };
@@ -90,6 +90,7 @@
90
90
  "docs/contract-2026-10-11-speaker-split-v0.md",
91
91
  "docs/contract-2026-10-11-ui-i18n.md",
92
92
  "docs/contract-2026-10-12-caption-look-v1.md",
93
+ "docs/contract-2026-10-15-playbook-v0.md",
93
94
  "packages/akari-ear/package.json",
94
95
  "packages/akari-ear/README.md",
95
96
  "packages/akari-launcher/package.json",
@@ -237,6 +238,7 @@
237
238
  "skills/overlay-authoring/text-behind-person.md",
238
239
  "skills/overlay-authoring/thumbnail.md",
239
240
  "skills/overlay-authoring/world.md",
241
+ "skills/record-playbook/SKILL.md",
240
242
  "skills/render-cut/SKILL.md",
241
243
  "skills/research-plan/competitor.md",
242
244
  "skills/research-plan/ideate.md",
@@ -0,0 +1,190 @@
1
+ ---
2
+ lifecycle: accepted
3
+ created: 2026-10-15
4
+ updated: 2026-10-15
5
+ ---
6
+
7
+ # playbook-v0(作り方 = Playbook)契約
8
+
9
+ - 日付: 2026-10-15
10
+ - 状態: **v0 受理(2026-10-15 オーナー GO)**。実装は本契約の範囲に限る
11
+ - 前提: `contract-2026-07-25-project-structure-v0.md`(プロジェクト内の置き場所)/
12
+ `contract-2026-07-17-data-contract-versioning.md`(版管理三原則。初版から適用)/
13
+ `contract-2026-09-02-asset-reference-model.md`(参照台帳 `.akari/asset-references.json`)/
14
+ `contract-2026-09-24-style-v0.md`(利用台帳 `.akari/style-usage.json`)/
15
+ `contract-2026-09-13-generation-v0.md`(仮枠。`planning/frames/<stem>.scene.json` と `assets/generated/`)/
16
+ `contract-2026-10-15-project-manifest-v0.md`(依存グラフ。本契約の `parts` と同じ語彙)/
17
+ `skills/create-project/SKILL.md` と `akari new`(雛形の写し。本契約はここに `--from` を足す)
18
+ - 発端: 1 本作り終えたプロジェクトの「作り方」を記録し、次のプロジェクトを同じ作り方から始められるようにしたい。
19
+ テンプレート(`templates/project-default` = 器、`channels/<ch>/templates/*.md` = 企画書の下書き)では
20
+ 工程・設定値・仮枠・使った部品・要る道具が残らない
21
+ - スコープ: 作り方の **形(playbook.md と playbook.json)・置き場・記録の規則(プロジェクト → 作り方)・
22
+ 適用の規則(作り方 → 新しいプロジェクト)・確認シート・検査**。深さは ① 流れと設定 と ② 部品と仮枠 まで
23
+ - 非スコープ(§8): ③ 元データごと(edit.json そのもの + 素材の実体)の配布 / Lab での公開・入手 /
24
+ URL から作り方を起こす分析 / クリエイター登録 / 画面の最終デザイン
25
+
26
+ ## 0. 位置づけ — 作り方は「文書 + 目録」で、エンジンではない
27
+
28
+ 作り方(Playbook)は、**人が読む `playbook.md`** と **機械が読む `playbook.json`** の対で 1 つ。
29
+ どちらも正本で、`playbook.json` は `playbook.md` の目録に相当する(章と項目が 1 対 1)。
30
+ 作り方は工程の並びと確認点を書いた文書であり、自動で回す仕組みは持たない(回すのはスキル)。
31
+
32
+ | 語 | 意味 |
33
+ |---|---|
34
+ | 作り方 / Playbook | 流れ(工程と確認点)+ 設定値 + 仮枠 + 使った部品 + 要る道具 + ライセンス |
35
+ | 記録する(record) | 終わったプロジェクトから作り方を書き出す |
36
+ | 始める(apply) | 作り方から新しいプロジェクトを起こす(雛形 + 作り方 + 仮枠つきの骨 + 確認シート) |
37
+ | 深さ(depth) | 1 = 流れと設定だけ / 2 = 部品と仮枠も / 3 = 元データごと(非スコープ) |
38
+ | 仮枠(placeholder) | 素材を役割に抽象化した空き枠。始めたとき edit.json の骨に並ぶ |
39
+
40
+ ## 1. 置き場
41
+
42
+ | 何 | どこ | 誰が書く |
43
+ |---|---|---|
44
+ | プロジェクトの作り方(記録したもの) | `<project>/planning/playbook.md` と `<project>/planning/playbook.json` | `record-playbook` スキル |
45
+ | 手元の作り方(自分用の棚) | `~/.akari/playbooks/<id>/{playbook.md, playbook.json, preview/}` | 人・スキル(記録の写し) |
46
+ | チャンネルの作り方(配りたいもの) | `channels/<channel>/playbooks/<id>/{playbook.md, playbook.json, preview/}` | 人・スキル |
47
+ | 始めたプロジェクトに写したもの | `<project>/planning/playbook.md` と `playbook.json`(出どころを `provenance` に残す) | `akari new --from` |
48
+ | 確認シート | `<project>/.akari/reports/playbook-sheet.html`(読み取り専用・派生) | `akari new --from` |
49
+
50
+ - 一覧の解決順は **チャンネル → 手元** の 2 択だけ(`create-project` の雛形解決と同じ規律。他の経路を作らない)
51
+ - `preview/` は任意。`cover.png` か `sample.mp4` を 1 つまで。無ければ画面は文字だけで出す
52
+ - `<id>` は英小文字・数字・ハイフン。同じ `id` は版で区別する(`version` 整数)
53
+
54
+ ## 2. 形 — playbook.json
55
+
56
+ ```json
57
+ {
58
+ "version": 0,
59
+ "kind": "akari-playbook",
60
+ "id": "kaisetsu-vertical-60s",
61
+ "name": "縦の解説 60 秒",
62
+ "playbookVersion": 1,
63
+ "depth": 2,
64
+ "category": "explainer",
65
+ "tags": { "form": ["vertical"], "length": ["30-60s"], "technique": ["live-action"], "tools": ["voicevox"],
66
+ "style": [], "industry": [], "materials": ["talking-head", "screen-capture"], "scale": ["solo"] },
67
+ "requires": { "cli": ">=1.4.0", "tools": ["voicevox"], "skills": ["edit-plan", "render-cut"] },
68
+ "steps": [
69
+ { "id": "intake", "title": "素材を置く", "what": "画面収録と顔出しを assets/ に置き、analyze-footage を回す", "skill": "analyze-footage", "checkpoint": false },
70
+ { "id": "script", "title": "台本を確定する", "what": "planning/script.md を書き、冒頭 3 秒のつかみを決める", "skill": "research-plan", "checkpoint": true },
71
+ { "id": "cut", "title": "カットを整える", "what": "無音を詰め、字幕を当てる", "skill": "edit-plan", "checkpoint": false },
72
+ { "id": "export", "title": "書き出す", "what": "1080x1920 で exports/ に出す", "skill": "render-cut", "checkpoint": false }
73
+ ],
74
+ "settings": {
75
+ "aspect": "9:16", "fps": 30, "targetDurationSec": 60,
76
+ "captions": { "styleUid": "st_01HZ…", "position": "lower" },
77
+ "transitions": { "default": "cut" },
78
+ "audio": { "roles": { "voice": -14, "bgm": -24 } }
79
+ },
80
+ "placeholders": [
81
+ { "id": "talking-head", "role": "話している本人の寄り", "kind": "video", "durationHintSec": 40, "sample": { "category": "sample", "id": "placeholder-talking-head" } },
82
+ { "id": "screen", "role": "画面収録", "kind": "video", "durationHintSec": 20 },
83
+ { "id": "bgm", "role": "軽めの BGM", "kind": "audio", "sample": { "category": "audio", "id": "light-loop-01", "source": "lab" } }
84
+ ],
85
+ "parts": [
86
+ { "kind": "style", "id": "caption-pop", "uid": "st_01HZ…", "revision": 2, "source": "builtin", "license": "CC0-1.0" },
87
+ { "kind": "asset", "category": "audio", "id": "light-loop-01", "source": "lab", "license": "LicenseRef-AKARI-Assets-v0", "tier": "free" }
88
+ ],
89
+ "license": "CC0-1.0",
90
+ "provenance": { "fromProject": "akari-howto", "recordedAt": "2026-10-15T10:00:00+09:00", "akariVersion": "1.4.0", "recordedBy": "record-playbook" }
91
+ }
92
+ ```
93
+
94
+ - 必須: `version`(0 固定。原則 1)・`kind`(`"akari-playbook"`)・`id`・`name`・`playbookVersion`・`depth`・
95
+ `category`・`steps[]`・`settings`・`license`・`provenance`。`tags` / `requires` / `placeholders` / `parts` は
96
+ 省略可(depth 1 では `placeholders` と `parts` を持たない)
97
+ - `category` は 1 つだけ。語彙は閉じる: `film` / `short-drama` / `mv` / `explainer` / `product` / `vlog` / `cm` /
98
+ `education` / `clip` / `logo`。足すときは本表に追記してから
99
+ - `tags` の 8 軸は開いた語彙(自由に足せる)。軸の名前だけ固定: `form` / `length` / `technique` / `tools` /
100
+ `style` / `industry` / `materials` / `scale`。`tools` は `requires.tools` から機械的に写す
101
+ - `steps[]`: `id`・`title`・`what` が必須。`skill` は公開リポの `skills/<name>` の名前。`checkpoint: true` は
102
+ **人の確認点**(自動で回すときはここで止まる。始めるときの確認シートにも出す)
103
+ - `settings`: 自由なオブジェクト。推奨キーは上の例(`aspect` / `fps` / `targetDurationSec` / `captions` /
104
+ `transitions` / `audio`)。edit.json の値をそのまま写さず、**次のプロジェクトで最初に当てる値**だけを書く
105
+ - `placeholders[]`: `id`・`role`・`kind`(`video` / `image` / `audio`)が必須。`sample` は見本の素材参照
106
+ (参照台帳と同じ `{category, id}` + `source`)。**素材の実体は持たない**。`source: own` / `site` の素材は
107
+ 必ず仮枠にし、`sample` を付けない(外部由来を見本に映さない)
108
+ - `parts[]`: project-manifest v0 の `kind` 語彙(`asset` / `style` / `kit`)と `source`(`builtin` / `lab` / `own` /
109
+ `site` / `ai`)。`license` は素材の `meta.json` から写す。`own` / `site` の部品は `parts` に残さず仮枠へ
110
+ - `license`: 作り方そのもののライセンス。無料で配るものは `CC0-1.0`、有償は `LicenseRef-AKARI-Assets-v0`
111
+ - 並びは `steps` が記述順、他は `id` の安定ソート。書き込みは tmp + rename。読み手は tolerant reader
112
+
113
+ ## 3. 形 — playbook.md(章立て固定)
114
+
115
+ ```markdown
116
+ # 縦の解説 60 秒 ← name。直下に 1 行で「何ができるか」
117
+ ## 目的とできあがり ← category と、できあがりの説明(尺・形・雰囲気)
118
+ ## 流れ ← steps を番号つきで。確認点は「☑ ここで確認」と明記
119
+ ## 設定値 ← settings を表で(キー / 値 / 意味)
120
+ ## 必要な素材(仮枠) ← placeholders を表で(役割 / 種類 / 尺の目安 / 見本)
121
+ ## 使った部品 ← parts を表で(種類 / 名前 / 入手先 / ライセンス)
122
+ ## 要る道具 ← requires(CLI の版・道具・スキル)。無いときの代案を 1 行
123
+ ## ライセンス ← license と、外部由来を仮枠にした旨
124
+ ## 出どころ ← provenance(どのプロジェクトから・いつ・どの版で)
125
+ ```
126
+
127
+ 章の追加は末尾のみ(additive-only)。章の名前は上の表記で固定し、読み手はこの見出しで章を引く。
128
+
129
+ ## 4. 記録する — プロジェクト → 作り方(`record-playbook` スキル)
130
+
131
+ 入力はプロジェクトのルート。出力は `planning/playbook.md` と `planning/playbook.json`(既にあれば `playbookVersion` を上げて上書き。他は `flag:'wx'`)。
132
+
133
+ | 章 / 項目 | 取り出し元 | 規則 |
134
+ |---|---|---|
135
+ | `steps` | `decisions.json`(判断の記録)・`planning/` の文書・使ったスキルの痕跡(`.akari/reports/` の種類) | 工程として並べ、`checkpoint` は決定ログで人が承認した点に立てる。取り出せないときは `steps` を 4 つの既定(素材を置く / 台本を確定する / カットを整える / 書き出す)で埋め、`what` に「要確認」と書く |
136
+ | `settings` | `edit.json`(アスペクト・fps・字幕スタイル・トランジションの既定・音のロール) | 値をそのまま写さず「最初に当てる値」に丸める(例: 尺は target、個々のカットの長さは写さない) |
137
+ | `placeholders` | `edit.json` の sources と `analysis.json` のタグ・話者 | 素材 1 つ = 仮枠 1 つではなく**役割で束ねる**(同じ役割の素材は 1 枠に `durationHintSec` を足し合わせる)。`own` / `site` は `sample` なし |
138
+ | `parts` | `.akari/asset-references.json`・`.akari/style-usage.json` | `builtin` / `lab` / `ai` だけ残す。`own` / `site` は仮枠へ |
139
+ | `requires` | 使ったスキル・レシピの `requires`(`blender` 等)・CLI の版 | — |
140
+ | `license` | 人が決める。既定は `CC0-1.0` | スキルは既定を書き、`playbook.md` の章に「要確認」と残す |
141
+ | `provenance` | プロジェクト名・現在時刻・`akari --version` | — |
142
+
143
+ スキルは確認を人に 1 回だけ取る(`name` と `category` と `license`)。それ以外は自走し、終わりに
144
+ `playbook.md` の要約(流れ・仮枠の数・部品の数・要る道具)を 1 画面で報告する。
145
+
146
+ ## 5. 始める — 作り方 → 新しいプロジェクト(`akari new --from`)
147
+
148
+ ```sh
149
+ akari new <target-dir> --from <playbook-dir | id> [--lang <bcp47>]
150
+ ```
151
+
152
+ 1. `--from` が `id` のときは §1 の解決順(チャンネル → 手元)で `playbook.json` を探す。無ければ非 0 で終わる
153
+ 2. `templates/project-default` を従来どおり写す(既存の規律と作成レポートはそのまま)
154
+ 3. `planning/playbook.md` と `planning/playbook.json` を写し、`provenance.appliedFrom` に出どころ
155
+ (パスと `playbookVersion`)と時刻を足す
156
+ 4. `settings` を edit.json の初期値に当てる(アスペクト・fps・字幕スタイル・音のロール)。
157
+ `placeholders` を **仮枠として edit.json の骨に並べる**(generation-v0 の仮枠の形を使う。
158
+ `sample` があれば見本として参照し、無ければ空の仮枠)。素材の実体は置かない
159
+ 5. `requires.tools` を道具チェックに掛け、無い道具は作成レポートと確認シートに「無い」と出す(止めない)
160
+ 6. 確認シート `.akari/reports/playbook-sheet.html` を書く(§6)
161
+ 7. 標準出力に作成レポートと確認シートのパスを出す
162
+
163
+ `--from` を付けないときの挙動は一切変えない(`--template` との併用は可。雛形の解決経路は増やさない)。
164
+
165
+ ## 6. 確認シート(読み取り専用 HTML)
166
+
167
+ 取り込む前に見る 1 枚。既存の作成レポートと同じ生成器・同じ見た目(自己完結 HTML・決定 UI なし)で、
168
+ 行は固定: **名前と目的 / 深さ / 流れ(確認点つき) / 設定値の数と主な値 / 仮枠(役割・種類・見本の有無)/
169
+ 使った部品(入手先・ライセンス・Pro 要否)/ 要る道具(持っていないものを明記)/ ライセンス / 出どころ**。
170
+ 画面側(シェル)はこの HTML をそのまま表示し、ボタン(白紙から / 取り込んで始める)は HTML の外に置く。
171
+
172
+ ## 7. 検査
173
+
174
+ - `packages/schemas/playbook.schema.json`(closed object・additive-only)と `validate-playbook.mjs`
175
+ - 検査項目: 必須項目 / `category` の語彙 / `steps[].skill` が存在するスキル名か(警告)/ `placeholders[].sample`
176
+ に `source: own` / `site` が無いこと(**fail**)/ `parts[]` に `own` / `site` が無いこと(**fail**)/
177
+ `playbook.md` の章立てが §3 と一致すること(見出しの有無のみ)
178
+
179
+ ## 8. 非スコープ
180
+
181
+ - 深さ 3(元データごと)。edit.json そのものと素材の実体の配布
182
+ - Lab での公開・入手・検索・タグ俯瞰・クリエイター登録・還元
183
+ - URL を貼って作り方を起こす分析
184
+ - 画面の最終デザイン(ポップアップの出だしは別の実装票。本契約は形と CLI と確認シートまで)
185
+ - 自動で回す仕組み(作り方は文書。回すのはスキルと人)
186
+
187
+ ## 9. 開けた問い(オーナー裁定待ち)
188
+
189
+ 1. `settings` の推奨キーをこの 6 つに固定するか、edit.json の該当キー名と揃えるか
190
+ 2. 仮枠の見本(`sample`)を `~/.akari/playbooks/<id>/preview/` に実体で持たせるか、参照だけにするか
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akari-video",
3
- "version": "1.5.0-beta.1",
3
+ "version": "1.5.0-beta.2",
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": [
@@ -88,6 +88,12 @@
88
88
  "cli.new.label.included": "included ({path})",
89
89
  "cli.new.label.skipped": "skipped",
90
90
  "cli.new.result.report": "Creation report: {path}",
91
+ "cli.new.help.fromUsage": "Usage: akari new <target-dir> --from <playbook-dir | id> [--lang <code>]",
92
+ "cli.new.error.fromMissing": "--from requires a playbook directory or ID.",
93
+ "cli.new.error.fromNotFound": "Playbook not found: {from}",
94
+ "cli.new.result.fromApplied": "Copied playbook: {path}",
95
+ "cli.new.result.sheet": "Review sheet: {path}",
96
+ "cli.new.warning.toolMissing": "Required tool is missing: {tool}",
91
97
  "cli.narration.engine.voicevoxAvailable": "VOICEVOX is available",
92
98
  "cli.narration.engine.voicevoxStart": "Start VOICEVOX automatically",
93
99
  "cli.narration.engine.voicevoxInstall": "Install VOICEVOX",
@@ -136,6 +136,17 @@
136
136
  "preview.contextBar.toolbar.verticalTextLabel": "Vertical text",
137
137
  "preview.contextBar.toolbar.weightLabel": "Weight",
138
138
  "preview.contextBar.toolbar.widthLabel": "Width",
139
+ "preview.diagnostics.audio.abnormal": "Most recent anomaly",
140
+ "preview.diagnostics.audio.copiedNotice": "Preview diagnostics copied",
141
+ "preview.diagnostics.audio.copyCommand": "Copy Preview Diagnostics",
142
+ "preview.diagnostics.audio.events": "Audio events",
143
+ "preview.diagnostics.audio.heading": "Audio status",
144
+ "preview.diagnostics.audio.host": "Host",
145
+ "preview.diagnostics.audio.lastQuery": "Last request",
146
+ "preview.diagnostics.audio.lastResult": "Last returned state",
147
+ "preview.diagnostics.audio.lastUpdate": "Last audio update",
148
+ "preview.diagnostics.audio.latest": "Latest",
149
+ "preview.diagnostics.audio.pending": "Pending",
139
150
  "preview.diagnostics.event.assetBoundsMeasuredStatus": "Asset bounds measurement {elapsed}ms {status} {path}",
140
151
  "preview.diagnostics.event.assetPlacementStatus": "Asset placement {key} {stage} {elapsed}ms",
141
152
  "preview.diagnostics.event.dimensionProbeStartFailedError": "Could not start dimension lookup: {reason}",
@@ -2267,5 +2267,79 @@
2267
2267
  "surfaces.settingsSections.ui.connectLabel": "Connect",
2268
2268
  "surfaces.settingsSections.ui.workflowLimitsLabel": "Workflow and limits",
2269
2269
  "surfaces.settingsSections.ui.displayLabel": "Display",
2270
- "surfaces.settingsSections.ui.dataLocationsLabel": "Data locations"
2270
+ "surfaces.settingsSections.ui.dataLocationsLabel": "Data locations",
2271
+ "surfaces.home.startProject.heading": "New project",
2272
+ "surfaces.home.startStepName.label": "Name",
2273
+ "surfaces.home.startStepPlaybook.label": "Playbook",
2274
+ "surfaces.home.startStepCreate.label": "Create",
2275
+ "surfaces.home.startBackToName.button": "← Back to name",
2276
+ "surfaces.home.startName.label": "Name",
2277
+ "surfaces.home.startChannel.label": "Channel",
2278
+ "surfaces.home.startNoChannel.label": "No channel",
2279
+ "surfaces.home.startNewChannel.button": "+ New channel",
2280
+ "surfaces.home.startStandalone.button": "Create without a channel",
2281
+ "surfaces.home.startStandaloneNote.heading": "This is a special setup",
2282
+ "surfaces.home.startStandaloneNote.message": "Channel kits, people, and styles are unavailable. Choose the save location when you create it.",
2283
+ "surfaces.home.startStandaloneLater.message": "You can add it to a channel later.",
2284
+ "surfaces.home.startBlank.button": "Start blank",
2285
+ "surfaces.home.startBlank.description": "Start with an empty project. Add your own content and settings as you go.",
2286
+ "surfaces.home.startFromPlaybook.button": "Start from a Playbook",
2287
+ "surfaces.home.startFromPlaybook.description": "Choose a Playbook from your library or channel. Start with its steps and settings.",
2288
+ "surfaces.home.startDefaultName.label": "New project",
2289
+ "surfaces.home.playbookCategory.label": "Category",
2290
+ "surfaces.home.playbookAll.label": "All",
2291
+ "surfaces.home.playbookSource.label": "Source",
2292
+ "surfaces.home.playbookSource.all.label": "All",
2293
+ "surfaces.home.playbookSource.local.label": "Mine",
2294
+ "surfaces.home.playbookSource.channel.label": "Channel",
2295
+ "surfaces.home.playbookEmpty.message": "No Playbooks yet. Record one from a finished project with record-playbook.",
2296
+ "surfaces.home.playbookSelectHint.message": "Select a Playbook to see its review sheet.",
2297
+ "surfaces.home.playbookRead.button": "Read contents",
2298
+ "surfaces.home.playbookApply.button": "Import and start",
2299
+ "surfaces.home.playbookFallbackNote.message": "Placeholders will be added later.",
2300
+ "surfaces.home.playbookSampleYes.label": "Sample available",
2301
+ "surfaces.home.playbookSampleNo.label": "No sample",
2302
+ "surfaces.home.playbookProRequired.label": "Pro required",
2303
+ "surfaces.home.playbookProNotRequired.label": "No Pro required",
2304
+ "surfaces.home.playbookToolMissing.label": "Missing",
2305
+ "surfaces.home.playbookToolAvailable.label": "Available",
2306
+ "surfaces.home.playbookDepthOne.label": "Steps and settings",
2307
+ "surfaces.home.playbookDepthTwo.label": "Includes parts and placeholders",
2308
+ "surfaces.home.playbookCheckpoint.label": "Check here",
2309
+ "surfaces.home.playbookSheetIdentity.label": "Name and purpose",
2310
+ "surfaces.home.playbookSheetDepth.label": "Depth",
2311
+ "surfaces.home.playbookSheetSteps.label": "Steps",
2312
+ "surfaces.home.playbookSheetSettings.label": "Settings",
2313
+ "surfaces.home.playbookSheetPlaceholders.label": "Placeholders",
2314
+ "surfaces.home.playbookSheetParts.label": "Parts used",
2315
+ "surfaces.home.playbookSheetTools.label": "Required tools",
2316
+ "surfaces.home.playbookSheetLicense.label": "License",
2317
+ "surfaces.home.playbookSheetProvenance.label": "Provenance",
2318
+ "surfaces.home.playbookCategory.film.label": "Film",
2319
+ "surfaces.home.playbookCategory.shortDrama.label": "Short drama",
2320
+ "surfaces.home.playbookCategory.mv.label": "Music video",
2321
+ "surfaces.home.playbookCategory.explainer.label": "Explainer",
2322
+ "surfaces.home.playbookCategory.product.label": "Product",
2323
+ "surfaces.home.playbookCategory.vlog.label": "Vlog",
2324
+ "surfaces.home.playbookCategory.cm.label": "Commercial",
2325
+ "surfaces.home.playbookCategory.education.label": "Education",
2326
+ "surfaces.home.playbookCategory.clip.label": "Clip",
2327
+ "surfaces.home.playbookCategory.logo.label": "Logo",
2328
+ "surfaces.home.playbookPurposeAspect.message": "Aspect ratio {aspect}",
2329
+ "surfaces.home.playbookPurposeDuration.message": "{duration} sec",
2330
+ "surfaces.home.playbookRequiredCli.message": "CLI {version}",
2331
+ "surfaces.home.playbookRequiredSkill.message": "Skill {skill}",
2332
+ "surfaces.home.playbookStepCount.message": "{count} steps ({checkpoints} checkpoints)",
2333
+ "surfaces.home.playbookSettingCount.message": "{count} settings",
2334
+ "surfaces.home.playbookPlaceholderCount.message": "{count} placeholders",
2335
+ "surfaces.home.playbookItemCount.message": "{count} items",
2336
+ "surfaces.home.startBlankAction.label": "Create now →",
2337
+ "surfaces.home.startPlaybookAction.label": "Choose →",
2338
+ "surfaces.home.playbookListHeading.message": "{category} Playbooks · {count} items",
2339
+ "surfaces.home.playbookCheckingTools.message": "Checking tools…",
2340
+ "surfaces.home.playbookExample.label": "Example",
2341
+ "surfaces.home.playbookNoPreview.message": "No preview yet",
2342
+ "surfaces.home.playbookPreviewPause.button": "Pause preview",
2343
+ "surfaces.home.playbookPreviewResume.button": "Resume preview",
2344
+ "surfaces.home.playbookPreviewFrame.button": "Show preview frame {frame}"
2271
2345
  }
@@ -88,6 +88,12 @@
88
88
  "cli.new.label.included": "実施({path})",
89
89
  "cli.new.label.skipped": "スキップ",
90
90
  "cli.new.result.report": "作成結果レポート: {path}",
91
+ "cli.new.help.fromUsage": "使い方: akari new <target-dir> --from <playbook-dir | id> [--lang <code>]",
92
+ "cli.new.error.fromMissing": "--from には作り方のディレクトリまたは ID が必要です。",
93
+ "cli.new.error.fromNotFound": "作り方が見つかりません: {from}",
94
+ "cli.new.result.fromApplied": "作り方を写しました: {path}",
95
+ "cli.new.result.sheet": "確認シート: {path}",
96
+ "cli.new.warning.toolMissing": "要る道具がありません: {tool}",
91
97
  "cli.narration.engine.voicevoxAvailable": "VOICEVOX を使用できます",
92
98
  "cli.narration.engine.voicevoxStart": "VOICEVOX を起動します(自動)",
93
99
  "cli.narration.engine.voicevoxInstall": "VOICEVOX をインストール",
@@ -136,6 +136,17 @@
136
136
  "preview.contextBar.toolbar.verticalTextLabel": "縦書き",
137
137
  "preview.contextBar.toolbar.weightLabel": "太さ",
138
138
  "preview.contextBar.toolbar.widthLabel": "幅",
139
+ "preview.diagnostics.audio.abnormal": "直近の異常",
140
+ "preview.diagnostics.audio.copiedNotice": "プレビューの診断をコピーしました",
141
+ "preview.diagnostics.audio.copyCommand": "プレビューの診断をコピー",
142
+ "preview.diagnostics.audio.events": "音の事象",
143
+ "preview.diagnostics.audio.heading": "音の状態",
144
+ "preview.diagnostics.audio.host": "ホスト",
145
+ "preview.diagnostics.audio.lastQuery": "最後の問い合わせ",
146
+ "preview.diagnostics.audio.lastResult": "最後に返った状態",
147
+ "preview.diagnostics.audio.lastUpdate": "最後の音声更新",
148
+ "preview.diagnostics.audio.latest": "最新",
149
+ "preview.diagnostics.audio.pending": "待機中",
139
150
  "preview.diagnostics.event.assetBoundsMeasuredStatus": "素材の枠測定 {elapsed}ms {status} {path}",
140
151
  "preview.diagnostics.event.assetPlacementStatus": "素材配置 {key} {stage} {elapsed}ms",
141
152
  "preview.diagnostics.event.dimensionProbeStartFailedError": "寸法の取得を開始できません: {reason}",
@@ -2267,5 +2267,79 @@
2267
2267
  "surfaces.settingsSections.ui.connectLabel": "つなぐ",
2268
2268
  "surfaces.settingsSections.ui.workflowLimitsLabel": "進め方と上限",
2269
2269
  "surfaces.settingsSections.ui.displayLabel": "表示",
2270
- "surfaces.settingsSections.ui.dataLocationsLabel": "データの場所"
2270
+ "surfaces.settingsSections.ui.dataLocationsLabel": "データの場所",
2271
+ "surfaces.home.startProject.heading": "新しいプロジェクト",
2272
+ "surfaces.home.startStepName.label": "名前",
2273
+ "surfaces.home.startStepPlaybook.label": "作り方",
2274
+ "surfaces.home.startStepCreate.label": "作る",
2275
+ "surfaces.home.startBackToName.button": "← 名前に戻る",
2276
+ "surfaces.home.startName.label": "名前",
2277
+ "surfaces.home.startChannel.label": "チャンネル",
2278
+ "surfaces.home.startNoChannel.label": "チャンネルなし",
2279
+ "surfaces.home.startNewChannel.button": "+ 新しいチャンネル",
2280
+ "surfaces.home.startStandalone.button": "チャンネルに入れずに作る",
2281
+ "surfaces.home.startStandaloneNote.heading": "特別な作り方です",
2282
+ "surfaces.home.startStandaloneNote.message": "チャンネルのキット・人物・スタイルが使えません。保存先は作るときに選びます。",
2283
+ "surfaces.home.startStandaloneLater.message": "あとからチャンネルに入れることもできます。",
2284
+ "surfaces.home.startBlank.button": "白紙から",
2285
+ "surfaces.home.startBlank.description": "素材も設定もない状態から始めます。あとで好きな形に組み立てられます。",
2286
+ "surfaces.home.startFromPlaybook.button": "作り方(Playbook)から",
2287
+ "surfaces.home.startFromPlaybook.description": "手元やチャンネルの作り方を選びます。流れと設定を引き継いで始められます。",
2288
+ "surfaces.home.startDefaultName.label": "新しいプロジェクト",
2289
+ "surfaces.home.playbookCategory.label": "カテゴリー",
2290
+ "surfaces.home.playbookAll.label": "すべて",
2291
+ "surfaces.home.playbookSource.label": "入手先",
2292
+ "surfaces.home.playbookSource.all.label": "すべて",
2293
+ "surfaces.home.playbookSource.local.label": "自分の",
2294
+ "surfaces.home.playbookSource.channel.label": "チャンネル",
2295
+ "surfaces.home.playbookEmpty.message": "作り方はまだありません。終わったプロジェクトから record-playbook で記録できます",
2296
+ "surfaces.home.playbookSelectHint.message": "作り方を選ぶと確認シートが出ます。",
2297
+ "surfaces.home.playbookRead.button": "中身を読む",
2298
+ "surfaces.home.playbookApply.button": "取り込んで始める",
2299
+ "surfaces.home.playbookFallbackNote.message": "仮枠は後で",
2300
+ "surfaces.home.playbookSampleYes.label": "見本あり",
2301
+ "surfaces.home.playbookSampleNo.label": "見本なし",
2302
+ "surfaces.home.playbookProRequired.label": "Pro が必要",
2303
+ "surfaces.home.playbookProNotRequired.label": "Pro 不要",
2304
+ "surfaces.home.playbookToolMissing.label": "無い",
2305
+ "surfaces.home.playbookToolAvailable.label": "ある",
2306
+ "surfaces.home.playbookDepthOne.label": "流れと設定",
2307
+ "surfaces.home.playbookDepthTwo.label": "部品と仮枠を含む",
2308
+ "surfaces.home.playbookCheckpoint.label": "ここで確認",
2309
+ "surfaces.home.playbookSheetIdentity.label": "名前と目的",
2310
+ "surfaces.home.playbookSheetDepth.label": "深さ",
2311
+ "surfaces.home.playbookSheetSteps.label": "流れ",
2312
+ "surfaces.home.playbookSheetSettings.label": "設定値",
2313
+ "surfaces.home.playbookSheetPlaceholders.label": "仮枠",
2314
+ "surfaces.home.playbookSheetParts.label": "使った部品",
2315
+ "surfaces.home.playbookSheetTools.label": "要る道具",
2316
+ "surfaces.home.playbookSheetLicense.label": "ライセンス",
2317
+ "surfaces.home.playbookSheetProvenance.label": "出どころ",
2318
+ "surfaces.home.playbookCategory.film.label": "映画",
2319
+ "surfaces.home.playbookCategory.shortDrama.label": "短編ドラマ",
2320
+ "surfaces.home.playbookCategory.mv.label": "MV",
2321
+ "surfaces.home.playbookCategory.explainer.label": "解説",
2322
+ "surfaces.home.playbookCategory.product.label": "商品紹介",
2323
+ "surfaces.home.playbookCategory.vlog.label": "Vlog",
2324
+ "surfaces.home.playbookCategory.cm.label": "CM",
2325
+ "surfaces.home.playbookCategory.education.label": "教育",
2326
+ "surfaces.home.playbookCategory.clip.label": "切り抜き",
2327
+ "surfaces.home.playbookCategory.logo.label": "ロゴ",
2328
+ "surfaces.home.playbookPurposeAspect.message": "画面比 {aspect}",
2329
+ "surfaces.home.playbookPurposeDuration.message": "{duration} 秒",
2330
+ "surfaces.home.playbookRequiredCli.message": "CLI {version}",
2331
+ "surfaces.home.playbookRequiredSkill.message": "スキル {skill}",
2332
+ "surfaces.home.playbookStepCount.message": "{count} 工程(確認点 {checkpoints})",
2333
+ "surfaces.home.playbookSettingCount.message": "{count} 件",
2334
+ "surfaces.home.playbookPlaceholderCount.message": "{count} 枠",
2335
+ "surfaces.home.playbookItemCount.message": "{count} 件",
2336
+ "surfaces.home.startBlankAction.label": "そのまま作る →",
2337
+ "surfaces.home.startPlaybookAction.label": "選ぶ →",
2338
+ "surfaces.home.playbookListHeading.message": "{category} Playbook · {count} 件",
2339
+ "surfaces.home.playbookCheckingTools.message": "道具を確認しています…",
2340
+ "surfaces.home.playbookExample.label": "例",
2341
+ "surfaces.home.playbookNoPreview.message": "見本はまだありません",
2342
+ "surfaces.home.playbookPreviewPause.button": "見本の再生を止める",
2343
+ "surfaces.home.playbookPreviewResume.button": "見本の再生を再開する",
2344
+ "surfaces.home.playbookPreviewFrame.button": "見本のコマ {frame} を見る"
2271
2345
  }
@@ -822,7 +822,6 @@ export function previewAudioSidecarStatus(options) {
822
822
  if (resolved.probe) return { ...previewAudioSidecarStatus(resolved.options), probe: resolved.probe };
823
823
  const prepared = prepare(resolved.options, {}, false);
824
824
  const { key, outputPath, outputDirectory } = prepared;
825
- if (requested.has(outputPath) || generating.has(outputPath)) return { state: 'generating', key };
826
825
  const metadata = readMetadata(prepared);
827
826
  if (metadata && fs.existsSync(outputPath)) {
828
827
  const { durationSec, sampleRate, channels, bytes, format, frames, bytesPerSample } = metadata;
@@ -830,6 +829,7 @@ export function previewAudioSidecarStatus(options) {
830
829
  sampleRate, channels, bytes, format,
831
830
  ...(format === 'pcm-s16le' ? { frames, bytesPerSample } : {}) };
832
831
  }
832
+ if (requested.has(outputPath) || generating.has(outputPath)) return { state: 'generating', key };
833
833
  const noAudio = readCacheJson(path.join(outputDirectory, `${key}.no-audio.json`));
834
834
  if (noAudio?.key === key) return { state: 'no-audio', key, reason: noAudio.reason };
835
835
  const failed = readCacheJson(path.join(outputDirectory, `${key}.failed.json`));