owner-clone-ai-mcp 1.71.0 → 1.72.0
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/domains/knowledge.js +21 -0
- package/domains/macbuil.js +1 -1
- package/domains/slides.js +1 -1
- package/domains/video.js +128 -15
- package/lib/api.js +4 -1
- package/package.json +1 -1
package/domains/knowledge.js
CHANGED
|
@@ -80,6 +80,19 @@ const tools = [
|
|
|
80
80
|
required: ['id'],
|
|
81
81
|
},
|
|
82
82
|
},
|
|
83
|
+
{
|
|
84
|
+
name: 'get_knowledge_image_url',
|
|
85
|
+
description: 'ナレッジの添付画像の「公開URL」を取得します。ナレッジの画像は非公開保存のため、そのままではスライド(image / gallery / testimonial.photo)や広告・SNS投稿に指定できません。このツールで公開URLへ変換してから使ってください。index を省略すると全ての画像のURLを返します(gallery のように複数まとめて使う場合に便利)。⚠️ 返すURLは公開(URLを知っていれば誰でも閲覧可)になります。',
|
|
86
|
+
annotations: { readOnlyHint: true },
|
|
87
|
+
inputSchema: {
|
|
88
|
+
type: 'object',
|
|
89
|
+
properties: {
|
|
90
|
+
id: { type: 'string', description: '画像を持つナレッジのID' },
|
|
91
|
+
index: { type: 'integer', description: '何枚目の画像か(1始まり)。省略時は全ての画像のURLを返す' },
|
|
92
|
+
},
|
|
93
|
+
required: ['id'],
|
|
94
|
+
},
|
|
95
|
+
},
|
|
83
96
|
{
|
|
84
97
|
name: 'get_knowledge_file',
|
|
85
98
|
description: 'ナレッジ(画像・資料/お客様の声/実績プロフィール/フリー・メモ系)に添付された資料ファイル(PDF・Excel・CSV・Word・テキスト・画像等)の本体を取得します。資料の中身を読む・ダウンロードする必要があるときに使います。複数ある場合は index(1始まり)で何件目かを指定します(省略時は1件目)。本文の【添付資料】の並び順に対応。',
|
|
@@ -455,6 +468,14 @@ const handlers = {
|
|
|
455
468
|
};
|
|
456
469
|
},
|
|
457
470
|
|
|
471
|
+
// 非公開のナレッジ画像を公開URL化して返す(スライド等は公開URLしか受け付けないため)
|
|
472
|
+
async get_knowledge_image_url(args) {
|
|
473
|
+
const q = args.index != null ? `?index=${Math.max(1, parseInt(args.index, 10) || 1)}` : '';
|
|
474
|
+
const data = await callApi(`/knowledge/${args.id}/image-url${q}`);
|
|
475
|
+
const lines = (data.images || []).map(im => `${im.index}枚目: ${im.url}${im.description ? `(${im.description})` : ''}`);
|
|
476
|
+
return `「${data.title || ''}」の画像URL(全${data.count}枚中 ${lines.length}件)\n${lines.join('\n')}\n\n※${data.note || ''}`;
|
|
477
|
+
},
|
|
478
|
+
|
|
458
479
|
// 資料ファイル本体を取得。画像はvisionとして、それ以外は埋め込みリソース(base64)として返す=DL/参照可能。
|
|
459
480
|
async get_knowledge_file(args) {
|
|
460
481
|
const idx = Math.max(1, parseInt(args.index, 10) || 1);
|
package/domains/macbuil.js
CHANGED
|
@@ -13,7 +13,7 @@ const post = (path, body) => callApi(path, { method: 'POST', body: JSON.stringif
|
|
|
13
13
|
const tools = [
|
|
14
14
|
{
|
|
15
15
|
name: 'macbuil_list_tools',
|
|
16
|
-
description: 'Macbuil(MAツール:
|
|
16
|
+
description: 'Macbuil(MAツール: ファネル・ページ制作・メール・オファー・イベント・フォーム・会員サイト・オンラインコース)で利用可能な操作カタログを取得します。引数なし=カテゴリ別の操作一覧+操作ガイド+プレイブック索引。tool_name指定=その操作の正確な引数定義(inputSchema)。★「広告用のLPを作りたい」「商品を売りたい」「購入者だけにメールを送りたい」のような目的ベースの依頼を受けたら、まず tool_name="playbook:<ID>" で手順書を取得してください(作る前に確認すべきこと・作る順番・完了後に伝えることが返ります)。macbuil_execute を使う前に必ず tool_name 指定で引数定義を確認してください。Owner Clone AI の設定画面で Macbuil APIキーを登録済みのユーザーのみ利用可能。',
|
|
17
17
|
annotations: { readOnlyHint: true },
|
|
18
18
|
inputSchema: {
|
|
19
19
|
type: 'object',
|
package/domains/slides.js
CHANGED
|
@@ -42,7 +42,7 @@ const tools = [
|
|
|
42
42
|
knowledge_item_ids: { type: 'array', items: { type: 'string' }, description: '生成元ナレッジID(複数可)' },
|
|
43
43
|
knowledge_folder_ids: { type: 'array', items: { type: 'string' }, description: '生成元ナレッジフォルダID(サブフォルダ含む・複数可)' },
|
|
44
44
|
text: { type: 'string', description: '生成元テキスト(ナレッジ指定と併用可)' },
|
|
45
|
-
format: { type: 'string', enum: ['wide', 'classic', 'square', 'vertical', 'a4'], description: 'スライド比率: wide=16:9(既定・省略可)/ classic=4:3 / square=1:1(SNS投稿) / vertical=9:
|
|
45
|
+
format: { type: 'string', enum: ['wide', 'classic', 'square', 'vertical', 'a4'], description: 'スライド比率: wide=16:9(既定・省略可)/ classic=4:3 / square=1:1(SNS投稿) / vertical=9:16縦長(ショート動画/スマホ) / a4=A4縦(書籍・印刷資料)' },
|
|
46
46
|
purpose: { type: 'string', enum: ['document', 'lecture', 'vsl', 'ad', 'free'], description: '用途(省略時 document)' },
|
|
47
47
|
theme: { type: 'string', description: 'デザインテーマID(省略時 light-clean)' },
|
|
48
48
|
instructions: { type: 'string', description: '追加指示(例: 経営者向けのトーンで・料金比較の表を入れて)' },
|
package/domains/video.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// 動画編集ドメイン(docs/VIDEO_PLAN.md Phase 2・v1.71.0
|
|
1
|
+
// 動画編集ドメイン(docs/VIDEO_PLAN.md Phase 2・v1.71.0〜/§19 F4 で12ツールへ拡張)
|
|
2
2
|
// スライドデッキから「要素の段階出現・切替アニメ付き」のスライド動画タイムラインを組む機能。
|
|
3
3
|
// 大原則: サーバーが持つのはタイムラインJSONのみ。音声/動画の実データ・mp4書き出しはユーザーPC側(編集画面 /video/<ID>)。
|
|
4
4
|
// → Claude Code / Desktop は手元の音声の文字起こし・SRT・台本を自分で読み、発話タイミングに合わせて
|
|
@@ -6,10 +6,22 @@
|
|
|
6
6
|
// ※ プランopt-inの機能(未解放プランでは403)。
|
|
7
7
|
const { callApi } = require('../lib/api');
|
|
8
8
|
|
|
9
|
+
// 保存系の応答に付く検証結果を人間にもAIにも読める形で出す(errors が残っている=直す必要がある)
|
|
10
|
+
function lintLines(d) {
|
|
11
|
+
const out = [];
|
|
12
|
+
for (const e of d.errors || []) out.push(` ❌ ${e.where ? `${e.where}: ` : ''}${e.message}`);
|
|
13
|
+
for (const w of d.warnings || []) out.push(` ⚠️ ${w.where ? `${w.where}: ` : ''}${w.message}`);
|
|
14
|
+
if (out.length === 0) return '';
|
|
15
|
+
const head = (d.errors || []).length > 0
|
|
16
|
+
? `\n⚠️ 修正が必要な点が ${(d.errors || []).length} 件あります(このままでは意図どおりに動きません):`
|
|
17
|
+
: '\n参考(品質のヒント):';
|
|
18
|
+
return `${head}\n${out.slice(0, 25).join('\n')}${out.length > 25 ? `\n …ほか${out.length - 25}件(lint_video_timeline で全件確認できます)` : ''}`;
|
|
19
|
+
}
|
|
20
|
+
|
|
9
21
|
const tools = [
|
|
10
22
|
{
|
|
11
23
|
name: 'get_video_timeline_spec',
|
|
12
|
-
description: '動画タイムライン(timeline JSON)の仕様を取得します。クリップ形式・transition/animの語彙・reveals
|
|
24
|
+
description: '動画タイムライン(timeline JSON)の仕様を取得します。クリップ形式・transition/animの語彙・reveals(要素の段階出現)の組み方・メディアの結びつけ方・用途別の尺の目安・音声同期のコツ。動画を作る前に必ず一度読んでください。',
|
|
13
25
|
annotations: { readOnlyHint: true },
|
|
14
26
|
inputSchema: { type: 'object', properties: {}, required: [] },
|
|
15
27
|
},
|
|
@@ -21,44 +33,122 @@ const tools = [
|
|
|
21
33
|
},
|
|
22
34
|
{
|
|
23
35
|
name: 'get_video_project',
|
|
24
|
-
description: '動画プロジェクトの内容を取得します。timeline=タイムラインJSON・slides=参照デッキの各スライド情報(title・note=ナレーション原稿・reveal_paths=段階出現できる要素の一覧(path
|
|
36
|
+
description: '動画プロジェクトの内容を取得します。timeline=タイムラインJSON・tracks_summary=トラック要約・slides=参照デッキの各スライド情報(title・note=ナレーション原稿・reveal_paths=段階出現できる要素の一覧(path と人間向けラベル)・available_levels=選べる粒度)。タイムラインを編集するときは reveal_paths の path をそのまま reveals に使ってください。更新時の競合を避けるため、応答の updated_at を update_video_project の base_updated_at に渡すことを推奨します。',
|
|
25
37
|
annotations: { readOnlyHint: true },
|
|
26
38
|
inputSchema: { type: 'object', properties: {
|
|
27
39
|
id: { type: 'string', description: 'プロジェクトID(list_video_projectsで確認)' },
|
|
40
|
+
reveal_level: { type: 'string', enum: ['group', 'item', 'text'], description: '返す reveal_paths の細かさ。group=まとめて(表全体・カードの行ごと)/ item=項目ごと(既定)/ text=テキストごと(Q&Aの質問だけ→回答だけ、カード内の見出し/説明/価格)。各スライドの available_levels に選べる粒度が入ります' },
|
|
28
41
|
}, required: ['id'] },
|
|
29
42
|
},
|
|
30
43
|
{
|
|
31
44
|
name: 'create_video_project',
|
|
32
|
-
description:
|
|
33
|
-
|
|
34
|
-
|
|
45
|
+
description: `動画プロジェクトを新規作成します。作り方は2通り:
|
|
46
|
+
① deck_id を渡す(スライド動画): note(ナレーション原稿)の分量比で尺を自動配分し、要素の段階出現も設定した初期タイムラインを作ります。
|
|
47
|
+
② timeline を直接渡す(撮影動画+テロップなど、スライドを使わない動画): deck_id は不要です。
|
|
48
|
+
作成後の流れ: ①このツール ②lint_video_timeline で検証 ③ユーザーが編集画面(/video/<ID>)で音声・動画ファイルを選択し、プレビュー確認して mp4 書き出し(すべてPC内処理)。
|
|
49
|
+
手元に音声の文字起こし(タイムスタンプ付き)がある場合は total_seconds に音声の長さを渡し、その後 update_video_project で各クリップの duration / reveals.at を発話に合わせると音声同期動画になります。`,
|
|
35
50
|
annotations: { destructiveHint: false },
|
|
36
51
|
inputSchema: { type: 'object', properties: {
|
|
37
|
-
deck_id: { type: 'string', description: '元スライドデッキID(list_slide_decks
|
|
52
|
+
deck_id: { type: 'string', description: '元スライドデッキID(list_slide_decksで確認)。timeline を直接渡す場合は不要' },
|
|
38
53
|
title: { type: 'string', description: '動画タイトル(省略時はデッキ名から自動)' },
|
|
39
54
|
total_seconds: { type: 'number', description: '動画の総尺(秒)。音声の長さが分かっていれば渡す(省略時は枚数×8秒)' },
|
|
40
|
-
|
|
55
|
+
timeline: { type: 'object', description: 'タイムラインJSONを直接指定(形式は get_video_timeline_spec)。スライドを使わない動画はこちら' },
|
|
56
|
+
}, required: [] },
|
|
41
57
|
},
|
|
42
58
|
{
|
|
43
59
|
name: 'update_video_project',
|
|
44
|
-
description: '動画プロジェクトを更新します(title / timeline)。timeline は get_video_timeline_spec の形式で全置換。既存の timeline は get_video_project で取得し、必要箇所だけ変えて渡してください(クリップの start
|
|
60
|
+
description: '動画プロジェクトを更新します(title / timeline / deck_id)。timeline は get_video_timeline_spec の形式で全置換。既存の timeline は get_video_project で取得し、必要箇所だけ変えて渡してください(クリップの start は隙間なく連続させること)。音声/映像の実データはPC側のため、audio / video トラックは既存の内容を維持して渡すこと。1トラックだけ直す場合は patch_video_track の方が安全で軽量です。応答には検証結果(errors / warnings / stats)が含まれるので、errors が空であることを必ず確認してください。',
|
|
45
61
|
annotations: { destructiveHint: false },
|
|
46
62
|
inputSchema: { type: 'object', properties: {
|
|
47
63
|
id: { type: 'string', description: 'プロジェクトID' },
|
|
48
64
|
title: { type: 'string' },
|
|
49
65
|
timeline: { type: 'object', description: 'タイムラインJSON(全置換・形式は get_video_timeline_spec)' },
|
|
66
|
+
deck_id: { type: 'string', description: '参照スライドデッキの差し替え。スライドを作り直した場合はここで新しいデッキIDを指定し、timeline 側の各クリップの deckId も同じ値に揃えてください(尺やタイミングはそのまま保てます)' },
|
|
67
|
+
base_updated_at: { type: 'string', description: 'get_video_project で取得した updated_at。渡すと、その後にユーザーが編集画面で保存していた場合に上書きせずエラーを返します(推奨)' },
|
|
50
68
|
}, required: ['id'] },
|
|
51
69
|
},
|
|
70
|
+
{
|
|
71
|
+
name: 'lint_video_timeline',
|
|
72
|
+
description: 'タイムラインの品質チェック(保存はしません)。保存は「形が壊れていないか」しか見ないため、打点のpathが存在しない・スライドに隙間がある・テロップが画面外にはみ出す・音声とスライドの長さが合わない、といった不具合があっても成功が返ります。作成/更新のあとは必ずこれで確認し、errors が空になるまで直してください。',
|
|
73
|
+
annotations: { readOnlyHint: true },
|
|
74
|
+
inputSchema: { type: 'object', properties: {
|
|
75
|
+
id: { type: 'string', description: 'プロジェクトID' },
|
|
76
|
+
purpose: { type: 'string', enum: ['ad', 'vsl', 'lecture', 'doc'], description: '用途。渡すと尺の規範(広告3〜10秒/VSL8〜25秒/講座15〜45秒 など)もチェックします' },
|
|
77
|
+
}, required: ['id'] },
|
|
78
|
+
// 保存系(create / update / auto_build / ai_build / import_srt / set_media / patch_track)の応答にも
|
|
79
|
+
// 同じ errors / warnings / stats が入る。lint はそれを保存せずに確認したいときに使う。
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: 'set_video_media',
|
|
83
|
+
description: '素材(ナレーション音声・BGM・撮影動画・画像)をタイムラインに登録します。ファイル名と長さを伝えるだけで全長クリップを1本作ります。⚠️ 実データはユーザーのPC内にしかないため、file_name はユーザーが編集画面で選ぶ実ファイル名と完全に一致させてください(一致するとAIが書いたカット・配置・音量がそのまま生きます)。長さが分からない場合はユーザーに聞くか、文字起こしの最終時刻を使ってください。⚠️ 同じ素材のトラックが既にある場合、そのクリップ(=カット編集)は全部消えて全長1本に置き換わります。既存のカットを残したまま直したいときは patch_video_track を使ってください(応答の replaced_clips に、置き換えで捨てたクリップ数が入ります)。',
|
|
84
|
+
annotations: { destructiveHint: true },
|
|
85
|
+
inputSchema: { type: 'object', properties: {
|
|
86
|
+
id: { type: 'string', description: 'プロジェクトID' },
|
|
87
|
+
type: { type: 'string', enum: ['audio', 'video', 'image'], description: 'audio=音声 / video=撮影動画 / image=画像' },
|
|
88
|
+
role: { type: 'string', enum: ['voice', 'bgm'], description: 'audio のとき: voice=ナレーション(既定)/ bgm=BGM' },
|
|
89
|
+
file_name: { type: 'string', description: 'ユーザーのPC上の実ファイル名(例: narration.mp3)' },
|
|
90
|
+
duration_sec: { type: 'number', description: '素材の長さ(秒)。audio / video では必須' },
|
|
91
|
+
start: { type: 'number', description: 'タイムライン上の配置位置(秒・省略=0)' },
|
|
92
|
+
gain: { type: 'number', description: '音量(1=100%・BGMは0.3程度)' },
|
|
93
|
+
muted: { type: 'boolean', description: 'video のとき true でその動画の音を使わない' },
|
|
94
|
+
media_id: { type: 'string', description: '複数の素材を使い分けるときの識別子(省略時は type から自動)' },
|
|
95
|
+
base_updated_at: { type: 'string', description: '競合防止(get_video_project の updated_at)' },
|
|
96
|
+
}, required: ['id', 'type', 'file_name'] },
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: 'import_srt_telops',
|
|
100
|
+
description: '字幕ファイル(SRT)の内容からテロップを一括生成してタイムラインに追加します。発話より少し先行して出す・長い行を自動で改行する処理込み。撮影動画+テロップの動画を作るときの本命ツールです。前の字幕と重ならないよう先行時間は自動で調整されます(調整した件数は応答のメッセージに出ます)。',
|
|
101
|
+
annotations: { destructiveHint: false },
|
|
102
|
+
inputSchema: { type: 'object', properties: {
|
|
103
|
+
id: { type: 'string', description: 'プロジェクトID' },
|
|
104
|
+
srt: { type: 'string', description: 'SRTファイルの中身(そのまま貼る)' },
|
|
105
|
+
style: { type: 'string', enum: ['shadow', 'band-dark', 'band-white', 'accent'], description: '見た目(省略=shadow: 白文字+黒フチ)' },
|
|
106
|
+
font: { type: 'string', description: 'フォント(noto-sans / biz-ud / mplus-rounded / zen-kaku / shippori-mincho / dela-gothic)' },
|
|
107
|
+
pos: { type: 'string', enum: ['bottom', 'center', 'top'], description: '表示位置(省略=bottom)' },
|
|
108
|
+
lead_sec: { type: 'number', description: '発話より何秒早く出すか(既定0.4)' },
|
|
109
|
+
max_chars: { type: 'number', description: '1行の最大文字数。超えたら自動で改行する(既定20)' },
|
|
110
|
+
replace: { type: 'boolean', description: 'true=既存のテロップを置き換える(省略=追加)' },
|
|
111
|
+
base_updated_at: { type: 'string', description: '競合防止(get_video_project の updated_at)' },
|
|
112
|
+
}, required: ['id', 'srt'] },
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: 'patch_video_track',
|
|
116
|
+
description: '1つのトラックだけを差し替えます(タイムライン全体を送り直さなくて済むので安全・軽量)。テロップだけ直す・BGMだけ足す、といった部分更新に使ってください。',
|
|
117
|
+
annotations: { destructiveHint: false },
|
|
118
|
+
inputSchema: { type: 'object', properties: {
|
|
119
|
+
id: { type: 'string', description: 'プロジェクトID' },
|
|
120
|
+
type: { type: 'string', enum: ['slides', 'audio', 'video', 'image', 'telop'], description: '対象トラックの種類' },
|
|
121
|
+
role: { type: 'string', description: '同じ種類が複数あるときの絞り込み(audio の voice / bgm)' },
|
|
122
|
+
media_id: { type: 'string', description: '同じ種類が複数あるときの絞り込み(mediaId)' },
|
|
123
|
+
clips: { type: 'array', items: { type: 'object' }, description: 'そのトラックのクリップ配列(全置換)。形式は get_video_timeline_spec' },
|
|
124
|
+
remove: { type: 'boolean', description: 'true=このトラックを削除する' },
|
|
125
|
+
base_updated_at: { type: 'string', description: '競合防止(get_video_project の updated_at)' },
|
|
126
|
+
}, required: ['id', 'type'] },
|
|
127
|
+
},
|
|
52
128
|
{
|
|
53
129
|
name: 'auto_build_video_timeline',
|
|
54
|
-
description: 'タイムラインを自動で組み直します(参照デッキの note
|
|
130
|
+
description: 'タイムラインを自動で組み直します(参照デッキの note 分量比で尺配分+要素出現を等間隔設定)。purpose を渡すと用途別の尺規範(広告3〜10秒/VSL8〜25秒/講座15〜45秒・冒頭30秒は1枚10秒以内)を反映します。総尺を変えたいとき・手動編集をやり直したいときに。音声・テロップ・映像トラックは維持されます。',
|
|
55
131
|
annotations: { destructiveHint: true },
|
|
56
132
|
inputSchema: { type: 'object', properties: {
|
|
57
133
|
id: { type: 'string', description: 'プロジェクトID' },
|
|
58
134
|
total_seconds: { type: 'number', description: '動画の総尺(秒・省略時は枚数×8秒)' },
|
|
135
|
+
purpose: { type: 'string', enum: ['ad', 'vsl', 'lecture', 'doc'], description: '用途。尺の目安と冒頭のテンポに反映されます' },
|
|
136
|
+
min_slide_sec: { type: 'number', description: '1枚の最短秒数(purpose より優先)' },
|
|
137
|
+
max_slide_sec: { type: 'number', description: '1枚の最長秒数(purpose より優先)' },
|
|
138
|
+
opening_fast: { type: 'boolean', description: '冒頭30秒を1枚10秒以内にする(purpose 指定時は既定ON)' },
|
|
59
139
|
with_reveals: { type: 'boolean', description: 'false=要素の段階出現を付けない(省略=付ける)' },
|
|
60
140
|
}, required: ['id'] },
|
|
61
141
|
},
|
|
142
|
+
{
|
|
143
|
+
name: 'ai_build_video_timeline',
|
|
144
|
+
description: 'AIが各スライドの内容とナレーションを読んで、尺の重み・切替・出現アニメを判断してタイムラインを構成します(組み立て自体は決定的なコードが行うため形が壊れません)。「いい感じに構成して」のような曖昧な依頼はまずこれを使い、細部は update_video_project / patch_video_track で調整してください。ユーザーの音声カット編集は維持されます。',
|
|
145
|
+
annotations: { destructiveHint: true },
|
|
146
|
+
inputSchema: { type: 'object', properties: {
|
|
147
|
+
id: { type: 'string', description: 'プロジェクトID' },
|
|
148
|
+
total_seconds: { type: 'number', description: '動画の総尺(秒・省略時は枚数×8秒)' },
|
|
149
|
+
instruction: { type: 'string', description: '演出の指示(例: 切替はフェード中心で落ち着いた雰囲気に/数値スライドは長めに強調)' },
|
|
150
|
+
}, required: ['id'] },
|
|
151
|
+
},
|
|
62
152
|
{
|
|
63
153
|
name: 'delete_video_project',
|
|
64
154
|
description: '動画プロジェクトを削除します(タイムライン定義のみ削除・元スライドや手元の音声ファイルは消えません)。',
|
|
@@ -79,21 +169,44 @@ const handlers = {
|
|
|
79
169
|
if (!rows.length) return '動画プロジェクトはまだありません。create_video_project で作成できます。';
|
|
80
170
|
return rows.map(r => `- ${r.title || '無題'}${r.deck_title ? `(元: ${r.deck_title})` : ''}\n ID: ${r.id} / 更新: ${r.updated_at}`).join('\n');
|
|
81
171
|
},
|
|
82
|
-
get_video_project: async ({ id }) => {
|
|
83
|
-
const
|
|
172
|
+
get_video_project: async ({ id, reveal_level }) => {
|
|
173
|
+
const q = reveal_level ? `?reveal_level=${encodeURIComponent(reveal_level)}` : '';
|
|
174
|
+
const r = await callApi(`/video/${id}${q}`);
|
|
84
175
|
return JSON.stringify(r, null, 2);
|
|
85
176
|
},
|
|
86
177
|
create_video_project: async (args) => {
|
|
87
178
|
const d = await callApi('/video', { method: 'POST', body: JSON.stringify(args) });
|
|
88
|
-
return `✅ ${d.message}\nID: ${d.id}\nタイトル: ${d.title}\n編集画面: ${d.edit_url}\n
|
|
179
|
+
return `✅ ${d.message}\nID: ${d.id}\nタイトル: ${d.title}\n編集画面: ${d.edit_url}\n(音声・動画ファイルの選択、プレビュー、mp4書き出しはユーザーが編集画面で行います)${lintLines(d)}`;
|
|
89
180
|
},
|
|
90
181
|
update_video_project: async ({ id, ...rest }) => {
|
|
91
182
|
const d = await callApi(`/video/${id}`, { method: 'PATCH', body: JSON.stringify(rest) });
|
|
92
|
-
return `✅ ${d.message}\nID: ${d.id}`;
|
|
183
|
+
return `✅ ${d.message}\nID: ${d.id}\n更新日時: ${d.updated_at}${lintLines(d)}`;
|
|
184
|
+
},
|
|
185
|
+
lint_video_timeline: async ({ id, purpose }) => {
|
|
186
|
+
const q = purpose ? `?purpose=${encodeURIComponent(purpose)}` : '';
|
|
187
|
+
const d = await callApi(`/video/${id}/lint${q}`);
|
|
188
|
+
const head = d.ok ? '✅ 問題は見つかりませんでした' : `❌ 修正が必要な点が ${d.errors.length} 件あります`;
|
|
189
|
+
return `${head}\n\n【統計】${JSON.stringify(d.stats)}${lintLines(d) || '\n(警告なし)'}`;
|
|
190
|
+
},
|
|
191
|
+
set_video_media: async ({ id, ...rest }) => {
|
|
192
|
+
const d = await callApi(`/video/${id}/media`, { method: 'POST', body: JSON.stringify(rest) });
|
|
193
|
+
return `✅ ${d.message}\n更新日時: ${d.updated_at}${lintLines(d)}`;
|
|
194
|
+
},
|
|
195
|
+
import_srt_telops: async ({ id, ...rest }) => {
|
|
196
|
+
const d = await callApi(`/video/${id}/import-srt`, { method: 'POST', body: JSON.stringify(rest) });
|
|
197
|
+
return `✅ ${d.message}\n更新日時: ${d.updated_at}${lintLines(d)}`;
|
|
198
|
+
},
|
|
199
|
+
patch_video_track: async ({ id, ...rest }) => {
|
|
200
|
+
const d = await callApi(`/video/${id}/track`, { method: 'PATCH', body: JSON.stringify(rest) });
|
|
201
|
+
return `✅ ${d.message}\n更新日時: ${d.updated_at}${lintLines(d)}`;
|
|
93
202
|
},
|
|
94
203
|
auto_build_video_timeline: async ({ id, ...rest }) => {
|
|
95
204
|
const d = await callApi(`/video/${id}/auto-build`, { method: 'POST', body: JSON.stringify(rest) });
|
|
96
|
-
return `✅ ${d.message}`;
|
|
205
|
+
return `✅ ${d.message}${lintLines(d)}`;
|
|
206
|
+
},
|
|
207
|
+
ai_build_video_timeline: async ({ id, ...rest }) => {
|
|
208
|
+
const d = await callApi(`/video/${id}/ai-build`, { method: 'POST', body: JSON.stringify(rest) });
|
|
209
|
+
return `✅ ${d.message}(${d.slide_count}枚 / ${Math.round(d.total_seconds)}秒)\nID: ${d.id}`;
|
|
97
210
|
},
|
|
98
211
|
delete_video_project: async ({ id }) => {
|
|
99
212
|
const d = await callApi(`/video/${id}`, { method: 'DELETE' });
|
package/lib/api.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const API_KEY = process.env.OCR_API_KEY;
|
|
4
|
-
|
|
4
|
+
// ⚠️ 既定は必ずサービスの正式ドメイン。以前は Railway の生URLが既定だったため、
|
|
5
|
+
// OCR_BASE_URL を設定し損ねた利用者が「サービスのURLではない場所」へ接続していた
|
|
6
|
+
// (配布物 manifest.json / install.ps1 / 案内はすべて api.ownercloneai.com 指定済み)。
|
|
7
|
+
const BASE_URL = (process.env.OCR_BASE_URL || 'https://api.ownercloneai.com').replace(/\/$/, '');
|
|
5
8
|
|
|
6
9
|
async function callApi(path, options = {}) {
|
|
7
10
|
const url = `${BASE_URL}/api/mcp/v1${path}`;
|