@gitruck/cli 1.3.15 → 1.3.17
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/AGENT.md +40 -10
- package/CHANGELOG.md +1262 -1231
- package/README.en.md +1 -1
- package/README.md +1 -1
- package/assets/composite-kit/kit.css +66 -57
- package/assets/composite-kit/stage.html +164 -18
- package/dist/index.js +653 -343
- package/docs/reference.en.md +866 -852
- package/docs/reference.md +909 -895
- package/docs/workflow.en.md +4 -3
- package/docs/workflow.md +4 -3
- package/package.json +1 -1
- package/skills/gtrk-ai-drama/SKILL.md +7 -7
- package/skills/gtrk-composite/SKILL.md +428 -222
- package/skills/gtrk-composite/references/fullscreen-card-migration.md +99 -0
- package/skills/gtrk-food-recap/SKILL.md +6 -3
- package/skills/gtrk-live-slicing/SKILL.md +9 -6
- package/skills/gtrk-long2short/SKILL.md +3 -2
- package/skills/gtrk-matrix/SKILL.md +9 -9
- package/skills/gtrk-mg/SKILL.md +62 -48
- package/skills/gtrk-music-visualizer/SKILL.md +1 -1
- package/skills/gtrk-narration/SKILL.md +15 -8
- package/skills/gtrk-oralcut/SKILL.md +1 -1
- package/skills/gtrk-splitter/SKILL.md +116 -24
- package/skills/gtrk-splitter/references/example-visual-split.json +34 -13
- package/skills/gtrk-splitter/references/example-visual-split.md +28 -5
- package/skills/gtrk-splitter/references/field-schema.md +88 -3
- package/skills/gtrk-style-maker/SKILL.md +8 -4
- package/skills/gtrk-style-maker/references/seeds/seed-ecom-home-goods.md +2 -2
- package/skills/gtrk-style-maker/references/seeds/seed-psych-humanities.md +1 -1
- package/skills/gtrk-talking-head/SKILL.md +26 -20
- package/skills/gtrk-tools/SKILL.md +1 -1
- package/skills/gtrk-transcript/SKILL.md +1 -1
- package/skills/gtrk-travel-recap/SKILL.md +36 -28
- package/skills/gtrk-vlog-docu/SKILL.md +41 -33
- package/skills/gtrk-voiceover/SKILL.md +19 -11
package/docs/reference.en.md
CHANGED
|
@@ -1,852 +1,866 @@
|
|
|
1
|
-
# Agent, configuration and command reference
|
|
2
|
-
|
|
3
|
-
Local visual handoff for `matrix describe`: `--prepare <project-directory>` writes a review job with source fingerprints, timestamps and image hashes, without calling Doubao. The current agent inspects the images, fills the response, then imports it with the same `--materials` or `--plan` arguments and `--review <visual-review.json>`. Only items explicitly marked unavailable with a reason fall back to Doubao. Missing answers, changed sources and mismatched criteria fail before cloud requests. This is an agent workflow, not a form the user must fill. Fully local completion requires no API key; cloud fallback requires configuration.
|
|
4
|
-
|
|
5
|
-
Video overviews cover each scene at intervals of at most six seconds. `describe --materials <video> --source-window <start,end>` inspects only that source window at intervals of at most two seconds and supports prepare/review. Images have no temporal window. Plan mode still describes each candidate's best frame; a frame is not evidence of an entire action. Indexing uses six-second cells for stable scenes and retains two-second sampling for other long scenes. Explicit indexing refreshes old stable materials with insufficient coverage and reports the extra work.
|
|
6
|
-
|
|
7
|
-
[Back to README](../README.en.md) · [Workflow](workflow.en.md) · [简体中文](reference.md)
|
|
8
|
-
|
|
9
|
-
## Using it with AI agents
|
|
10
|
-
|
|
11
|
-
Once installed, a single sentence in any agent invokes a gtrk skill:
|
|
12
|
-
|
|
13
|
-
| | |
|
|
14
|
-
|:--:|:--:|
|
|
15
|
-
|  |  |
|
|
16
|
-
|  |  |
|
|
17
|
-
|
|
18
|
-
`gtrk install` installs the 20 bundled CLI skills (`gtrk-oralcut`·`gtrk-long2short`·`gtrk-splitter`·`gtrk-matrix`·`gtrk-mg`·`gtrk-composite`·`gtrk-ai-drama`·`gtrk-style-maker`·`gtrk-transcript`·`gtrk-tools`·`gtrk-music-visualizer`·`gtrk-cover`·`gtrk-travel-recap`·`gtrk-live-slicing`·`gtrk-talking-head`·`gtrk-narration`·`gtrk-voiceover`·`gtrk-food-recap`·`gtrk-vlog-docu`·`gtrk-ref-reading`) into the agents detected on this machine. The mechanism matches lark-cli: gtrk hands its local skill sources to the generic `skills` CLI, which owns agent detection, directory mapping and update rules; gtrk no longer hardcodes per-vendor paths.
|
|
19
|
-
|
|
20
|
-
By default `~/.agents/skills` is the single source of truth, linked into each agent's compatible directory (junctions on Windows); where linking is unavailable the adapter falls back to copying. That way updates touch one canonical copy instead of letting duplicates drift apart. Common commands:
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
# 自动探测已安装的 Agent(等价核心:npx -y skills add <gtrk包根>/skills -g -y)
|
|
24
|
-
gtrk skills install
|
|
25
|
-
|
|
26
|
-
# 只装指定宿主;这里使用通用 skills CLI 的 Agent ID
|
|
27
|
-
gtrk skills install --agents codex,cursor,gemini-cli,trae-cn
|
|
28
|
-
|
|
29
|
-
# 安装到适配器当前支持的全部 Agent(会创建较多宿主目录)
|
|
30
|
-
gtrk skills install --all
|
|
31
|
-
|
|
32
|
-
# 不使用链接,每个宿主各复制一份
|
|
33
|
-
gtrk skills install --copy
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
> ⚠️ **Upgrading the CLI does not refresh the skills you already installed.**
|
|
37
|
-
> `npm i -g @gitruck/cli@latest` swaps the CLI package only; the copy under each agent's directory is still
|
|
38
|
-
> **the snapshot from your last install** — the agent keeps working from the stale wording, **and nothing errors out**.
|
|
39
|
-
> Refresh with `gtrk upgrade` (CLI + skills) or run `gtrk skills install` on its own.
|
|
40
|
-
>
|
|
41
|
-
> Since **1.1.3** this is no longer silent: the skill-backed commands (`oralcut`, `long2short`, `split`,
|
|
42
|
-
> `matrix`, `mg`, `subtitle`, `project`) print a one-off notice on **stderr** with the fix command when they
|
|
43
|
-
> detect that the installed skills lag behind the package; when they match, or cannot be judged, output is
|
|
44
|
-
> **empty**. Run `gtrk doctor` any time for the "Skill freshness" row, or set
|
|
45
|
-
> `GTRK_SKILL_FRESHNESS=off` to silence the whole thing.
|
|
46
|
-
|
|
47
|
-
`--agents` accepts agent IDs from both the upstream adapter and the gtrk supplement layer. Chinese agents already covered include `trae`, `trae-cn`, `codebuddy`, `qoder`, `qoder-cn`, `qwen-code`, `kimi-code-cli`, `iflow-cli`, `codearts-agent` and `lingma`, plus `workbuddy`, `qoderwork` and `comate` which upstream has not registered yet. Common shorthands — `qwen`, `kimi`, `iflow`, `codearts`, `tongyi-lingma`, `qoder-work`, `baidu-comate` — are mapped automatically. When upstream adds new agents, gtrk can use the new IDs without a release; if an existing script must hardcode a directory, `--dir <skills dir>` still gives you the compatible copy mode.
|
|
48
|
-
|
|
49
|
-
**Agent input UIs are not standardized**: Claude usually surfaces skill names in `/` completion; different Codex clients enter via `$`, `/skills` or a Skills panel; TRAE relies mostly on Skills settings, explicit naming or semantic triggering. So not seeing a Claude-style `/gtrk-*` dropdown does not mean the skill is missing. If a new skill does not show up, refresh the window or start a new session.
|
|
50
|
-
|
|
51
|
-
Then just say "**cut a version of this talking-head**", or explicitly pick `gtrk-oralcut` from your agent's Skills entry point. The agent will ask about the raw file, script and pacing, call `gtrk oralcut --json` to run the loop, verify the artifacts and tell you how to open all three formats. The full portable playbook is in [`AGENT.md`](../AGENT.md).
|
|
52
|
-
|
|
53
|
-
**Hand the whole chain to the agent**: it is not just the talking-head cut — keep going with "split the storyboard", "lay the B-roll", "lay the MG particles", "render the video", and the agent will pair each show-specific production skill with `gtrk split` / `gtrk matrix` / `gtrk mg` / `gtrk render` to run the entire **production pipeline**. **You just talk; leave the CLI typing to the agent** — the "Command reference" below exists so the agent can look up parameters, not so you type them in a terminal.
|
|
54
|
-
|
|
55
|
-
### Capabilities agents can drive (skill drives command)
|
|
56
|
-
|
|
57
|
-
**Each capability = one skill (the brain — you trigger it, it knows its place in the SOP and handles interaction) driving one gtrk command (the hands — deterministic mechanical work).** Production is an **ordered SOP with a user checkpoint at every step**, not a one-shot parallel fan-out — a `/gtrk-X` skill runs `gtrk X` at the right moment, with your confirmation:
|
|
58
|
-
|
|
59
|
-
| SOP | Driving skill (what you say) | Underlying command (what the agent runs) | What it does |
|
|
60
|
-
|:--:|---|---|---|
|
|
61
|
-
| ① | `/gtrk-oralcut` | `gtrk oralcut` | Smart talking-head cut → desktop client / Jianying / Premiere projects + transcript |
|
|
62
|
-
| ② | `/gtrk-splitter` | `gtrk split` | Storyboard dispatch → `dispatch.json` (A_ROLL/MG/AI_DRAMA/FILM_BROLL, four lanes) |
|
|
63
|
-
| ③ | `/gtrk-matrix` | `gtrk matrix` | **B-roll base · film/local-footage leg**: lays candidate tracks → **you adjust/choose** (toggle visibility in opencut) |
|
|
64
|
-
| ③ | `/gtrk-ai-drama` | `gtrk ai-drama validate` (check storyboard drafts) · `lay` / `pack` / `swap` (re-insert) | **B-roll base · AI scene-clip leg (same stage as matrix, not last)**: emits four-part description docs (backstory / characters / shots / source text, in Chinese and English blocks) → generate on any external platform and re-insert by hand (the artifact is description text with no mechanical tail, same as `/gtrk-style-maker`: skill only, no command) |
|
|
65
|
-
| ④ | (no skill) | (no command) | **Global frame-sampling composition check**: sample frames from the merged three-source base layer and have the user confirm the composition — a hard agent-discipline gate feeding
|
|
66
|
-
| ⑤ |
|
|
67
|
-
| ⑥ | `/gtrk-composite` | `gtrk composite` | **Composite layer** (after subtitles, before
|
|
68
|
-
|
|
|
69
|
-
|
|
|
70
|
-
|
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
|
|
|
75
|
-
|
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
| 🧭 | `/gtrk-
|
|
79
|
-
| 🧭 | `/gtrk-
|
|
80
|
-
| 🧭 | `/gtrk-
|
|
81
|
-
| 🧭 | `/gtrk-
|
|
82
|
-
| 🧭 | `/gtrk-
|
|
83
|
-
| 🧭 | `/gtrk-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
>
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
-
|
|
103
|
-
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
| `
|
|
122
|
-
|
|
|
123
|
-
|
|
|
124
|
-
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
✅
|
|
137
|
-
✅
|
|
138
|
-
✅
|
|
139
|
-
✅
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
- `gtrk
|
|
224
|
-
- `gtrk
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
|
232
|
-
|
|
|
233
|
-
| `--
|
|
234
|
-
| `--
|
|
235
|
-
| `--online-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
gtrk transcript "D:/素材/采访视频.mp4"
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
| `
|
|
266
|
-
| `
|
|
267
|
-
| `
|
|
268
|
-
| `
|
|
269
|
-
| `
|
|
270
|
-
| `
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
gtrk media tiles "reference.mp4" --
|
|
275
|
-
gtrk media
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
- **
|
|
280
|
-
- **
|
|
281
|
-
- **
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
| `
|
|
291
|
-
| `
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
gtrk client
|
|
296
|
-
gtrk client
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
- `
|
|
303
|
-
-
|
|
304
|
-
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
| `-
|
|
312
|
-
| `-
|
|
313
|
-
| `-
|
|
314
|
-
|
|
|
315
|
-
| `--
|
|
316
|
-
| `--
|
|
317
|
-
| `--
|
|
318
|
-
| `--
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
|
334
|
-
| `--
|
|
335
|
-
| `--
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
| `--
|
|
347
|
-
| `--
|
|
348
|
-
| `--
|
|
349
|
-
| `--
|
|
350
|
-
| `--
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
>
|
|
354
|
-
>
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
gtrk patch
|
|
371
|
-
gtrk patch
|
|
372
|
-
gtrk patch
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
|
381
|
-
|
|
382
|
-
| `--
|
|
383
|
-
| `--
|
|
384
|
-
| `--
|
|
385
|
-
|
|
|
386
|
-
| `--
|
|
387
|
-
| `--
|
|
388
|
-
| `--
|
|
389
|
-
| `--
|
|
390
|
-
| `--
|
|
391
|
-
| `--
|
|
392
|
-
| `--
|
|
393
|
-
| `--
|
|
394
|
-
| `--
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
>
|
|
402
|
-
>
|
|
403
|
-
>
|
|
404
|
-
>
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
gtrk matrix source-import
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
gtrk matrix status
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
|
455
|
-
|
|
456
|
-
| `
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
|
470
|
-
|
|
471
|
-
| `--
|
|
472
|
-
| `--
|
|
473
|
-
| `--
|
|
474
|
-
| `--
|
|
475
|
-
| `--
|
|
476
|
-
| `--
|
|
477
|
-
| `--
|
|
478
|
-
| `--
|
|
479
|
-
| `--
|
|
480
|
-
| `--
|
|
481
|
-
| `--
|
|
482
|
-
| `--
|
|
483
|
-
| `--
|
|
484
|
-
| `--
|
|
485
|
-
| `--
|
|
486
|
-
| `--
|
|
487
|
-
| `--
|
|
488
|
-
| `--
|
|
489
|
-
| `--
|
|
490
|
-
| `--
|
|
491
|
-
| `--
|
|
492
|
-
| `--
|
|
493
|
-
| `--
|
|
494
|
-
| `--
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
| `--
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
>
|
|
505
|
-
>
|
|
506
|
-
>
|
|
507
|
-
>
|
|
508
|
-
>
|
|
509
|
-
>
|
|
510
|
-
>
|
|
511
|
-
>
|
|
512
|
-
>
|
|
513
|
-
>
|
|
514
|
-
>
|
|
515
|
-
>
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
- **
|
|
531
|
-
- **
|
|
532
|
-
- **
|
|
533
|
-
- **
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
>
|
|
541
|
-
|
|
542
|
-
>
|
|
543
|
-
>
|
|
544
|
-
>
|
|
545
|
-
>
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
|
559
|
-
|
|
560
|
-
| `--
|
|
561
|
-
| `--
|
|
562
|
-
| `--
|
|
563
|
-
| `--
|
|
564
|
-
| `--
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
- **
|
|
572
|
-
- **
|
|
573
|
-
- **
|
|
574
|
-
- **
|
|
575
|
-
- **
|
|
576
|
-
- **
|
|
577
|
-
- **
|
|
578
|
-
- **
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
gtrk composite status
|
|
595
|
-
|
|
596
|
-
gtrk composite
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
gtrk composite
|
|
600
|
-
gtrk composite
|
|
601
|
-
gtrk composite
|
|
602
|
-
gtrk composite
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
- `
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
`project init`
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
gtrk project
|
|
644
|
-
gtrk project
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
`--
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
|
714
|
-
|
|
715
|
-
| `
|
|
716
|
-
| `
|
|
717
|
-
| `
|
|
718
|
-
| `
|
|
719
|
-
| `
|
|
720
|
-
| `
|
|
721
|
-
| `
|
|
722
|
-
| `
|
|
723
|
-
| `
|
|
724
|
-
| `
|
|
725
|
-
| `
|
|
726
|
-
| `
|
|
727
|
-
| `
|
|
728
|
-
| `
|
|
729
|
-
| `
|
|
730
|
-
| `
|
|
731
|
-
| `
|
|
732
|
-
| `
|
|
733
|
-
| `
|
|
734
|
-
| `
|
|
735
|
-
| `
|
|
736
|
-
| `
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
- `gtrk tool
|
|
758
|
-
- `gtrk tool
|
|
759
|
-
- `gtrk tool
|
|
760
|
-
- `gtrk tool
|
|
761
|
-
- `gtrk tool
|
|
762
|
-
- `gtrk tool
|
|
763
|
-
- `gtrk tool
|
|
764
|
-
- `gtrk tool
|
|
765
|
-
- `gtrk tool
|
|
766
|
-
- `gtrk tool
|
|
767
|
-
-
|
|
768
|
-
- `gtrk tool
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
- `gtrk tool
|
|
772
|
-
- `gtrk tool
|
|
773
|
-
- `gtrk tool
|
|
774
|
-
- `gtrk tool
|
|
775
|
-
- `gtrk tool
|
|
776
|
-
- `gtrk tool
|
|
777
|
-
- `gtrk tool
|
|
778
|
-
- `gtrk tool
|
|
779
|
-
- `gtrk tool
|
|
780
|
-
- `gtrk tool
|
|
781
|
-
-
|
|
782
|
-
- `gtrk tool
|
|
783
|
-
- `gtrk tool
|
|
784
|
-
- `gtrk tool
|
|
785
|
-
- `gtrk tool
|
|
786
|
-
- `gtrk tool
|
|
787
|
-
- `gtrk tool
|
|
788
|
-
-
|
|
789
|
-
-
|
|
790
|
-
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
The
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
- `gtrk
|
|
847
|
-
- `gtrk
|
|
848
|
-
- `gtrk
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
`gtrk
|
|
1
|
+
# Agent, configuration and command reference
|
|
2
|
+
|
|
3
|
+
Local visual handoff for `matrix describe`: `--prepare <project-directory>` writes a review job with source fingerprints, timestamps and image hashes, without calling Doubao. The current agent inspects the images, fills the response, then imports it with the same `--materials` or `--plan` arguments and `--review <visual-review.json>`. Only items explicitly marked unavailable with a reason fall back to Doubao. Missing answers, changed sources and mismatched criteria fail before cloud requests. This is an agent workflow, not a form the user must fill. Fully local completion requires no API key; cloud fallback requires configuration.
|
|
4
|
+
|
|
5
|
+
Video overviews cover each scene at intervals of at most six seconds. `describe --materials <video> --source-window <start,end>` inspects only that source window at intervals of at most two seconds and supports prepare/review. Images have no temporal window. Plan mode still describes each candidate's best frame; a frame is not evidence of an entire action. Indexing uses six-second cells for stable scenes and retains two-second sampling for other long scenes. Explicit indexing refreshes old stable materials with insufficient coverage and reports the extra work.
|
|
6
|
+
|
|
7
|
+
[Back to README](../README.en.md) · [Workflow](workflow.en.md) · [简体中文](reference.md)
|
|
8
|
+
|
|
9
|
+
## Using it with AI agents
|
|
10
|
+
|
|
11
|
+
Once installed, a single sentence in any agent invokes a gtrk skill:
|
|
12
|
+
|
|
13
|
+
| | |
|
|
14
|
+
|:--:|:--:|
|
|
15
|
+
|  |  |
|
|
16
|
+
|  |  |
|
|
17
|
+
|
|
18
|
+
`gtrk install` installs the 20 bundled CLI skills (`gtrk-oralcut`·`gtrk-long2short`·`gtrk-splitter`·`gtrk-matrix`·`gtrk-mg`·`gtrk-composite`·`gtrk-ai-drama`·`gtrk-style-maker`·`gtrk-transcript`·`gtrk-tools`·`gtrk-music-visualizer`·`gtrk-cover`·`gtrk-travel-recap`·`gtrk-live-slicing`·`gtrk-talking-head`·`gtrk-narration`·`gtrk-voiceover`·`gtrk-food-recap`·`gtrk-vlog-docu`·`gtrk-ref-reading`) into the agents detected on this machine. The mechanism matches lark-cli: gtrk hands its local skill sources to the generic `skills` CLI, which owns agent detection, directory mapping and update rules; gtrk no longer hardcodes per-vendor paths.
|
|
19
|
+
|
|
20
|
+
By default `~/.agents/skills` is the single source of truth, linked into each agent's compatible directory (junctions on Windows); where linking is unavailable the adapter falls back to copying. That way updates touch one canonical copy instead of letting duplicates drift apart. Common commands:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# 自动探测已安装的 Agent(等价核心:npx -y skills add <gtrk包根>/skills -g -y)
|
|
24
|
+
gtrk skills install
|
|
25
|
+
|
|
26
|
+
# 只装指定宿主;这里使用通用 skills CLI 的 Agent ID
|
|
27
|
+
gtrk skills install --agents codex,cursor,gemini-cli,trae-cn
|
|
28
|
+
|
|
29
|
+
# 安装到适配器当前支持的全部 Agent(会创建较多宿主目录)
|
|
30
|
+
gtrk skills install --all
|
|
31
|
+
|
|
32
|
+
# 不使用链接,每个宿主各复制一份
|
|
33
|
+
gtrk skills install --copy
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
> ⚠️ **Upgrading the CLI does not refresh the skills you already installed.**
|
|
37
|
+
> `npm i -g @gitruck/cli@latest` swaps the CLI package only; the copy under each agent's directory is still
|
|
38
|
+
> **the snapshot from your last install** — the agent keeps working from the stale wording, **and nothing errors out**.
|
|
39
|
+
> Refresh with `gtrk upgrade` (CLI + skills) or run `gtrk skills install` on its own.
|
|
40
|
+
>
|
|
41
|
+
> Since **1.1.3** this is no longer silent: the skill-backed commands (`oralcut`, `long2short`, `split`,
|
|
42
|
+
> `matrix`, `mg`, `subtitle`, `project`) print a one-off notice on **stderr** with the fix command when they
|
|
43
|
+
> detect that the installed skills lag behind the package; when they match, or cannot be judged, output is
|
|
44
|
+
> **empty**. Run `gtrk doctor` any time for the "Skill freshness" row, or set
|
|
45
|
+
> `GTRK_SKILL_FRESHNESS=off` to silence the whole thing.
|
|
46
|
+
|
|
47
|
+
`--agents` accepts agent IDs from both the upstream adapter and the gtrk supplement layer. Chinese agents already covered include `trae`, `trae-cn`, `codebuddy`, `qoder`, `qoder-cn`, `qwen-code`, `kimi-code-cli`, `iflow-cli`, `codearts-agent` and `lingma`, plus `workbuddy`, `qoderwork` and `comate` which upstream has not registered yet. Common shorthands — `qwen`, `kimi`, `iflow`, `codearts`, `tongyi-lingma`, `qoder-work`, `baidu-comate` — are mapped automatically. When upstream adds new agents, gtrk can use the new IDs without a release; if an existing script must hardcode a directory, `--dir <skills dir>` still gives you the compatible copy mode.
|
|
48
|
+
|
|
49
|
+
**Agent input UIs are not standardized**: Claude usually surfaces skill names in `/` completion; different Codex clients enter via `$`, `/skills` or a Skills panel; TRAE relies mostly on Skills settings, explicit naming or semantic triggering. So not seeing a Claude-style `/gtrk-*` dropdown does not mean the skill is missing. If a new skill does not show up, refresh the window or start a new session.
|
|
50
|
+
|
|
51
|
+
Then just say "**cut a version of this talking-head**", or explicitly pick `gtrk-oralcut` from your agent's Skills entry point. The agent will ask about the raw file, script and pacing, call `gtrk oralcut --json` to run the loop, verify the artifacts and tell you how to open all three formats. The full portable playbook is in [`AGENT.md`](../AGENT.md).
|
|
52
|
+
|
|
53
|
+
**Hand the whole chain to the agent**: it is not just the talking-head cut — keep going with "split the storyboard", "lay the B-roll", "lay the MG particles", "render the video", and the agent will pair each show-specific production skill with `gtrk split` / `gtrk matrix` / `gtrk mg` / `gtrk render` to run the entire **production pipeline**. **You just talk; leave the CLI typing to the agent** — the "Command reference" below exists so the agent can look up parameters, not so you type them in a terminal.
|
|
54
|
+
|
|
55
|
+
### Capabilities agents can drive (skill drives command)
|
|
56
|
+
|
|
57
|
+
**Each capability = one skill (the brain — you trigger it, it knows its place in the SOP and handles interaction) driving one gtrk command (the hands — deterministic mechanical work).** Production is an **ordered SOP with a user checkpoint at every step**, not a one-shot parallel fan-out — a `/gtrk-X` skill runs `gtrk X` at the right moment, with your confirmation:
|
|
58
|
+
|
|
59
|
+
| SOP | Driving skill (what you say) | Underlying command (what the agent runs) | What it does |
|
|
60
|
+
|:--:|---|---|---|
|
|
61
|
+
| ① | `/gtrk-oralcut` | `gtrk oralcut` | Smart talking-head cut → desktop client / Jianying / Premiere projects + transcript |
|
|
62
|
+
| ② | `/gtrk-splitter` | `gtrk split` | Storyboard dispatch → `dispatch.json` (A_ROLL/MG/AI_DRAMA/FILM_BROLL, four lanes, plus `layouts` — the layout windows handed to compositing) |
|
|
63
|
+
| ③ | `/gtrk-matrix` | `gtrk matrix` | **B-roll base · film/local-footage leg**: lays candidate tracks → **you adjust/choose** (toggle visibility in opencut) |
|
|
64
|
+
| ③ | `/gtrk-ai-drama` | `gtrk ai-drama validate` (check storyboard drafts) · `lay` / `pack` / `swap` (re-insert) | **B-roll base · AI scene-clip leg (same stage as matrix, not last)**: emits four-part description docs (backstory / characters / shots / source text, in Chinese and English blocks) → generate on any external platform and re-insert by hand (the artifact is description text with no mechanical tail, same as `/gtrk-style-maker`: skill only, no command) |
|
|
65
|
+
| ④ | (no skill) | (no command) | **Global frame-sampling composition check**: sample frames from the merged three-source base layer and have the user confirm the composition — a hard agent-discipline gate feeding the composite's footage choices and the overlays' placement |
|
|
66
|
+
| ⑤ | (no skill) | `gtrk subtitle lay` | **Subtitles**: style from the kickoff / checkpoint decision; compositing reads the subtitle input, so subtitles come first |
|
|
67
|
+
| ⑥ | `/gtrk-composite` | `gtrk composite` | **Composite layer (layout)** (after subtitles, before `gtrk mg`): turn chosen time windows into composite particles — one code particle takes over the whole frame for that span (picture changes per sentence, side-by-side contrasts, list cards, subtitle layout) while the talking head, B-roll and images are drawn into its slots; four entry modes (take the layout windows from the storyboard / cover the whole film / let the AI pick / user-given ranges), candidates show up in the client outline's CP row; purely local, zero billing. On export, `gtrk composite bake` bakes them into video locally (the first run needs `gtrk deps install --browser`) |
|
|
68
|
+
| ⑦ | `/gtrk-mg` | `gtrk mg` | **Overlays** (after compositing; overlay slots lying entirely inside a composite window are taken over by it and are neither produced nor laid; full-screen cards now belong to compositing, and full-screen slots in older dispatches are still made as before) |
|
|
69
|
+
| — | `/gtrk-style-maker` | (no command, builds a show) | A one-time interview that builds your show's style system (skill family + show config, see next section) |
|
|
70
|
+
| 🔍 | `/gtrk-ref-reading` | `gtrk transcript` + `gtrk media` | **Reference reading**: someone else's video → word-level transcript + frame grids labelled with the spoken line + key motion frame by frame → records, system by system, which line each design event answers, in `ANALYSIS.md` / `TIMELINE.md` / `PROGRESS.md`; hand the result to `/gtrk-style-maker` to build a show. The viewing commands are local and free (only the transcription step is billed); **not part of the production SOP** |
|
|
71
|
+
| ③′ | "**screen-recording PiP**" | `gtrk pip lay` | Mirror the talking-head rough cut's cut points onto a screen recording / second camera recorded in sync: lays a full-frame companion track + a muted picture-in-picture copy of the talking head (ellipse / rounded rectangle / heart / diamond / star mask, optional corner radius); purely local, zero billing; when alignment confidence is low it writes an alignment project for the client to drag into place, then `--resume` |
|
|
72
|
+
| — | (wrap-up) | `gtrk render` | Render a gtrk project locally → finished mp4 (overlays and MG particles included; particles that miss the cache are cloud-rendered and billed, `--no-particles` skips them) |
|
|
73
|
+
| ✂️ | `/gtrk-long2short` | `gtrk long2short` | Long-to-short rough cut: semantic segment selection + jump cuts → per-clip client/Jianying/Premiere projects (the raw file is never uploaded); **not part of the production SOP**, usable standalone at any time |
|
|
74
|
+
| 📝 | `/gtrk-transcript` | `gtrk transcript` | Local video / voice-over audio → one Markdown file with an agent-written summary, timecoded record and plain text; **not part of the production SOP** |
|
|
75
|
+
| 🧰 | `/gtrk-tools` | `gtrk tool <name>` | The single-shot tool family (image-to-camera-move / image & video matting …) — single request, single result, **not part of the production SOP**, usable standalone at any time |
|
|
76
|
+
| 🎵 | `/gtrk-music-visualizer` | `gtrk music-visualizer` | One song → a spectrum-visualizer video (template + optional background/cover + colour styling), **not part of the production SOP**, used standalone for audience acquisition |
|
|
77
|
+
| 🖼️ | `/gtrk-cover` | `gtrk cover embed` (compress background images into the workbench; purely local, zero billing) | The two-stage cover workbench: design diagnosis + text-to-image prompts in three sizes and two languages → you generate images on an external platform → an HTML5 typesetting workbench (drag/scroll fine-tuning, one-click export to multiple PNG sizes). Show-specific cover aesthetics are injected through the show config's `style.skills` (`produces:"cover"`); **not part of the production SOP** (it is the "stage zero" companion to distribution) |
|
|
78
|
+
| 🧭 | `/gtrk-talking-head` | orchestrates `gtrk audio` → `oralcut` → `split` → `matrix` → `subtitle lay` → `composite` → `mg` → `audio lay` | **Talking-head chain blueprint**: one or more on-camera raw takes → external audio aligned and swapped in, multi-take stitching, rough cut, dispatch, B-roll / MG cards, BGM, subtitles → a client-ready project |
|
|
79
|
+
| 🧭 | `/gtrk-travel-recap` | orchestrates `gtrk tool audio_tts_clone` → `project init` → `split` → `matrix` → `subtitle lay` → `composite` → `mg` → `audio lay` | **Travel-recap blueprint**: a folder of travel footage → the AI reads the footage, writes a three-act narration, you confirm once → voice-over / project / dispatch / B-roll / cards / BGM / subtitles run unattended → a client-ready project |
|
|
80
|
+
| 🧭 | `/gtrk-live-slicing` | orchestrates `gtrk long2short` (very long replays are segmented first) | **Live-stream slicing blueprint**: a multi-hour replay → segmentation (server-side 2 h hard limit) → topic list confirmed → a batch of per-clip rough-cut projects (gtrk + Jianying + Premiere), split-screen matched to the picture |
|
|
81
|
+
| 🧭 | `/gtrk-narration` | orchestrates `gtrk transcript` → `project init` → `split` → `matrix` → `subtitle lay` → `composite` → `mg` → `audio lay` | **General narration blueprint (canonical for the narration chain)**: something long that carries its own timeline (a feature film, gameplay, a restaurant visit …) → distil the outline and highlights → retell it concisely as a narration project; travel recap and food recap are its vertical instances |
|
|
82
|
+
| 🧭 | `/gtrk-voiceover` | orchestrates `gtrk tool audio_tts_clone` → `project init` → `split` → `matrix` → `subtitle lay` → `composite` → `mg` → `audio lay` | **Voice-over chain quick preset**: a finished script (or one the AI writes) → voice-over → automatic visuals → cards / BGM / subtitles → a client-ready project; for material with no timeline of its own (explainers, emotional radio, opinion pieces, product copy, round-ups) |
|
|
83
|
+
| 🧭 | `/gtrk-food-recap` | follows the `/gtrk-narration` chain | **Food-recap vertical blueprint (narration-chain example)**: a restaurant-visit / fly-on-the-wall long take or a cooking-process recording → distil the highlights and retell it as a Chinese food-narration project |
|
|
84
|
+
| 🧭 | `/gtrk-vlog-docu` | orchestrates `gtrk transcript` → `tool audio_tts_clone` → `split` → `matrix` → `subtitle lay` → `composite` → `mg` → `audio lay` | **Documentary-vlog blueprint**: a batch of on-location footage → footage understanding, register choice and script, one sign-off → live-sound skeleton + narration voice-over + B-roll + subtitle layer + BGM run unattended → a client-ready project; alternates on-location sound with post-production narration, unlike the pure talking-head or pure voice-over chains |
|
|
85
|
+
|
|
86
|
+
> **Skill vs command**: `/gtrk-mg` is the **brain** — it knows it belongs at SOP step ⑦ (MG only after all three B-roll sources have landed, the composition is checked, and subtitles and compositing are in place; slots taken over by a composite are not produced), asks for your confirmation, and resolves which particle type to produce from the show config; `gtrk mg` is the **hands** — purely deterministic lint + track laying. You trigger the skill by talking, and the skill runs the command for you.
|
|
87
|
+
> The 20 `/gtrk-X` skills above are **framework skills bundled with the CLI** (installed by `gtrk skills install`; the list is identical to the ones in "Using it with AI agents" and "Layout") — the 7 marked 🧭 are **composite blueprints** (one sentence runs a whole chain; they only orchestrate the single-command skills above and add no commands of their own); `/gtrk-long2short` independently drives long-to-short, `/gtrk-transcript` independently drives video/audio-to-transcript, `/gtrk-tools` covers only the single-shot tool family, `/gtrk-cover` handles covers, `/gtrk-ref-reading` handles reference reading, and none of the five belong to the production SOP; `/gtrk-style-maker` is a pure authoring skill (no command), while `/gtrk-ai-drama`·`/gtrk-cover` are mostly authoring and only run commands for mechanical steps such as validation and image embedding. Show-specific **visual style and content** come instead from your own show's production skills (created by `/gtrk-style-maker`, bound through the show config's `style.skills`) and are never hardcoded into these framework skills.
|
|
88
|
+
|
|
89
|
+
**How each lane's actual visuals/content get produced** — what the MG looks like, what tone the AI re-enactment has — is not hardcoded into the CLI. It comes from **your own show's production skills** (created interactively with `/gtrk-style-maker`, kept locally). They are bound through the show config's **`style.skills[].produces`** (the value is the lane name), and **general-purpose drivers** such as `gtrk mg` / `gtrk matrix` consume them accordingly. **The direction is: the CLI drives the show skills** — show skills only supply style/content and carry no "which command to run" orchestration; the framework only knows lanes and pipeline interfaces, and the look always belongs to your show. Without a show, the built-in defaults are used and everything still runs end to end.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Shows and style: a two-layer structure
|
|
94
|
+
|
|
95
|
+
> **The show config is remodelling your kitchen; producing a video is cooking dinner. You do not remodel the kitchen before every dish, but every dish is indeed cooked in the kitchen you remodelled.**
|
|
96
|
+
|
|
97
|
+
The system has two layers on completely different time scales:
|
|
98
|
+
|
|
99
|
+
**[Show layer · one-time / infrequent] = building a show (remodelling the kitchen)**
|
|
100
|
+
Run `/gtrk-style-maker` (a meta skill). It uses a heuristic interview to help you work out **your own** visual grammar — presupposing no dimensions at all: it does not assume you have a narrative structure, a thematic system, or a split between animation and live action. Your dimensions and their values are entirely yours to define. It produces:
|
|
101
|
+
|
|
102
|
+
- Your own executable skill family (written into the current agent's user-level skills directory; a black box, kept local)
|
|
103
|
+
- A vocabulary shared inside the show (referenced by every skill in the family, preventing drift between multiple definitions)
|
|
104
|
+
- The show config `~/.gitruck/columns/<id>.json` (vocabulary + B-roll retrieval preferences + a list of style references)
|
|
105
|
+
|
|
106
|
+
**[Production layer · every video] = cooking (the shape of the flow never changes)**
|
|
107
|
+
Cut the talking-head → split the script → dispatch (B-roll retrieval / motion graphics / re-enactment) → assemble → render. Every step explicitly consumes the current show config: script splitting validates against your vocabulary (`--column <id>` or the config's `defaultColumn`), B-roll retrieval follows your show's retrieval preferences (`broll.column_tag_ids` show tags / `material_class_policy` / facets), and each lane goes through your own production skills.
|
|
108
|
+
|
|
109
|
+
**No show configured? Use the default "kitchen".** Zero config = the built-in default show; everything runs end to end, byte-for-byte identical to the behaviour before show configs existed — the show layer is an optional asset, not a mandatory gate.
|
|
110
|
+
|
|
111
|
+
**Pipeline contract**: the framework presupposes nothing about aesthetics and is fully authoritative about pipeline interfaces. Skills whose artifacts enter the render pipeline must satisfy the corresponding contract (see [`contracts/`](../contracts/README.md), e.g. `gsap-emit v1` for HTML animation particles); a contract only constrains machine-decidable pipeline properties, and what the picture looks like is always yours.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Configuration
|
|
116
|
+
|
|
117
|
+
`gtrk init` writes config to `~/.gitruck/config.json` (a unified user-level directory — config, caches, ffmpeg and show configs all live under `~/.gitruck/`). Resolution order: **environment variables / `.env` > persisted `init` config > default base URL**.
|
|
118
|
+
|
|
119
|
+
| Item | Source | Notes |
|
|
120
|
+
|---|---|---|
|
|
121
|
+
| `GITRUCK_API_KEY` | env / init | The **bare value** of the `Authorization` header (not a Bearer token). To get one: open https://cloud.ai-mcn.tv/zh-CN, click 注册 / 登录 (Sign up / Log in; logging in creates the account), then copy the API key from the dashboard (仪表盘) |
|
|
122
|
+
| `GITRUCK_API_BASE` | env / init | API base URL, defaults to `https://api.ai-mcn.tv:10000` |
|
|
123
|
+
| Jianying draft folder | init / auto-detect / `--jianying-draft-dir` | Determines where Jianying drafts land and whether they open directly |
|
|
124
|
+
| `defaultColumn` | hand-written in config.json | Default show config id (used by `gtrk split` when `--column` is omitted; if that is also missing, the built-in default show) |
|
|
125
|
+
| Show config | `~/.gitruck/columns/<id>.json` | One file per show; generated and registered by `/gtrk-style-maker`, or hand-written |
|
|
126
|
+
|
|
127
|
+
Non-interactive configuration (scripts / CI):
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
gtrk init --api-key <KEY> --jianying-draft-dir auto -y
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Run `gtrk doctor` any time for a self-check:
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
✅ 运行时:node v24.x
|
|
137
|
+
✅ CLI 版本:v0.3.0(已是最新)
|
|
138
|
+
✅ API Key:已配(gc_xxx…)
|
|
139
|
+
✅ 云端连通 + 鉴权:可达,鉴权通过
|
|
140
|
+
✅ 剪映草稿目录:C:\Users\…\com.lveditor.draft
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Enum catalog (`--refresh-catalog`)
|
|
144
|
+
|
|
145
|
+
`gtrk doctor` shows an “enum catalog” row: the CLI fetches the **complete set of public enum values**
|
|
146
|
+
from the server (subtitle styles and colours, language codes, project formats, rhythm presets,
|
|
147
|
+
task availability, …), stores it at `~/.gitruck/catalog.json`, and refreshes it every 24 hours.
|
|
148
|
+
|
|
149
|
+
With it, a bad `--subtitle-type` is rejected **before the upload starts**, with the currently valid
|
|
150
|
+
values listed. When the server adds a new style, you get it without upgrading the CLI.
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
gtrk doctor --refresh-catalog # refetch now, ignoring the 24h freshness window
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Failing to fetch it never blocks you**: the CLI falls back to the last snapshot; with no snapshot at
|
|
157
|
+
all it **skips local validation and submits anyway**, letting the server decide — the server-side
|
|
158
|
+
whitelist is always the single source of truth. Set `GITRUCK_CATALOG_OFFLINE=1` to disable the fetch
|
|
159
|
+
entirely.
|
|
160
|
+
|
|
161
|
+
### Crash reports, and how to turn them off
|
|
162
|
+
|
|
163
|
+
When gtrk crashes (uncaught exception / unhandled promise rejection / a program defect reaching the top-level exit) it automatically sends one report so we can locate the defect. **On by default; you are told once, when you first configure the CLI.**
|
|
164
|
+
|
|
165
|
+
**What is sent, in full**: the error message, the error stack, a source tag (`cli`), the CLI version, how many times this crash accumulated, and — only when the crash happened during a cloud task — that task's ID.
|
|
166
|
+
|
|
167
|
+
**What is never sent**: your media files or their contents, project files and path listings, your scripts, your API key (the key's literal value and any `gc_…`-shaped token are replaced with `<KEY>` before sending), device identifiers, hostname, environment variables.
|
|
168
|
+
|
|
169
|
+
**Only crashes are reported, never expected failures**: missing file, invalid argument, insufficient credits, wrong command usage — none of the errors you can read and act on are ever sent.
|
|
170
|
+
|
|
171
|
+
Three ways to turn it off (any one of them, effective immediately):
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
gtrk init --no-crash-report # persisted in config, off for good
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
GITRUCK_CRASH_REPORT=0 gtrk oralcut a.mp4 # environment variable, off for one run (takes precedence over config)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Or set `"crashReport": false` directly in `~/.gitruck/config.json`.
|
|
182
|
+
|
|
183
|
+
You can check the current state any time: the “崩溃自动上报” row in `gtrk doctor` shows on / off, and which of the two turned it off. With reporting off, the crash presentation and exit code are **exactly the same** as with it on — the switch only controls whether that one report is sent.
|
|
184
|
+
|
|
185
|
+
### Usage statistics, and how to turn them off
|
|
186
|
+
|
|
187
|
+
gtrk sends anonymous usage statistics so we know which commands get used, how often they fail, and how fast new versions roll out. **On by default; you are told once, when you first configure the CLI** (right after the crash-report line).
|
|
188
|
+
|
|
189
|
+
**What is sent per command, in full**: the command name (its registered name, e.g. `matrix.search`, never any argument), success or failure, on failure an error code or category (e.g. `ENOENT`, never the error message), the elapsed-time range, the caller type (a terminal, or an agent name such as `claude-code`), the CLI version, OS and architecture, Node major version, and whether an API key is configured (yes / no only).
|
|
190
|
+
|
|
191
|
+
**What is never sent**: command arguments and option values, file names and paths, media and project contents, your scripts, your API key, error messages, device identifiers, hostname, account information. The statistics service sees your IP address like any network request; it is used only to tell the country or region and is not stored.
|
|
192
|
+
|
|
193
|
+
**It never slows a command down**: when a command finishes, gtrk only appends one line to `~/.gitruck/usage-queue.jsonl`; a background process sends it and the command exits immediately as usual. Anything that can't be sent stays on your machine (up to 200 entries, 7 days) and goes out next time.
|
|
194
|
+
|
|
195
|
+
**Never sent when**: running from source, running unit tests, or the `CI` environment variable is set.
|
|
196
|
+
|
|
197
|
+
Four ways to turn it off (any one of them, effective immediately):
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
gtrk init --no-usage-stats # persisted in config, off for good (also deletes anything not yet sent)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
GITRUCK_USAGE_STATS=0 gtrk patch move … # environment variable, off for one run (takes precedence over config)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
DO_NOT_TRACK=1 gtrk … # the common “do not track” convention works too
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Or set `"usageAnalytics": false` directly in `~/.gitruck/config.json`.
|
|
212
|
+
|
|
213
|
+
You can check the current state any time: the “使用统计” row in `gtrk doctor` shows on / off, which setting turned it off, and whether the current environment sends at all. With statistics off, command output and exit codes are **exactly the same** as with them on.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Command reference
|
|
218
|
+
|
|
219
|
+
Common entry points: `gtrk oralcut` edits talking heads, `gtrk long2short` selects highlights, `gtrk transcript` transcribes media, and `gtrk project init` builds from voiceover. The per-source limit for `oralcut` / `long2short` is 2 hours; split longer replays first, as described in the [workflow guide](workflow.en.md). Use `gtrk <command> --help` for current options.
|
|
220
|
+
|
|
221
|
+
### `gtrk long2short` / `gtrk pip` / `gtrk qc` — Additional commands
|
|
222
|
+
|
|
223
|
+
- `gtrk long2short <input>`: select topics and jump-cut into per-clip gtrk / Jianying / XML projects. `--split-screen` uses a 720p proxy for smart split-screen; `--output-size` selects the aspect ratio; `--subtitle-out` writes captions for each clip; `--speed-factor 0.5–2.0` writes an overall speed change (pitch preserved) into every clip project (no cloud rendering, no extra charge); `--camera-move` has the cloud write push / pull camera moves as scale keyframes on main-track segments (visible and editable in the client and Jianying, not shown by local `gtrk render` or Premiere projects; `clips.md` marks "N camera moves"), and later `gtrk patch` trims / splits keep those keyframes valid. The output root also gets a whole-source transcript `json/transcript.json`, so any clip can get a client caption track: `gtrk subtitle lay --gtrk <clip dir>/gtrk/<project>.gtrk --transcript <output root>/json/transcript.json --language <source language>` (`--language` sets the cloud line-split language, default zh-CN). Run landscape and portrait separately; content determines the number of clips. Before extracting audio it prints the live price and an estimate for this run (stderr; `pricing` in the `--json` root result); to get a quote first for a long source, add `--dry-run` (no extraction, no upload, no charge, no folders). See `gtrk long2short --help` for all options.
|
|
224
|
+
- `gtrk pip lay`: lay a simultaneously recorded screen or second camera against the talking-head cut points. Both sources need shared audio for alignment; low-confidence matches require calibration in the client before resuming. Use `gtrk pip lay --help` for inputs, shapes, positions and offsets.
|
|
225
|
+
- `gtrk qc <video>`: inspect flash frames, black/frozen frames, volume and synchronization. Add `--gtrk` for project context and `--fail-on` for pipeline gating. With `--gtrk`, in-clip jump cuts and severe too-short shots name their beat and slot, and list the beat's unused candidate segments (from the project's `split/broll-plan.json`, steadiest first). Findings locate issues; they do not automatically repair the video.
|
|
226
|
+
|
|
227
|
+
### `gtrk matrix --online` — External-platform search in current source
|
|
228
|
+
|
|
229
|
+
This entry exists in the current development workspace. Check `gtrk matrix --help` for availability in your installed version; cloud availability must also be confirmed.
|
|
230
|
+
|
|
231
|
+
| Option | Purpose and boundary |
|
|
232
|
+
| --- | --- |
|
|
233
|
+
| `--online` | Search external-platform B-roll; supported only for ad-hoc search or dispatch consumption, and mutually exclusive with `--local`. Ad-hoc search requires `--out <result.json>` for results and recovery records; dispatch consumption requires `--project` or `--dispatch`. This submits cloud work, not a purely local operation |
|
|
234
|
+
| `--platforms <list>` | Comma-separated `youtube,vimeo,tiktok,bilibili`; requires `--online`. Defaults to all four registered platforms. Results depend on service and source availability |
|
|
235
|
+
| `--online-session <name>` | Nonempty external-search batch name; requires `--online`. Continue within a batch; changing the name starts a new search and may incur new task charges |
|
|
236
|
+
| `--online-concurrency <n>` | How many external-search needs run at once; requires `--online`. 1–8, default 3. Needs are submitted ahead in dispatch order and still written to the plan in that order; `1` waits for each search before submitting the next |
|
|
237
|
+
|
|
238
|
+
In dispatch consumption, if a round yields **no layable candidates** while the project already has a `split/broll-plan.json` with candidates (for example the previous cloud or local plan), that plan is not overwritten: this round's plan (with per-request errors and review-only candidates) is saved as `split/broll-plan.online-attempt.json`, the `--json` result carries `plan_kept`, and `planPath` still points at the existing plan. The exit code stays non-zero.
|
|
239
|
+
|
|
240
|
+
### `gtrk transcript <local video|voice-over audio>`
|
|
241
|
+
|
|
242
|
+
Turns a local video or voice-over audio file into a multi-level Markdown transcript. It accepts local file paths only: video is extracted — and audio input transcoded — to 16 kHz mono audio on your machine, and only that derivative is uploaded. The original file is never uploaded, and URLs or platform video downloads are not supported.
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
gtrk transcript "D:/素材/采访视频.mp4"
|
|
246
|
+
gtrk transcript "D:/素材/采访视频.mp4" --lang zh-CN --out "D:/文字稿/采访.md" --json
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
By default it produces only `D:/素材/采访视频-transcript.md`, whose structure is fixed:
|
|
250
|
+
|
|
251
|
+
1. `## 总结` (Summary): the CLI marks it as pending, and `/gtrk-transcript` drives the agent to read the full text, generate it and write it back;
|
|
252
|
+
2. `## 文字记录` (Transcript record): readable paragraphs each starting with `[00:01:23]`;
|
|
253
|
+
3. `## 纯文本` (Plain text): the complete recognized text, easy to copy in one go.
|
|
254
|
+
|
|
255
|
+
Live pricing is queried from the website's price table under `asr` before the run; neither the CLI nor the docs store price numbers. With `--json`, stdout contains only `{ok,taskId,fileId,output,transcriptJson,summaryPending}`, where `output` points at that single Markdown file; `summaryPending:true` means `/gtrk-transcript` still needs the agent to write the semantic summary and replace the pending marker in place — the deliverable remains the same single file.
|
|
256
|
+
|
|
257
|
+
> With `--json` it additionally drops a sentence-timecoded `<name>-transcript.json` next to the source file (`utterances[]{id,text,st,ed}` + `material_id` + `text_hash` + `duration`, field-for-field aligned with the transcript structure `gtrk split` consumes), which the `gtrk project init --transcript` fallback path can consume directly. **Do not re-run ASR here on TTS-synthesized voice-overs** — `gtrk project init --tts-task` fetches the server-side sentence timecodes directly, zero ASR and zero extra billing.
|
|
258
|
+
|
|
259
|
+
### `gtrk media <subcommand>` — local footage viewer (evidence for reference reading)
|
|
260
|
+
|
|
261
|
+
Look at any local video by timecode or by spoken line: frame grids labelled with the transcript, frame-by-frame motion, visual-change candidates. **Purely local, free, offline, no API key**; reads local files only and never downloads links. Driven by `/gtrk-ref-reading`; also handy for checking your own renders.
|
|
262
|
+
|
|
263
|
+
| Subcommand | What it does |
|
|
264
|
+
|---|---|
|
|
265
|
+
| `probe <video \| folder>` | Duration, display size (pixel aspect and rotation applied), frame rate and VFR, audio presence. Given a **folder** it looks at that level only (no recursion, hidden files skipped), picks the audio and video files (`mp4 mov mkv avi webm m4v mts` / `wav mp3 m4a flac aac ogg opus`), probes each and sorts by name: `{mode:"probe-dir", files:[{path, kind, duration, codec, width?, height?, fps?, hasAudio}], skipped:[{path, reason}], truncated?}`; a broken file goes to `skipped` without stopping the rest, and only the first 200 are probed |
|
|
266
|
+
| `lines <transcript>` | One line per utterance `u<id> start–end text`; `--find <phrase>` lists every occurrence with word-level times |
|
|
267
|
+
| `frames <video>` | Single frames by `--at` / `--every` / `--frames` / `--every-frame`; with `--transcript` or `--label` a label band is added below each frame |
|
|
268
|
+
| `tile <video>` | One labelled grid (≤60 cells) |
|
|
269
|
+
| `tiles <video>` | Paginated grids (`--cols × --rows`, default 3×3); `--ranges <json>` visits several intervals; `--every-frame` decodes each interval once and keeps every original frame |
|
|
270
|
+
| `boundaries <video>` | Visual-change candidates (`--rate` default 12, `--threshold` default 0.1, `--min-gap` merges neighbours); with `--transcript` each candidate notes which line it falls on. **Mechanical evidence, not shot detection** |
|
|
271
|
+
| `cut <video>` | Saves an evidence clip (`.mp4/.mov/.mkv`, re-encoded). With `--copy` it **stream-copies** instead: no re-encode, seconds for a long raw recording (e.g. splitting raws over 2 hours); the start falls on the last keyframe before `--start`, the receipt's `seconds` is the actual length and its `note` says so; `-o` must keep the source's extension; audio-only sources work too |
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
gtrk media tiles "reference.mp4" --frames 48 --cols 6 --rows 4 --cell 320 --transcript "reading/transcript.json" -o "reading/evidence/overview"
|
|
275
|
+
gtrk media tiles "reference.mp4" --around "can't afford it" --occurrence 1 --every-frame --cols 6 --rows 4 --transcript "reading/transcript.json" -o "reading/evidence/motion/stamp"
|
|
276
|
+
gtrk media boundaries "reference.mp4" --rate 4 --threshold 0.12 --transcript "reading/transcript.json" -o "reading/evidence/boundaries.json"
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
- **Intervals**: `--start/--end` (seconds or `[hh:]mm:ss.mmm`), or `--around <phrase> [--occurrence n] [--padding s]` to locate by the spoken line (needs `--transcript`; a repeated phrase must name its occurrence — `lines --find` lists them).
|
|
280
|
+
- **Transcripts**: the `gtrk transcript --json` output (v1, with word-level times) works as is; `hypit.transcript@1` is also accepted. The transcript must belong to this video — a duration or file-name mismatch prints a warning on stderr.
|
|
281
|
+
- **Labels** (below the picture, so the original captions and graphics stay visible): source seconds · timecode (plus frame number in frame-by-frame mode) · utterance id / the word being spoken with its times / the whole sentence with the current word highlighted. Moments with no timed word are labelled as such, never inferred as silence. Labels are drawn with libass; an ffmpeg without the `ass` filter fails with a pointer to `gtrk deps install --ffmpeg`.
|
|
282
|
+
- **Output**: `-o` is required (except `frames`, which defaults to a new folder under `$GTRK_FRAMES_DIR` when that is set) — nothing lands in the current directory or next to the source; existing paths are never overwritten, and `--force` only replaces this command family's own earlier output. `frames` / `tiles` directories include an `index.json` recording each cell's file, time, word and utterance. Frame-by-frame is capped at 1800 frames per call.
|
|
283
|
+
|
|
284
|
+
### `gtrk client <subcommand>` — read the project as it is in the editor
|
|
285
|
+
|
|
286
|
+
When the desktop client has this project open, reads the **live state** over the local bridge (which segment is selected, the playhead, unsaved edits, the picture the editor shows); otherwise reads the project files or renders a frame locally. Both paths return the same shape and `source` says which one answered. **The client is never required**: not installed, not running or showing another project, all three subcommands still exit successfully.
|
|
287
|
+
|
|
288
|
+
| Subcommand | What it does | `--json` output |
|
|
289
|
+
|---|---|---|
|
|
290
|
+
| `state` | Project summary: clips on every track with their timeline times, project duration; clips on the main track (the one carrying the voice) get a 1-based `no`. Never prints the whole `.gtrk` | `{source:"client"\|"file", project, duration, tracks:[{track, kind, index, main?, clips:[{no?, clip_id, track_st, track_ed, duration, volume?}]}], selection, playhead, viewport}`; the last three are `null` when read from files |
|
|
291
|
+
| `segment --no <N>` | Timeline times and spoken text of main-track segment N (utterances aligned to timeline times exactly as in the `gtrk split` projection view; cut utterances are left out). Out of range exits non-zero and says how many segments there are | `{source, no, clip_id, track_st, track_ed, text}` |
|
|
292
|
+
| `frame --at <sec>` | One composited frame at that timeline moment (`--width` default 768). Rendered by the client it matches the editor; rendered locally it is free and has no MG particles (`note` says so). Past the end it is pinned to the last frame, with a note | `{source:"client"\|"local-render", at, path, width, height, note?}` |
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
gtrk client state --project . --json
|
|
296
|
+
gtrk client segment --no 12 --json
|
|
297
|
+
gtrk client frame --at 31.5 --json # 31.5 s on the timeline, not 31.5 s into the raw footage
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
> When `state` reads the live client it also carries `disk`, a comparison with the project on disk: `{revision, same_layout, unsaved_changes, track_map:[{client, disk, clips}], disk_only}`. Unsaved track additions/removals in the client shift track numbers (e.g. the concept track is `video:2` in the client but `video:1` on disk). `gtrk patch` / `gtrk matrix` edit the project on disk, so **use the `disk` side's track numbers**, or save in the client first; a one-line notice on stderr flags any mismatch.
|
|
301
|
+
|
|
302
|
+
- `--project` defaults to the current directory (`gtrk/project.gtrk` or `project.gtrk`).
|
|
303
|
+
- `frame` writes to `$GTRK_FRAMES_DIR` by default, or `gtrk-frames/<project-path-hash>/frame-<sec>.jpg` under the system temp folder — **never into the project folder** (projects get packed up whole). `-o <file.jpg>` picks the path; an existing file needs `--force`.
|
|
304
|
+
- When the bridge was not used, `--json` carries `bridge:{tried, reason}` (`no_file` / `not_running` / `not_open` / `protocol_too_new` / `protocol_too_old` / `timeout` / …) for troubleshooting; human output says on its first line whether it read files or rendered locally.
|
|
305
|
+
- The bridge: on start the client writes `~/.gitruck/client-bridge.json` (port, token, process id, protocol version) and listens on `127.0.0.1` only; the CLI sends the token and gives each request 10 seconds.
|
|
306
|
+
|
|
307
|
+
### `gtrk oralcut <raw>`
|
|
308
|
+
|
|
309
|
+
| Parameter | Purpose | Default |
|
|
310
|
+
|---|---|---|
|
|
311
|
+
| `-s, --script <file>` | Script txt (cutting against a script is more accurate) | Looks for a `.txt` next to the raw file; otherwise reconstructs the script automatically |
|
|
312
|
+
| `-p, --preset <p>` | Pacing `steady`\|`concise`\|`compact` (loose → tight) | `concise` |
|
|
313
|
+
| `-o, --out <dir>` | Custom output folder | `<raw-name>-video-project-<timestamp>` (`-2`… is appended when the same name is taken within the same second; the Jianying draft folder follows the same rule) |
|
|
314
|
+
| `-f, --formats <list>` | Comma-separated list of the three formats | `gtrk,jianying,xml` |
|
|
315
|
+
| `--jianying-draft-dir <dir>` | Jianying draft root (or `auto`) | Reads the init config / auto-detects |
|
|
316
|
+
| `--reupload` | Force re-upload, ignoring the upload cache | off |
|
|
317
|
+
| `--no-open` | Do not open the output folder when done | **opens automatically by default** |
|
|
318
|
+
| `--json` | Machine-readable: stdout carries only the result JSON (for agents / scripts) | off |
|
|
319
|
+
| `--dry-run` | Probe and quote only (live price + estimate for this run): no extraction, no upload, no charge, no folders created; with `--json`, stdout is a single line `{ ok, dry_run:true, source, duration, pricing }` | off |
|
|
320
|
+
|
|
321
|
+
`--json` output (a single stdout line on success): `{ ok, outDir, files:{gtrk,jianying,xml}, jianyingDraftPath, rendered, report, errors, taskId, fileId, pricing }`; on failure the process exits non-zero, errors go to stderr, and stdout carries no JSON.
|
|
322
|
+
|
|
323
|
+
> **Billing notice**: before extracting audio, the CLI anonymously looks up the live price once and prints a "billing notice" line to stderr (unit price + an estimate for this run based on the source duration; the server's settlement is final). `pricing` in the `--json` result carries the same data. If the price cannot be fetched, the line reads "live price unavailable, the server's settlement is final" and the run continues. `long2short` works the same way.
|
|
324
|
+
|
|
325
|
+
> Every run **always writes a `result.json` into the output folder** (regardless of `--json`), and once submission succeeds it also drops a `task.json` breadcrumb. Even if stdout is lost or the run crashes midway, the report and `taskId` are on disk, and `oralcut-result` below can fetch everything back in seconds without re-running the cloud job.
|
|
326
|
+
|
|
327
|
+
### `gtrk oralcut-result <taskId> --out <dir>`
|
|
328
|
+
|
|
329
|
+
Fetches the report and the three project formats of an **already completed** task by `task_id` (with optional local rendering), **skipping preprocessing / upload / submission / polling** — use it when the report is lost or you want to pull the artifacts again on another machine, without re-running the cloud job.
|
|
330
|
+
|
|
331
|
+
| Parameter | Purpose | Default |
|
|
332
|
+
|---|---|---|
|
|
333
|
+
| `-o, --out <dir>` | Output folder | **Required** (`--out .` = the current directory itself) |
|
|
334
|
+
| `--render` | Additionally render locally (requires the raw file still at the path embedded in gtrk, plus ffmpeg) | off |
|
|
335
|
+
| `--jianying-draft-dir <dir>` | Jianying draft root (or `auto`) | Reads the init config / auto-detects |
|
|
336
|
+
| `--no-open` / `--json` | Same as `oralcut` | — |
|
|
337
|
+
|
|
338
|
+
> Fetching results requires the **same account's** API key that submitted the task (a different account or a deleted task returns `TASK_NOT_FOUND`). The report is stored with the task record and stays available long-term; the underlying artifact files are cleaned up after roughly **60 days**, after which the report is still retrievable but artifact downloads 404 (the command tells you and still writes the report to disk).
|
|
339
|
+
|
|
340
|
+
### `gtrk split [split doc]` — visual split dispatcher
|
|
341
|
+
|
|
342
|
+
Finished cut × transcript projection → beat storyboard. **No positional argument = export the projection view** (projects the current `.gtrk` timeline × transcript into a beat view for splitting/proofreading, without writing back); **with a split doc = validate and land it** (validates the doc's machine contract → projects beat timecodes → atomically writes back `struct_meta.split` and produces the `split/dispatch.json` dispatch list, driving the A_ROLL / MG / AI_DRAMA / FILM_BROLL lanes). Timecodes always belong to the CLI (a split doc only describes "which span does what" and never carries timecodes).
|
|
343
|
+
|
|
344
|
+
| Parameter | Purpose | Default |
|
|
345
|
+
|---|---|---|
|
|
346
|
+
| `--project <dir>` | The oralcut output folder (locates `gtrk/project.gtrk` and `transcript/transcript.json` automatically) | — |
|
|
347
|
+
| `--gtrk <path>` / `--transcript <path>` | Explicit project / transcript paths (fallback for non-standard layouts) | Derived from `--project` |
|
|
348
|
+
| `--column <id>` | Show config id (validates lane / category / produces against your show's vocabulary) | config `defaultColumn` → built-in default show |
|
|
349
|
+
| `--md` | Also render the human-readable `split/visual-split.md` when landing (rendered one-way from the JSON) | off |
|
|
350
|
+
| `--words` | Attach word-level detail in view mode | sentence level only |
|
|
351
|
+
| `--json` | Machine-readable: stdout carries only the result JSON | off |
|
|
352
|
+
|
|
353
|
+
> The landed `dispatch.json` has three queues feeding downstream consumers: `mg` (MG particles) → the `gtrk mg` command, `film_broll` → the `gtrk matrix` command, `ai_drama` → the `/gtrk-ai-drama` skill (which emits four-part description docs in Chinese/English blocks; pure authoring, no command). The companion skill `/gtrk-splitter` produces the split doc.
|
|
354
|
+
>
|
|
355
|
+
> **Layout windows**: the optional top-level key `layouts[]` (`id` / `span` / `visual_job` / `visual_brief` / `slot_hints?`) declares which time windows go to compositing; a window takes no lane. With it, landing also emits a `composite` queue → `gtrk composite plan --mode split`, a `layouts` snapshot in `struct_meta.split` and a "layout windows" section in the readable doc; overlays lying entirely inside a window are never dispatched (particles inside a composite window do not appear in the export; `beats.skipped[]` with reason `covered_by_layout`), and a retired legacy field in the doc only triggers a warning and is ignored. An empty `layouts` array needs a top-level `layout_note`. Old docs without the key behave as before. Field reference: `skills/gtrk-splitter/references/field-schema.md`.
|
|
356
|
+
>
|
|
357
|
+
> **Full-screen cards** (zero-slot layout windows): a window with `zero_slot: true` (optionally `theme` / `bg`) is a title card, chapter card or data card laid out in pure typography with no picture slots; compositing takes it as a zero-slot scene and bakes it locally. It must not carry `slot_hints`, is not warned for being shorter than 5 seconds and does not count toward the 25% density; the beat underneath is dispatched as `A_ROLL`. In older docs, a `lane: MG` beat with a full-screen category (`fullscreen` / `title`, legacy `mg-fullscreen` / `op-ed-title`) is converted into a full-screen card on landing (window `L` + beat id, e.g. `LB07`) and stays out of `dispatch.mg`; the receipt lists each conversion (`layouts.converted` under `--json`), and the dispatch carries `layouts_declared` at the top level (`false` when the doc has no `layouts`: finishing runs `--mode split` first, then `--mode auto`). The storyboard file itself is never rewritten.
|
|
358
|
+
>
|
|
359
|
+
> **Dispatch entries carry their own `span:{from,to}`** (the utterance range that entry covers; `overlay` aux entries carry **their own** span, which may be a sub-range of the main beat's). **`track_st/track_ed` are a snapshot taken at projection time** — `gtrk mg` / `gtrk matrix` **re-project on the spot** when consuming them (see below), so after editing the talking-head track you do **not** need to re-run `gtrk split`; only a change to the split doc itself requires that.
|
|
360
|
+
|
|
361
|
+
### `gtrk patch <move|trim|split|set|add|replace|remove>` — element-level editing (the only way to edit a project)
|
|
362
|
+
|
|
363
|
+
Edit the timecode or parameters of a single clip / gap / particle. **Agents must not hand-edit `.gtrk` JSON** —
|
|
364
|
+
a clip carries **two parallel timecode representations** (`clip_st`+`clip_ed` and `clip_st`+`duration`).
|
|
365
|
+
Changing one without the other is a **silent failure**: the desktop client reads `clip_ed` first while the
|
|
366
|
+
backend does not strictly validate it, so nothing errors out yet the render uses a stale out-point.
|
|
367
|
+
This command handles identity synchronisation + frame alignment + a whole-file check before writing.
|
|
368
|
+
|
|
369
|
+
```bash
|
|
370
|
+
gtrk patch move --project <dir> --clip c2 --to 5.0
|
|
371
|
+
gtrk patch trim --project <dir> --clip c2 --out -1s
|
|
372
|
+
gtrk patch split --project <dir> --clip c2 --cut 5.5
|
|
373
|
+
gtrk patch set --project <dir> --track audio:1 --at 3.0 --volume 0.5
|
|
374
|
+
gtrk patch add --project <dir> --track video:2 --to 263.733 --candidate <clip_id> # put a candidate into a gap
|
|
375
|
+
gtrk patch replace --project <dir> --clip <clip_id> --candidate <clip_id> # swap the source in place
|
|
376
|
+
gtrk patch add --project <dir> --track video:5 --to 263.7 --candidate A --to 266.2 --candidate B # several segments at once
|
|
377
|
+
gtrk patch remove --project <dir> --clip <clip_id> # delete one clip, leave its spot empty
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
| Flag | Purpose | Default |
|
|
381
|
+
|---|---|---|
|
|
382
|
+
| `--project <dir>` / `--gtrk <path>` | Project dir (auto-locates `gtrk/project.gtrk`) or an explicit path | — |
|
|
383
|
+
| `--clip <clip_id>` | Address by id. A video/audio **mirror pair** counts as one editing unit | — |
|
|
384
|
+
| `--track <kind:idx> --at <sec>` | Address by position (`track_st ≤ at < track_ed`). Mutually exclusive with `--clip` | — |
|
|
385
|
+
| `--to <sec\|Nf>` | Target position for `move` / `add` (`add` does not take `--at`: in this command `--at` always means addressing) | — |
|
|
386
|
+
| `--candidate <clip_id>` / `--material <id>` | Source for `add` / `replace`, exactly one: a B-roll candidate (the project candidate pool including neighbours first, then `split/broll-plan.json`) or a video / image material already in `materials` | — |
|
|
387
|
+
| `--beat <id>` | The beat the candidate belongs to (required when the same candidate appears in several beats with different windows) | — |
|
|
388
|
+
| `--from <sec>` | Source in-point for `add` / `replace` (a candidate uses its own source time; external candidates are converted to preview-file time) | Same window as dragging a candidate in the client: centred on `seg.best`, clamped to the material; a material starts at 0 |
|
|
389
|
+
| `--dur <sec\|Nf>` | Duration for `add` | The length of the gap at the target (up to the start of the next element on that track, ending on the same frame number); the candidate's window length when nothing follows |
|
|
390
|
+
| Repeated `--to` … (`add`, several segments) | Each `--to` is one segment; `--candidate` / `--material` / `--track` / `--beat` / `--from` / `--dur` are given once (shared) or as many times as `--to` (paired in order). Prepared once (a material is downloaded once) and written once; with default durations on one track, each segment stops where the next begins. Mismatched counts give `paired_count_mismatch`; mixing `--candidate` and `--material` gives `paired_mixed_source` (use `--ops` for that); a failing segment is reported as "segment N (the N-th --to)" with nothing written. Repeating these flags on other actions gives `repeat_only_on_add` | — |
|
|
391
|
+
| `--in` / `--out` / `--set-in` / `--set-out` / `--slip` | The five `trim` semantics (first two relative, next two absolute, `--slip` shifts only the source window) | — |
|
|
392
|
+
| `--cut <sec\|Nf>` | Cut point for `split`. ⚠️ Distinct from the addressing flag `--at` | — |
|
|
393
|
+
| `--muted` / `--no-muted` / `--volume <gain>` / `--opaque` | Element-level parameters for `set` (`--volume` is linear gain, not dB, and must be > 0; `--volume 0` fails with `volume_zero_use_muted` — use `--muted` to silence). Track mute is a master switch: if the clip's track is muted, `--no-muted` fails with `track_muted_master` — unmute the track's speaker in the client | — |
|
|
394
|
+
| `--audio-fade-in <sec\|Nf>` / `--audio-fade-out <sec\|Nf>` | `set`: audio fade-in / fade-out length (a video clip's own sound or an audio-track clip; particles and gaps are rejected); seconds or frames, whole milliseconds; 0 deletes the key; rejected outright if the two sides together exceed the clip duration (never scaled for you); `trim` / `split` maintain fades automatically | — |
|
|
395
|
+
| `--audio-track <index>` | `set`: move an audio clip onto an existing audio track; timing, material and effective volume / mute are kept, overlaps and track settings that cannot be preserved are rejected, an emptied source track is removed; moving a clip that is audible onto a muted track fails with `audio_track_target_muted` | — |
|
|
396
|
+
| `--total <sec\|Nf\|max>` | Top-level duration for `set` (project-scoped op, mutually exclusive with element addressing) | — |
|
|
397
|
+
| `--ops <file\|->` | Batch transaction: read once, compute all, validate all, write once; any failure writes **nothing** | off |
|
|
398
|
+
| `--dry-run` | Compute and validate only, do not write | off |
|
|
399
|
+
| `--json` | Machine-readable receipt on stdout (human logs go to stderr) | off |
|
|
400
|
+
|
|
401
|
+
> Time literals: seconds (`3.5` / `3.5s`) or frames (`105f`); relative values take a sign (`-1s`).
|
|
402
|
+
>
|
|
403
|
+
> The receipt carries `ops[].resolved`, a locator triple `{track, clip_id, track_st}` — use it on the next
|
|
404
|
+
> round to confirm you are still pointing at the same element.
|
|
405
|
+
> `preexisting[]` lists invariant problems that were **already in the file** (not caused by this run, not
|
|
406
|
+
> blocking); violations caused by this run mean **zero writes and a non-zero exit**.
|
|
407
|
+
>
|
|
408
|
+
> ⚠️ A gap cannot be addressed with `--clip ""`: the contract lets multiple gaps share that value, so it is
|
|
409
|
+
> not an address. Use `--track/--at` instead.
|
|
410
|
+
|
|
411
|
+
**`add` / `replace` (putting candidates on the timeline and swapping sources while fine-editing)**:
|
|
412
|
+
|
|
413
|
+
- When the candidate's material is not yet in `materials`, the preview is downloaded to `assets/broll-preview/` and registered (the same landing code as `gtrk matrix lay`); a registered material is reused, never downloaded again. So right after `matrix source-import` a single `patch add` puts it on the timeline. A failed download writes nothing and exits non-zero (`preview_download_failed`: the candidate URL may have expired — re-run the search / import to refresh); a preview already on disk is kept for next time.
|
|
414
|
+
- `add` only uses existing video tracks; overlapping a non-gap element is refused (`add_overlap`, listing the blockers; when the blocker is a black fill patch it points to `patch replace`); explicit gaps covered by the new clip give way; no ripple, no new tracks. Image candidates are refused (they need a camera-move render first). A source that is too short is clamped with an `add_clamped` warning, never stretched. The new clip's `clip_id` is `<beat>-add-<n>`, it carries no `producer`, and a candidate source gets a solid black `background_fill`.
|
|
415
|
+
- `replace` swaps only `material` and the source window: `clip_id`, track, start, speed, transform, fill, transitions and keyframes stay. If the new material is too short from the in-point, the clip is shortened honestly (`replace_shortened`) — never stretched, start never moved; `producer` is removed so the next `matrix lay` keeps the track as a user track; the old material entry is kept. Mirror pairs (video + mirrored audio) are refused.
|
|
416
|
+
- A candidate that is only in a plan (`split/broll-plan.json` or a layer snapshot) and not in the project's pool is registered into that beat's pool as it goes on the timeline (layer = the plan it came from; a missing beat registration is created from the plan's window), so the client's B-roll panel shows it and can swap it; the receipt carries `source.pooled: {beat, layer}`. Candidates already in the pool are not registered twice.
|
|
417
|
+
- Every change is first computed and validated with declared values; only then is anything landed. `--dry-run` downloads and writes nothing and the receipt carries `would_download`. The op receipt also carries `source` (candidate / material, `material_id`, `landed`: existing / reused / downloaded / registered) and, for `add`, `gaps_consumed`. `--ops` entries have the same shape: `{"action":"add","track":"video:2","to":263.733,"candidate":"…"}`.
|
|
418
|
+
|
|
419
|
+
**`remove` (delete a clip)**: `gtrk patch remove (--clip <id> | --track video:<N> --at <sec>)` deletes one clip (or explicit gap) and leaves its spot empty — later clips do not move (B-roll stays aligned with the voice by its timeline position; close the hole with `patch seal`, move things with `patch move`). A mirrored pair (video + same-id mirrored audio) is deleted together; split ranges on the beat track are refused (`remove_beat_track`); any other flag gives `remove_args`. The material stays registered; transitions that referenced it are maintained before writing (`transition_dropped`). In `--ops`: `{"action":"remove","clip":"…"}`, which can be batched with `add` to "delete, then fill".
|
|
420
|
+
|
|
421
|
+
**Preserving and maintaining transitions** (`transition_in` / `transition_out` / `transition_next`; created in the client — the CLI does not produce transitions in this release and adds no flags):
|
|
422
|
+
|
|
423
|
+
- `split`: the entrance transition stays on the front part; the exit transition and the transition into the next clip go to the back part (`to_clip_id` unchanged); the new cut carries no transition.
|
|
424
|
+
- Every run (a single action or a whole `--ops` batch) maintains the changed tracks once before writing: a dangling `transition_next` is deleted (never re-pointed at the new neighbour), a transition that no longer fits is shortened frame by frame (head first, then tail), and one left under 1 frame is deleted; the receipt's `warnings[]` lists each `transition_dropped` / `transition_shortened`.
|
|
425
|
+
- The granule catalog is fetched at run time from `https://api.ai-mcn.tv:9000/cloud/static/assets/transitions/catalog.json` and cached at `~/.gitruck/cache/transitions/catalog.json` (the shared static-resource cache, also used by the client, refreshed after 24 hours; `composite lay` reads only the cache and never goes online); it is not shipped in the npm package. Offline, with the catalog unavailable, or for a granule missing from it, the transition is kept as is.
|
|
426
|
+
- Pre-existing transition violations unrelated to this edit only go to `preexisting` (`transition_invalid`) and do not block.
|
|
427
|
+
- When a lay command re-lays its own tracks, the number of replaced clips that carried transitions is reported in the log and the `--json` receipt as `replacedTransitionClips`, and each maintenance deletion or shortening is listed in `transitions[]`; `gtrk project export` normalizes the upload body before submitting (the file on disk is untouched; deletions and shortenings go to `result.json` under `transitions`) and prints each cloud `transition_not_carried` warning; `gtrk render` renders hard cuts in this release and counts `transition_not_carried` (`format: "cli_render"`).
|
|
428
|
+
|
|
429
|
+
### `gtrk matrix source-import` — Put selected video URLs into a B-roll beat
|
|
430
|
+
|
|
431
|
+
When the source videos are already known, send them directly to one beat instead of running keyword search:
|
|
432
|
+
|
|
433
|
+
```bash
|
|
434
|
+
gtrk matrix source-import --project <project-dir> --beat B07 --url <video-url> --url <another-url> --json
|
|
435
|
+
gtrk matrix source-import --project <project-dir> --beat B07 --urls links.txt --json
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
Repeat `--url`, or provide one URL per line with `--urls` (1–32 total). Supported pages are HTTPS YouTube, Vimeo, TikTok and bilibili URLs. With `--project`, the CLI only appends candidates to that beat's `struct_meta.broll`; it does not touch the timeline or run `matrix lay`. The complete task receipt is kept under `split/.source-import/`. For an agent or another automation to consume the result without a project, use `--out <result.json>` and omit `--project/--beat`.
|
|
439
|
+
|
|
440
|
+
Each source becomes one low-resolution full-window preview candidate. `source-import` itself does not download the high-resolution source, change the timeline, or create an `online_broll_resolve` task. The client may still open the Trim dialog by double-clicking it, but the selectable range is strictly bounded by that candidate's source window; the pretrim is carried into the timeline when dragged. After the user places the candidate on a track and clicks “Confirm B-roll”, the client submits the selected source window to `online_broll_resolve`; the cloud downloads that high-resolution window and replaces the low-resolution timeline media. `更多外网候选` / `More external candidates` paginates keyword-search tasks only and never treats manually specified sources as another search page.
|
|
441
|
+
|
|
442
|
+
### `gtrk matrix status` — See where a beat stands in one command (read-only)
|
|
443
|
+
|
|
444
|
+
```bash
|
|
445
|
+
gtrk matrix status --project <project-dir> --beat B20 --json
|
|
446
|
+
gtrk matrix status --project <project-dir> --beat B20,B21
|
|
447
|
+
gtrk matrix status --project <project-dir> --json # every B-roll beat, one line each
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
Accepts only `--project` / `--beat` / `--json`. It calls no cloud endpoint, needs no Key and writes no file; it reads the project on disk, not unsaved edits in the client (that is `gtrk client state`'s job). Here `--beat` may list several beats separated by commas; `matrix source-import`'s `--beat` still takes exactly one.
|
|
451
|
+
|
|
452
|
+
With `--beat`, each beat reports:
|
|
453
|
+
|
|
454
|
+
| Field | Content |
|
|
455
|
+
|---|---|
|
|
456
|
+
| `window` | Time window, re-projected on the spot (the same code `gtrk matrix` / `gtrk mg` use); when it falls back to the dispatch snapshot, `source:"dispatch_snapshot"` with a `degraded_reason` |
|
|
457
|
+
| `lane` / `queries` | Lane and dispatch queries |
|
|
458
|
+
| `candidates` | The project candidate pool in compact form: `clip_id`, `type` (online / cloud / local / image), platform and title, score, `seg` window, `review_only`, `preview_landed` (material registered and the file is on disk), `used_by` (clips already using it); no download URLs |
|
|
459
|
+
| `plan` | Total candidates for the beat in `split/broll-plan.json`, how many are not in the pool, and the top 5 by score; `present:false` when there is no plan |
|
|
460
|
+
| `clips` | Clips on every video track that intersect the window: track, `clip_id`, material, start/end, `category` (broll / raw / black_fill / user / a_roll), and whether it carries a producer identity |
|
|
461
|
+
| `gaps` / `black_only` | Spans above the main track with no picture (seams shorter than one frame are ignored); the part of them covered only by black fill patches |
|
|
462
|
+
|
|
463
|
+
Without `--beat`, one line per B-roll beat: window, candidate count, plan candidate count, covered seconds, number and seconds of gaps. Both forms also carry the project `revision` (usable as `gtrk patch --expected-revision`), `main_track`, an overview of every video track `video_tracks[]` (`{track, track_index, main?, verdict, layer?, clips, hidden?}`, ascending, empty tracks included; the human output starts with a "video tracks: …" line — these are the numbers to use with `gtrk patch --track`), the re-projection summary, the strip verdict of each candidate track and `lay.relay_refused` (whether a full re-lay would now be refused with `tracks_edited`). Beats in non-B-roll lanes get only the window, lane and clips. An unknown beat gives `ok:false`, exit code 1, and the list of all known beats.
|
|
464
|
+
|
|
465
|
+
### `gtrk matrix` — B-roll retrieval + candidate track laying
|
|
466
|
+
|
|
467
|
+
**No positional argument = consume the dispatch**: reads the `film_broll` queue from `split/dispatch.json` → dual-endpoint retrieval → produces the candidate list `split/broll-plan.json`, downloads preview proxies, and lays N candidate tracks in the project (open it in opencut and toggle track visibility to compare and choose). **`matrix search "<query>"` = a one-off ad-hoc search** (independent of any dispatch). **`matrix fetch <clip_id...>` = pull raw footage during the fine cut** (project-independent; see below).
|
|
468
|
+
|
|
469
|
+
| Parameter | Purpose | Default |
|
|
470
|
+
|---|---|---|
|
|
471
|
+
| `--project <dir>` | The oralcut output folder (locates `split/dispatch.json` and the artifact destination) | — |
|
|
472
|
+
| `--dispatch <path>` | Explicit `dispatch.json` path | Derived from `--project` |
|
|
473
|
+
| `--column <id>` | Show config id (uses your show's B-roll retrieval preferences: tags / material_class / facets) | config `defaultColumn` → built-in default show |
|
|
474
|
+
| `--lay <n>` | How many candidate tracks to lay (`0` = produce the plan only, lay nothing) | `1` |
|
|
475
|
+
| `--top-k <n>` | Candidate cap per query (overrides the dispatch's shots; server cap is 50) | dispatch value |
|
|
476
|
+
| `--material-class <c>` | Material type `real_shot` \| `concept` (matrix-member endpoint only; overrides the show policy) | show policy |
|
|
477
|
+
| `--neighbors <n>` | Bring back up to n neighboring shots on each side of a matched concept clip, taken from its source film (0–5, matrix-member endpoint only). Results gain `source_ref` (source title, sequence number, start/end in the source; called `source` in the server docs) and `neighbors[]` (with `offset` / `contiguous` / `hit`). `matrix search` prints the run in source order plus a ready-to-run `gtrk matrix fetch` line; dispatch searches write neighbors into the plan and the project, folded in the client panel, and **never auto-laid**. Ignored with a notice on the public endpoint, `--local` and `--online`; invalid values fail before any request | `0` for `matrix search`; `2` for dispatch searches |
|
|
478
|
+
| `--score-floor <f>` | Fill-confidence floor: segments scoring below this are not used and the slot stays empty — in talking-head projects the candidate track **patches empty spots with solid black**. Raising it shrinks the candidate pool, and a span that cannot be filled at all becomes pure black over the talking-head, so check the hole warnings after adjusting | `0.2` |
|
|
479
|
+
| `--black-bed` | Legacy layout: lay one solid black bed track and leave candidate clips without a background fill (for older clients that do not read clip fills); `--no-black-bed` is now the default (no-op) | off |
|
|
480
|
+
| `--force-relay` | Strip and re-lay even when you have already edited a candidate track in the client (by default it refuses and keeps that track) — **this deletes the `broll-raw-*` material registrations of confirmed source clips, orphaning those files on disk** | off |
|
|
481
|
+
| `--out <file>` | Write ad-hoc results to a file; for `matrix fetch`, the raw-footage output directory (never the Jianying draft folder) | stdout / `./matrix-fetch/` |
|
|
482
|
+
| `--arrange <m>` | **B-roll arrangement route** — **picked automatically by material source; you normally do not pass it**: your own local footage → `cloud` (arranged in the cloud, billed by **arrangement volume**, with an estimate and a confirmation prompt first; `--yes` skips). Material from the asset matrix → `local` (arranged on your machine, not billed, unchanged byte for byte). `shadow` is an observation mode: your machine lays as usual while the cloud runs the same arrangement for comparison only. ⚠️ On the local-footage route `--arrange local` is not accepted (passing it is a parameter error), and if the cloud cannot deliver a result the command **fails outright** instead of quietly switching to a different algorithm. It is **not a way to save credits** either — asset-matrix material is billed for search. Both routes cost something; they just cost it at different steps | picked by material source |
|
|
483
|
+
| `--arrange-qc` | **Arrangement-time QC** (off by default): before anything is laid, check each beat's anchor sentence for whether the picture actually shows what the script says; if not, swap candidates and re-arrange, at most 2 rounds, then deliver and report honestly which lines still do not match. Zero rendering throughout — it replaces the "lay → render → look → re-lay → render again" loop. ⚠️ Judging goes through the material-understanding endpoint and is **billed per frame** (1 frame per anchor sentence per round); an estimate and a confirmation prompt come first (`--yes` skips). Orthogonal to `--arrange`: works on both the local and cloud routes | off |
|
|
484
|
+
| `--arrange-cost-cap <n>` | Hard cap on arrangement volume for a single cloud run: over the cap the server **refuses up front** — zero execution, zero charge (it does not cut off midway). Only meaningful with `--arrange shadow\|cloud` | uncapped |
|
|
485
|
+
| `--dump-request <file>` | **For troubleshooting**: write the **exact bytes actually sent** for the cloud arrangement request to this file. The server **does not keep your plan** (only a size summary), so when something goes wrong this file is the only thing that can reproduce the call — just send it to us. ⚠️ It **must not point inside the project directory** (projects get zipped, copied and synced around, and this file contains your beat names and search queries); with `--arrange-qc` each round writes its own file, round N landing at the same name plus `.roundN`. The machine-readable receipt is `lay.arrange_run.dump_request` | not written |
|
|
486
|
+
| `--explain` | **Emit the tuning gauges**: by default the machine-readable accounting gives only the empty-slot count `lay.dedup.emptySlots` (enough to tell whether your material pool is too thin); the rest of the tuning detail (how many of those were caused by window refinement, how many jump-cut waivers were exhausted, how many high-motion / blurry segments were used) sits behind this flag, and the human-readable log follows the same rule. It changes no decision — the project output is byte-for-byte identical | off |
|
|
487
|
+
| `--query <q>` | Search terms for `matrix search`, repeatable: several angles in one run, merged per clip (highest score kept), tagged with `matched_queries`, sorted by score; the receipt gains `queries`. The positional term (the whole string as one term) comes first; online search takes one term per run | — |
|
|
488
|
+
| `--estimate-only` | `matrix search`: report the most this run could cost, without searching — `billing_estimate: {credits, basis}` in `--json` (`credits` is an upper bound at the overage price; `null` when it cannot be worked out, e.g. the public price list is unreachable or the online-search price is not on it). Member endpoint 0, public endpoint list price × number of terms, `--local` 0. The built-in AI in Jijian skips the confirmation for commands estimated at 100 credits or less based on this | off |
|
|
489
|
+
| `--beat <id>` + `--project <dir>` (`matrix search`) | Write the results into this beat's candidate pool without laying: merged into the layer snapshot `split/broll-plan.<layer>.json` (so `gtrk patch --candidate` finds them) and appended to the project's candidate registration (visible in the client panel right away; a missing beat is created from the dispatch window). Re-runs add nothing twice; the receipt carries `pool: {beat, added_to_plan, added_to_pool}`. The two flags go together | — |
|
|
490
|
+
| `--pool-only` (`matrix lay`) | Register plan candidates that are not yet in the project's pool: **no laying, no downloads, no track touched**, no network, no key needed (fixes `not_in_pool` in `matrix status`). Reads the main plan and every layer snapshot by default (`--plan` reads only that one), each with its own layer; `--beat <id,…>` limits it to those beats (unknown beats fail); nothing new means the project is not written. Receipt `{pool_only:true, pooled:[{beat, layer, added}]}`. On `matrix lay`, `--beat` only goes with this flag | off |
|
|
491
|
+
| `--arrange-estimate-only` | **Estimate only, do not execute**: stop right at the cloud-arrangement billing confirmation, report the arrangement volume and return **successfully** (`ok:true` + `estimateOnly:true` — that is "I am deciding", not "I declined"). Zero cloud calls, zero changes to the project file. Machine-readable values live in `lay.arrange.units` / `lay.arrange.scale`. ⚠️ What it saves is **that one cloud call and its charge** (plus the candidate downloads and laying that follow), not the whole chain: the denominators of the arrangement volume still require reading the project, the plan, and re-projection. On the asset-matrix route it reports `applicable:false` rather than **0**. When given together with `--yes`, this flag wins | off |
|
|
492
|
+
| `--cut-align <ratio>` | Sentence-boundary snapping target ratio 0..1: `0.7` ≈ about seven in ten subtitle sentence starts land exactly on a shot cut, three in ten deliberately off (snapping all of them reads mechanical); `0` = off, back to the old rhythm-slot cutting. ⚠️ Sentence-level timecodes come from live `transcript` re-projection (same source as the keyword anchors), and **when re-projection degrades it silently falls back to the old behaviour and warns** — the snapping ratio does not hold for that run | `0.7` |
|
|
493
|
+
| `--gap-fill <mode>` | How holes in the main track of an audio-driven project get filled: `fast` = **leave as little black as possible** (relax the score floor and fill from the candidate pool → then extend neighbouring grains → then borrow unconsumed candidates across beats → then fill residual holes shorter than the minimum shot length with real footage → only pad black when a whole segment cannot be filled); `solid` = pad everything with black (so in fine-cut you can see at a glance "nothing matched here"); `none` = leave the gap as is. ⚠️ Under `fast`, borrowed footage is weakly related to that segment's script and sub-floor slots are quick cuts under 1.2s; both are reported in the log with `kind` `borrowed` / `subfloor` — **that is honest disclosure, not a defect**. `none` combined with main-track magnetic snapping in the client will swallow the gap and shift everything after it **out of sync with the voiceover** | `solid` |
|
|
494
|
+
| `--highlight-weight <w>` | `matrix lay` only: fold "is there anything worth watching" (information density / drama / emotional intensity / rarity) into candidate ranking, 0..1. **Orthogonal** to `--mark-weight` (how good the frame looks); the two weights are clamped to sum to 1. ⚠️ The highlight score reads the `describe` understanding cache, so **without a prior `describe` run this flag does nothing** — uncached candidates are treated as neutral and the weight is returned to similarity | `0` (off, zero regression) |
|
|
495
|
+
| `--decode-path <mode>` | `matrix index` only: decode path for scene detection, `auto` \| `gpu` \| `cpu` \| `full`. `auto` probes for hardware decoding and **degrades per asset** (recommended); `gpu`/`cpu`/`full` pin one tier and **do not degrade on failure** (for A/B comparison and troubleshooting). ⚠️ The default is still `full` (legacy behaviour) — you have to pass `auto` yourself to get the speedup | `full` |
|
|
496
|
+
| `--proxy-width <n>` | `matrix index` only: proxy decode width. ⚠️ Below this, fidelity degrades noticeably — **do not shrink it casually** | `384` |
|
|
497
|
+
| `--proxy-scaler <name>` | `matrix index` only: proxy scaling algorithm. Defaults to `neighbor` (point sampling, no filtering); pass another value when you need a different algorithm | `neighbor` |
|
|
498
|
+
| `--exclude-recent <n>` | `matrix material --scope audio` only: avoid the last n BGM tracks already used. The history is **booked automatically** when `audio lay` writes to the track — you do not maintain it | `12` |
|
|
499
|
+
| `--no-exclude-recent` | Turn off the BGM avoidance above, allowing recent tracks to be reused | off (avoidance is the default) |
|
|
500
|
+
|
|
501
|
+
**`matrix fetch <clip_id...>` (pull raw footage during the fine cut, project-independent)**: for materials you have **searched with billing** (hits in the grant ledger), re-signs fresh download links for free by clip_id and lands them as `<clip_id>.<ext>` — when the rough cut is already exported to Jianying and one more B-roll is needed, you can pull the raw file locally and drag it straight in without going back to the client app. The flow is always **two-step**: pick clip_ids from `matrix search` → `matrix fetch` to pull (fetch itself is free of charge, performs no search, and has no confirmation gate). **Grants are persistent**: the 24h-expiring signature is no obstacle — a clip searched three days ago still fetches fine. Ungranted items are reported one by one as "not granted" with the way out (run one billed search for that keyword to obtain the grant) and never block the rest; one batch ≤ 500. **The initial scope covers video clip raws only** (the re-sign surface for image/audio materials is not open yet; such ids land in missing with a hint). Outputs never enter `.gtrk` and never land in the Jianying draft folder; material added inside Jianying does not flow back into the project (export is one-way).
|
|
502
|
+
| `--json` | Machine-readable: stdout carries only the result JSON | off |
|
|
503
|
+
|
|
504
|
+
> **Cloud arrangement keeps nothing on the server**: the projected plan you send up is **not stored**. What we keep is a size summary, the metering version and the recomputed amount — enough to settle a billing dispute independently, but nothing that reveals your material structure. The price of that is that **when something goes wrong we have nothing to reproduce it with** — hence `--dump-request <file>`, which keeps the exact bytes that went up **on your own machine**; send us that file when you need help. It is off by default and **refuses to write inside the project directory** (projects get zipped and copied around).
|
|
505
|
+
>
|
|
506
|
+
> Two protections sit in front of the endpoint, both answering **429 with zero execution and zero charge**: a per-key rate limit, and a check that recognizes "the same plan resubmitted over and over with different parameters". Transport retries send **byte-for-byte identical** request bodies and are never counted against either.
|
|
507
|
+
>
|
|
508
|
+
> **Beat windows are re-projected on the spot**: in dispatch-consumption mode, **before the first cloud retrieval**, each beat's `[track_st, track_ed]` is recomputed from "`transcript` × the current `.gtrk`", and retrieval, `broll-plan.json` and track laying all use the recomputed values (`--lay 0` obeys the same rule; ad-hoc `search` is unaffected). The timecodes in `dispatch.json` are only a **projection-time snapshot**, used as a fallback solely when re-projection is impossible — **so after editing the talking-head track you can run this command directly without re-running `gtrk split`**. `--json` always emits `reprojection:{mode,degraded,reason?,drifted,max_offset,shrunk,dropped}`; beats with **zero surviving span** after re-projection are skipped (no retrieval quota is burned on them and nothing is laid). If re-projection is impossible (missing transcript / project not found / no talking-head material on the main track) → it **degrades to the snapshot with a warning and a `--json` marker**, while retrieval and the plan still complete instead of hard-failing; behaviour for non-v1 projects is unchanged (the plan lands first, then the version gate exits non-zero).
|
|
509
|
+
>
|
|
510
|
+
> Candidates' `preview_url`/`cover_url` **are unsigned and never expire** (once the local proxy is on disk it is always reused); what carries a signature and expires in roughly 24 h is the **source `url`**, re-signed by the client's "confirm source clip" flow — **you do not need to re-run this command just to re-sign**.
|
|
511
|
+
>
|
|
512
|
+
> **Re-running strips and re-lays, but never touches tracks you edited**: candidate tracks are identified by "material prefix + last round's registration fingerprint", no longer by track number (saving in the client renumbers all overlay tracks). Once a candidate track is judged "edited by you" (a clip was changed, or you confirmed the source clip in the client so the material became `broll-raw-*`), this run **lays nothing at all**: no track is stripped, no track is appended, `.gtrk` is byte-for-byte unchanged, `broll-plan.json` is still produced, and the command reports "which track / what evidence / what to do next" and exits non-zero (`--json` emits `{ok:false, refused:[…]}`). Add `--force-relay` to force a re-lay.
|
|
513
|
+
>
|
|
514
|
+
> **Machine-readable accounting: `counts.results` is the pre-dedup number**: in `--json`, `counts.results` is always the **sum of retrieval-response rows across queries** (unchanged legacy semantics) — when 15 queries all hit the same material it reads 15, while the landed plan may hold only 8 rows covering a single material. To judge "how much footage is actually there", read the three keys emitted in dispatch-consumption mode: `counts.zero_yield` (queries that **truly yielded nothing**, decided on the **retrieval response** being empty rather than by scanning the plan for `results: []` afterwards — in-beat dedup folds a hit into a sibling query of the same beat, and folding ≠ zero yield), `counts.plan_results` (the actual number of result rows **after the plan lands**, deduplicated) and `counts.distinct_clips` (distinct `clip_id` count inside the plan). These three appear **only in dispatch-consumption mode**; the `counts` of ad-hoc `matrix search` and `matrix lay` are byte-for-byte unchanged (**absence means "no such concept here", not "measured as 0"**). On the laying side it likewise emits `lay.beatsWithCandidates` (beats that have candidates) and `lay.emptyBeats` (**the list of zero-candidate beats** — spans with no footage to lay at all); the two always satisfy `beatsWithCandidates + emptyBeats.length = the plan's total beat count`.
|
|
515
|
+
>
|
|
516
|
+
> **Material-on-disk self-check**: after writing back the project, the CLI read-only checks whether every `materials[].path` exists. Relative paths resolve against the directory containing the `.gtrk` file (`<output>/gtrk/`). `--json` emits `integrity:{ checked, counts, dangling:[…], danglingReferenced, danglingOrphan, external:[…], noPathIds:[…] }`; `dangling` lists registered materials missing on disk and marks whether the timeline references each one, while missing absolute paths are counted as `external`; http(s) materials are counted without network requests. This check only reports: it does not change `ok`, the exit code, material entries or files. Repair a dangling reference by re-confirming the source clip in the client or deleting the corresponding clip. Runs that never write back (`--lay 0` / refused / missing project) emit no `integrity` field.
|
|
517
|
+
>
|
|
518
|
+
> **Clip background fill (default)**: every candidate clip carries a solid black fill (gtrk contract `background_fill`, so narrow or shrunken clips never reveal the talking-head underneath), and each candidate track patches its own empty spans inside every landed beat envelope with solid black clips — with `--lay 2`, leaving only one track visible still hides the talking-head; audio-driven projects (no talking-head) are not patched. `--json` emits `lay.bed` (`fill`) and `lay.bed_fill` (patches and seconds). Spans with no B-roll at all count as holes: `lay.blackBedHoleSec` / `lay.blackBedHoles` are always emitted, with a non-fatal warning at ≥3 s for one span or ≥15% of one beat; adjust `--score-floor` or patch in the client. The patch material is stored at `assets/builtin/solid-000000-<W>x<H>.png` and reused idempotently. Gaps shorter than 1.2 s (1–2-frame seams between clips, the span before an anchored shot) are first absorbed by the neighbouring clip within its source-window headroom (never crossing the search segment, in-segment cuts or black spans); only gaps that cannot be absorbed are patched black, and each is listed in `lay.flash_gaps.kept` and a warning.
|
|
519
|
+
>
|
|
520
|
+
> **Solid black bed track (`--black-bed`, legacy)**: one solid black track covers the landed beat envelope beneath candidate tracks and above the talking-head track, and candidate clips carry no fill; holes are counted the same way with the same numbers. A black bed track left in an older project is replaced by clip fills on the next default re-lay.
|
|
521
|
+
|
|
522
|
+
**Local-footage mode (`matrix index` / `--local`)**: footage does not have to live in the cloud library — retrieve and lay tracks straight from your local footage folders (video and images mixed):
|
|
523
|
+
|
|
524
|
+
```bash
|
|
525
|
+
gtrk matrix index --dirs <folder-or-file,...> # ① build a slice-free index: content-fingerprint incremental, resumable; renames/moves are not recomputed
|
|
526
|
+
gtrk matrix --local --dirs <folder-or-file,...> --project <dir> # ② local retrieval + track laying (--lay 0 = plan only; pass a single media file to narrow the search scope to it)
|
|
527
|
+
gtrk matrix lay --project <dir> [--plan <path>] # ③ consume the (edited) plan and lay tracks, zero retrieval cost
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
- **Repeat the flag when a path contains an ASCII comma**: `--dirs` / `--materials` split on ASCII commas by default; when a path carries one, repeat the flag instead (`--dirs "A" --dirs "B"` — it **accumulates**, it does not overwrite). A whole string that exists on disk is never split, and the full-width comma "," never participates in splitting. **When enumeration reports `0/0`, check this first**, then check the folder for broken symlinks.
|
|
531
|
+
- **Your footage never leaves your machine**: only 512px sampled frames are sent to Gitruck Cloud's own embed endpoint for vectorization, discarded on arrival; results reference your local originals by absolute path (no downloads, no proxies). Indexing is metered by frames actually sampled (pre-held before the run, settled to actual usage afterwards); text-side retrieval costs zero credits.
|
|
532
|
+
- **Images are first-class**: images are indexed, retrievable and layable; when selected, an image goes through cloud `image_move` and lands as a 5-second camera-move video — **the image itself does go to the cloud** (2 credits per image, summarized for confirmation before laying; same image + same params is reused forever, never re-billed). Zero images to the cloud → `--no-image-broll`.
|
|
533
|
+
- **No material reuse**: within one laying round each material unit is used once globally (local video per scene, images per file); when candidates run dry, slots stay empty rather than repeat; `--dedup-scope material` tightens to file level.
|
|
534
|
+
- **Projects containing local footage cannot cloud-render**: submission is rejected (`local_broll_cloud_render_rejected`) — produce locally in the desktop client or via `gtrk render`.
|
|
535
|
+
- **Optional atoms**: `matrix describe --plan <path> [--top-k N]` / `--materials <a,b>` understands candidates on demand (VLM description / tags / quality mark / watermark·subtitle·black-border·blur signals; 1 credit per frame (**async task billing**: pre-deducted on submit → settled on completion, auto-refunded on failure; Gitruck internal members are exempt, detected automatically at run time — with `--json`, `credits_estimated` is the actual charge and `credits_would_be` the list price), results injected into the plan and cached locally, cache hits are free, >20 frames triggers a confirmation guard). **One describe speaks for one segment, not the whole candidate**: in `--plan` mode each candidate is sampled at a single frame (`segments[0].best`), the result carries the scope anchor `describe.at_sec` (seconds on the material timebase), and the run reports "describe coverage = frames understood / total **segments** carried by the understood candidates" (`describe_coverage` in `--json`) — injecting N entries does not mean those N candidates were all looked at; `--source-window <start,end>` filters by source-time window (only with `--local`; the film-commentary pattern "segment N of the narration gets footage from around segment N of the film"); `matrix lay --mark-weight <0..1>` blends describe's quality mark into candidate ranking (fused score = sim×(1-w)+(mark/100)×w; reorders only, never changes admission; candidates without a cached mark are treated as neutral).
|
|
536
|
+
- **Highlight rubric**: `--highlight-rubric <text|@file>` (same flag on `describe` and `lay`; ≤2000 characters; `@<path>` reads from a file, which is the main form since a rubric is multi-line). It tells the highlight score (`--highlight-weight`) **what to judge by** — each vertical blueprint carries its own (food judges portion contrast and visible prices, travel judges rare landforms and extreme weather). **Omit it and the field is not sent at all**: the server falls back to its own domain-agnostic default, byte-for-byte identical to behaviour before this flag existed. Highlight scores are cached in **per-rubric buckets**: switching rubric rescores without invalidating or overwriting the objective description cache. `describe --plan` pins the run's `rubric_hash` into the plan and `lay` reads that same bucket automatically (no need to pass it twice); if the two disagree `lay` **fails hard** instead of silently picking one — scoring against the wrong rubric is undetectable after the fact. ⚠️ Rescoring under a new rubric still re-sends the frames (billed per frame): a text-only rescore channel needs server support and does not exist yet.
|
|
537
|
+
- **Grid understanding**: `matrix describe --layout grid` asks the server to tile candidates of the same query (the same material for `--materials`) into contact sheets and understand them in batches (≤9 frames per sheet, a cell-by-cell scan for corner logos and black bars, blur judged by a sharpness metric). **Still 1 credit per frame**, faster, and the same budget covers more frames; but mark / highlight are **only comparable within one sheet** and shot size / black-border calls are less stable than per-frame, so keep the default per-frame mode when you rank by `--mark-weight` / `--highlight-weight` or rely on shot size. **Omit `--layout` = per-frame, request body byte-for-byte identical to before this flag existed.** Whether the server actually used grids is taken from its receipt (an old or ops-disabled server is reported as "this run was per-frame"; read `layout_receipt` with `--json`); the cache records how each frame was understood, and a per-frame run **does not reuse grid results** (it re-understands them per frame and reports the count).
|
|
538
|
+
- **Index knobs and score scale**: `--scene-threshold` tunes scene-split granularity, `--stability-threshold` collapses static-camera scenes to fewer sampled frames, `--rebuild` forces a rebuild (describe caches are kept); the index is not portable across machines (keys are absolute paths — just re-run `index` on the new machine). Local score scale differs from the cloud's (a perfect hit can score as low as ~0.25), so do not raise `--score-floor` on cloud instincts.
|
|
539
|
+
|
|
540
|
+
**`gtrk matrix material "<query>"` (general tri-state material search)**: the second line alongside the B-roll search above, returning a download link for the **whole material** (not a segment) — `--scope clip|image|audio` (default `audio`, the BGM use case), `--commercial-only` searches commercially usable material only (**an explicit opt-in switch — off by default**), `--min-duration/--max-duration` picks by finished-cut length, `--top-k` (default 5, server cap 50), `--diversity`, `--json` for machine reading, `--out` to write a file. With `--scope clip|image` it also returns **Pexels supplementary results**, listed separately in `pexels_results` and not counted as candidates (`--no-stock` turns this off); download them straight from `download_url` (not via `matrix fetch`) and keep the photographer credit and the Pexels link when you use them.
|
|
541
|
+
|
|
542
|
+
> ⚠️ **`is_copyright` means "may this be used commercially", not "is this under copyright"**: `true` = **commercially usable** (owned ∪ licensed), `false` = **not commercially usable**.
|
|
543
|
+
>
|
|
544
|
+
> **Do not read `false` as "no copyright, use it freely" — it means exactly the opposite.** The decisive counter-example: concept material (other people's copyrighted works) is ingested with a hard-coded `is_copyright=0`; if the field really meant "is under copyright", that batch would have to be 1.
|
|
545
|
+
>
|
|
546
|
+
> `is_copyright` means “commercially usable”: `true` = usable and `false` = not usable. Under `--json`, each result also carries `copyright_label` (`"可商用"` / `"不可商用"`), derived in the same direction and absent when `is_copyright` is absent; read these fields directly instead of inferring from the name.
|
|
547
|
+
>
|
|
548
|
+
> The field exists **only on the matrix-member endpoint**: on the public endpoint its absence does not mean "not commercially usable" — the server already restricts that endpoint to commercially usable material at the source (absent = nothing to judge; the CLI reports the absence honestly and never fabricates a value).
|
|
549
|
+
>
|
|
550
|
+
> **Default scope**: the matrix-member tier searches the whole library by default (`copyright_scope=all`, including non-commercial and concept material). The CLI and bundled skills do not narrow it; pass `--commercial-only` when you need commercially usable material only.
|
|
551
|
+
|
|
552
|
+
Orchestration recipes (pure matching / describe-then-lay / time-window / footage-first scripting / three-layer stacking) and the plan-editing contract live in the bundled skill `/gtrk-matrix`.
|
|
553
|
+
|
|
554
|
+
### `gtrk mg` — MG motion-graphics particles (lay / lint / status / render)
|
|
555
|
+
|
|
556
|
+
Consumes the `dispatch.mg` dispatch landed by `gtrk split`, laying html-particle assets produced by **your show's MG skill** into the `.gtrk` project's `beat_track`. Four modes are dispatched by the first positional word: **no argument = lay**, `mg lint <file>` = single-file validation, `mg status` = orchestration dashboard, `mg render <file>` = standalone particle cloud render (project-independent; the fine-cut supplement channel). The old name `gtrk rrv` remains a deprecated alias (it prints a notice; prefer `gtrk mg`).
|
|
557
|
+
|
|
558
|
+
| Parameter | Purpose | Default |
|
|
559
|
+
|---|---|---|
|
|
560
|
+
| `--project <dir>` | The oralcut / split output folder (locates `split/dispatch.json` and the `.gtrk` project) | — |
|
|
561
|
+
| `--dispatch <path>` | Explicit `dispatch.json` path (fallback for non-standard layouts) | Derived from `--project` |
|
|
562
|
+
| `--only <beat>` | Run a single beat only (takes a **beat id** such as `B12`, not a `composition_id`; the main particle and its `-aux<n>` overlays are selected together). **True incremental merge**: only the matched particles are re-laid, and every other already-laid particle on the track (including your manual tweaks) is preserved as is | all |
|
|
563
|
+
| `--lint-only` | Lint only; lay nothing and write nothing back | off |
|
|
564
|
+
| `--replace-all` | Explicitly authorize a **full track reset**: no incremental preservation, the whole track is stripped and re-laid — **this deletes every other already-laid particle on the track** | off |
|
|
565
|
+
| `--duration <sec>` | **Required in render mode**: the explicit duration anchor (seconds) — standalone mode has no slot envelope, so this value is at once the lint envelope, the output duration and the billed duration | — |
|
|
566
|
+
| `--format <fmt>` | Render-mode output format: `qtrle` only for now (Jianying-readable transparent MOV; `webm` is explicitly refused — Jianying cannot read VP8-alpha) | `qtrle` |
|
|
567
|
+
| `--out <dir>` | Render-mode output directory (never writes into the Jianying draft folder — dragging into Jianying is your move) | `./mg-render/<composition_id>/` |
|
|
568
|
+
| `--yes` | Render mode: skip the billing-estimate confirmation | off |
|
|
569
|
+
| `--json` | Machine-readable: human logs go to stderr, stdout carries only the result JSON | off |
|
|
570
|
+
|
|
571
|
+
- **Laying** (`gtrk mg --project <dir>`): reads `dispatch.mg` → for each beat takes the source particle from `<project>/mg/<composition_id>.html` → lints → lays it into `beat_track` and atomically writes `struct_meta.mg` back into `.gtrk` (self-produced tracks are registered idempotently in `lay_tracks`; a re-lay strips the previous self-produced items before appending, and user-added tracks are never touched). Whether a particle is a "transparent overlay" or a "full-screen bed" is decided by `opaque`, inferred from the particle HTML's root `background`. The lint compares each particle's aspect ratio with the project's `video_size`; a particle with a different ratio (say, one declared 1920×1080 in a portrait project) fails `1-canvas-match` and is not laid. Beats with a missing HTML file or a failed lint are counted in `skipped` and do not block the rest.
|
|
572
|
+
- **The stripping surface ≠ "what gets laid this run", and ≠ "every registered track"**: `--only <beat>` **strips only the matched particles** (true incremental merge) — every other already-laid particle's clip / material / registration entry is **preserved as is**, together with any manual tweaks you made in opencut (what is preserved is the existing clip itself, not a rebuild from the registration, so transparency `opaque` is not lost); those preserved entries are **not re-linted and their source HTML is not re-copied** (the project is self-contained, so deleting files under `<project>/mg/` does not matter). A full re-lay is still "strip clean, then rebuild the whole track", with **one exception**: particles that are in this dispatch but failed to land (missing HTML / failed lint / zero surviving span after re-projection) keep their previous round's clip on the track (a broken new one must not destroy the working old one); conversely, already-laid entries **no longer present in the dispatch** are still stripped (a plan change ≠ something broke). To strip every other already-laid particle too, authorize it explicitly with `--replace-all`.
|
|
573
|
+
- **The material table does not accumulate**: strip materials by “self-produced identity × zero references” (self-produced = an `mg-`/`rrv-` prefix, or a registered filename under the CLI-exclusive `assets/mg/`), without trusting the client-rewritable `html_material` prefix. The `mg-` count stays equal to the particles on the track; duplicate and orphan entries are removed. Non-self-produced materials, self-produced materials still referenced by a surviving clip, and HTML copies under `assets/mg/` are preserved.
|
|
574
|
+
- **"Nothing matched" is not a clear-everything instruction**: when `--only` matches nothing, `dispatch.mg` is empty/missing, or every entry in this run was skipped, **while the track already has laid particles**, the write-back is refused (that is a signal that the dispatch or the selector is broken). Add `--replace-all` if you really mean to clear it. A first-time lay (no existing laid entries on the track) is exempt and completes normally, reporting `laid=0`.
|
|
575
|
+
- **Slot windows are re-projected on the spot**: before laying and linting, each queue entry's `[track_st, track_ed]` is recomputed from "`transcript` × the current `.gtrk`", and thereafter the lint slot envelope (house rule ⑦) and the laid clip duration both follow the recomputed values (`--only` obeys the same rule; aux particles re-project against **their own** span and are not conflated with the main beat window). The timecodes in `dispatch.mg` are only a **projection-time snapshot**, used as a fallback solely when re-projection is impossible — **after editing the talking-head track you can lay directly without re-running `gtrk split`**. `--json` always emits `reprojection:{mode,degraded,reason?,drifted,max_offset,shrunk,dropped}` (including under `--lint-only`). Entries with **zero surviving span** after re-projection are skipped and counted in `skipped` (no HTML is copied and nothing is laid back from the snapshot); if re-projection is impossible (missing transcript / project not found / no talking-head material on the main track) → it degrades to the snapshot with a warning and a `--json` marker, and the exit code is unchanged; behaviour for **non-v1** projects is unchanged (the laying path's version gate exits non-zero, while `--lint-only` still produces its report). A successful lay appends this run's timecode provenance (`timecode_source` / `reprojected_at`) into `struct_meta.mg`.
|
|
576
|
+
- **lint** (`gtrk mg lint <particle.html> [--dispatch <path>]`): a purely local static check of the machine-decidable subset of the house rules for a particle HTML (wrapped in `<template>`, `data-composition-id` + root `data-width` / `data-height` (positive integers), `gsap.timeline({ paused: true })`, registration in `window.__timelines`, no `Math.random` / `Date.now`, self-contained with no relative external links, root `background` consistent with `opaque`, …); when `--dispatch` is given it also checks that the `composition_id` matches the dispatch, and compares the particle's declared aspect ratio with the project's `.gtrk` `video_size` (`1-canvas-match`: a different aspect ratio is fatal, the same ratio at another size passes, and ratios within 7% count as the same — a 16:9 particle in a 17:9 DCI 4K project passes, accepting a 6.7% horizontal stretch; `--project` does the same). A bare lint has no target project and only checks for positive integers. Any fatal item exits non-zero and reports every reason.
|
|
577
|
+
- **Expected-id consistency** (`1-cid-expect`, **fatal**): the `data-composition-id` inside the HTML must equal the expected id (when laying, the dispatch entry's `composition_id`; for `mg lint`, the filename — but only when it matches the dispatch or looks like `…-B<digits>[-aux<n>]`, so a renamed copy such as `./tmp.html` is not compared). This guards against "copying `<id>.html`, renaming the file and forgetting the id inside" — laying would write a clip/material named after the file while the file registers a different `__timelines` key and fights the same-named particle over the same style scope.
|
|
578
|
+
- **House rule ⑦, timeline length estimation** (`7-fill-slot` / `7-no-estimate` / `7-infinite-repeat`, **always non-fatal, never blocks laying**): when the slot envelope is known (per particle when laying; for `mg lint --dispatch` when it matches a dispatch entry) it computes a **static lower bound** on the GSAP timeline — degrading call by call, counting whatever it can parse (`duration×(repeat+1) + repeatDelay×repeat`, with `yoyo` adding no time), while calls with expression positions or non-literal durations are **skipped and not counted** (ignoring some calls still yields a valid lower bound). Estimate < envelope → warning; nothing computable at all → an explicit notice that "length could not be estimated statically, house rule ⑦ was not verified, and it must be accepted against the real engine's seek" (**never silent**: "could not compute" and "computed and passed" are distinguishable in the output); containing `repeat:-1` → a warning that "an infinite loop makes the total length Infinity, so house rule ⑦ cannot be verified statically; please use a finite repeat computed from the slot". The real criterion is always the render engine frame by frame; this item is only a reminder layer.
|
|
579
|
+
- **House rule ⑧, repeated-primitive merging** (`8-primitive-merge`, **always non-fatal, never blocks laying**): identifies mergeable batches of `line` / `rect` / `path` / `polyline` / `polygon` that are "created inside a loop, or by a named factory called in a loop; landing under the same parent node; and not driven by per-element animation". Only batches whose purely numeric loop trip counts sum to **≥ 8** under the same parent are reported; when bounds involve `.length` or named constants and cannot be computed it still reports "count unknown" without constant folding; elements with per-element `gsap.set` / tweens, or used as a tween's first argument, are excluded. This item only points out "there is a batch of repeated primitives here that can be merged **losslessly**, pixel-identical after merging" — it is **not a risk verdict**: a hit does not mean the particle will reproduce a defect, and a miss does not mean it is safe. The real criterion remains sampling frames from a real render.
|
|
580
|
+
- **Callback and seek semantics** (`x-callback-driven` / `x-engine-api-override` / `x-raf-interval`, **always non-fatal, never blocks laying**): aligned with the same-named contract section. The engine MUST use `seek(t,false)` / `time(t)` / `progress(p)` when fixing a frame; particles may drive their picture from timeline callbacks but MUST NOT override `tl.seek` or replace `window.__timelines[…]`. These lint items are reminders only and do not require seek shims.
|
|
581
|
+
- **status** (`gtrk mg status --project <dir>`): summarizes the MG pipeline — total beats in `dispatch.mg` / how many source HTML files exist / how many are laid into `.gtrk`, annotating each beat (missing HTML / produced but not laid / laid). A slot (overlays and full-frame MG alike) whose laid envelope lies **entirely** inside a composite window (a window in `struct_meta.composite` whose status is not `rejected` / `trimmed`, or a storyboard layout window in `dispatch.composite` not yet imported into compositing; the scene's `takeover` is not consulted, matching the export's coverage rule) carries `covered_by: <window id>`; partial overlap does not count. The top level also carries `covered` (slots taken over) and `todo` (slots neither produced nor taken over — the count you actually have to make). `total` / `authored` keep their meaning.
|
|
582
|
+
- **Slots taken over by a composite**: laying skips them and records `{ composition_id, reason: "covered_by_composite", window }` in `skipped[]` — not a failure, and already-laid particles are not stripped. There is no switch to lay them anyway: on export, particles lying entirely inside a live composite window never appear, so to emphasize something there, put it in the composite scene. In the production order compositing (⑥) comes before `gtrk mg` (⑦), so overlays are only produced outside the windows.
|
|
583
|
+
- **Full-screen slots in older dispatches**: full-screen cards now belong to compositing, so newly landed `dispatch.mg` queues carry no full-screen entries; in dispatches landed earlier, slots whose `category` is full-screen (`fullscreen` / `title`, legacy `mg-fullscreen` / `op-ed-title`) are still produced, laid and cloud-rendered as before. `status --json` reports their count as top-level `legacy_fullscreen` (with a hint to re-run `gtrk split` and turn them into full-screen cards, baked locally at no charge). During migration: after re-running the split, a full lay keeps the old full-screen particle `<slug>-<beat>` untouched while the dispatch has its converted window (`converted_from` = that beat) and the card has not yet been built (`kept_superseded[]` in the receipt); once the matching composite is `built` and on the timeline, the old particle is stripped as a plan change (`removed_superseded[]`, not counted in `removed`). `--only` and `--replace-all` behave as before. `fetch --category fullscreen` / `render` add a `hint` when they receive or infer a full-screen particle; `lint` adds the non-fatal `x-fullscreen-card-hint` for a dispatch slot with no `category` whose particle has a full-frame solid bed.
|
|
584
|
+
- **render** (`gtrk mg render <particle.html> --duration <sec> [--out <dir>] [--yes]`): renders a single particle in the cloud, **independent of any project**, into a Jianying-readable qtrle transparent alpha MOV (the fine-cut supplement channel — when the rough cut is already exported to Jianying and one more motion graphic is needed, you can add it without going back to the client app). The chain = lint upfront (envelope = `--duration`; any fatal item is blocked locally, zero submission, zero billing) → **billing-estimate confirmation** (live price lookup; the CLI has no local HTML render engine, so the cloud billed task is the only path for standalone particles; `--yes` skips the prompt) → inline submission to the cloud → `<composition_id>.mov` landed with `task.json`/`result.json` breadcrumbs (recoverable by task_id after a crash). **Scope**: qtrle only for now (`--format webm` is explicitly refused — Jianying cannot read VP8-alpha), particle geometry must be positive integers, and `--duration` is required; the MOV comes out at the particle's declared `data-width` / `data-height` (a 1080×1920 portrait particle yields a 1080×1920 MOV). The output never enters `.gtrk` and never lands in the Jianying draft folder; qtrle is lossless and relatively large, suited to seconds-long particles. Note it shares a word with `gtrk render` (full-video rendering) but is a different thing.
|
|
585
|
+
- **fetch** (`gtrk mg fetch <query|block> [--top 3] [--all]` / `gtrk mg fetch --pick <block> --slot <beat> --project <dir>` / `--pick <block> --as <composition_id> --duration <sec> [--out <dir>]`): the **neutral particle source** from the HyperFrames registry — MG without a show skill. Candidate mode is **offline** (no network: it reads the locally cached catalog `~/.gitruck/cache/mg-registry/catalog.json`, or the snapshot that ships with the package; pinned to a source commit) and lists 2–3 blocks per query with compat flags and poster links; pick mode first checks the arguments and the landing spot locally, then refreshes the catalog once (unified static-resource delivery: refreshed every 24 hours, falling back to the cache and then the bundled snapshot), then fetches the block through the mirrors the catalog lists (Gitruck Cloud first, reachable from mainland China, then GitHub raw → jsDelivr fastly → jsDelivr gcore → gh-proxy; 8 s per mirror, **every copy is checked against its sha256 and byte count**, nothing is written if all of them fail; fetched blocks are cached under `~/.gitruck/cache/mg-registry/files/`) → eight mechanical rewrites (`<template>` wrap / id rename / drop data-start and fit the slot / sink the solid backdrop into a child / swap GSAP to the contract CDN / swap fonts to a CJK font provable in our runtime mirror / fit duration to the slot / letterbox scaling, never stretch) → `gtrk mg lint` (fatal items block the write) → lands at `<project>/mg/<composition_id>.html`. **A skeleton is not a deliverable**: the returned `editable` (copy / number arrays / colors) MUST be rewritten for the beat and the show before laying. Registry neutral blocks come in one geometry only, 1920×1080 (the size is baked into each block), and `--canvas` with any other size is refused; in slot mode, a project whose `.gtrk` `video_size` is not 16:9 (7% tolerance, so 4K landscape and 17:9 DCI still fetch) is refused before anything is downloaded or written — portrait / square projects use `--source text` (no `.gtrk` or an invalid `video_size` skips the check with a notice); `excluded` blocks are refused, `review` blocks (canvas / house-rule 8 shapes) can be fetched but need a real render check. Setting `GITRUCK_MG_REGISTRY_BASE` makes it the only mirror root for both the catalog and the blocks (`<root>/catalog.json`, `<root>/files/…`, i.e. the layout of a publish staging folder or the static disk); nothing is written to the local cache.
|
|
586
|
+
|
|
587
|
+
`--json` output: `{ ok, mode:"lay"|"lint"|"status", … }` (each mode carries its own fields, e.g. `laid` / `skipped` when laying, per-beat status for `status`). Laying mode additionally carries **`track_total`** (how many laid particles currently exist on the track), **`kept`** / **`kept_ids`** (how many are **left over from the previous round** and not re-laid this time, plus their `composition_id` list) and **`removed`** (how many old self-produced particles were stripped this run) — `laid` (this run), `track_total` (total on the track) and `kept` (left over) **must be read together**, and `track_total = laid + kept` always holds. Reading `laid` alone makes "lay 1, strip 20" look identical to "patch in 1", and reading only the first two hides the cost that "a few particles on the track are not from this round" (`kept_ids` and `skipped` overlap: something that failed to land this round is still there from the previous one). When not fully green it also carries a machine-readable **`reason`**: `skipped` (some were not laid) / `empty_queue` (**write-back refused**, the project was not modified, with `refused:true` and `blocked[]`) / `no_project` (project missing, nothing laid). Runs that actually wrote back also carry **`integrity`** (the material-on-disk self-check, identical in name and shape to `gtrk matrix`; see the previous section).
|
|
588
|
+
|
|
589
|
+
> **Exit codes**: an `ok:false` from laying or `--lint-only` **always comes with a non-zero exit** (including the ordinary mid-loop case of "some beats were skipped"). Agents should not read non-zero as "the command crashed" — judge by `reason` / `skipped`.
|
|
590
|
+
|
|
591
|
+
> **Aux overlay particles**: if `gtrk split` dispatched an `overlay` particle in some beat's `aux_layers`, it derives a `<beat>-aux<n>` composition entry into `dispatch.mg` — `gtrk mg` lays it too, giving you "a main visual on the base track plus a transparent conceptual diagram stacked on the same span".
|
|
592
|
+
> **Dual-read compatibility**: `dispatch.mg` (also reads the old `rrv_mg`), the source directory `mg/` (also reads the old `rrv/`), the material prefix `mg-` (also reads the old `rrv-`) — projects created before the de-branding need zero migration.
|
|
593
|
+
|
|
594
|
+
### `gtrk composite` — composite layer (plan / review / status / scaffold / build / lint / lay / shots / bake / materials)
|
|
595
|
+
|
|
596
|
+
Once the rough cut, B-roll and subtitles are settled, and before `gtrk mg` lays the overlays, turn chosen time windows into **composite particles**: one code particle takes over the whole frame for that span, and the client draws the talking head, B-roll and images into its slots. Driven by `/gtrk-composite` (which carries the layout rules and two checkpoints); purely local, zero billing. `plan --mode split` takes the storyboard's layout windows (`dispatch.composite`, re-projected onto the current timeline; the reason is the window's `visual_brief`, and `slot_hints` go into the window's context file) — projects whose storyboard has a `layouts` key use it instead of `auto`; an old storyboard without that queue is refused with directions.
|
|
597
|
+
|
|
598
|
+
```bash
|
|
599
|
+
gtrk composite plan --project <dir> [--mode split|full|auto|ranges] [--range 11,32 | --range u0004-u0009]... [--density 0.25]
|
|
600
|
+
gtrk composite review --project <dir> [--approve W01,W03] [--reject W02] [--adjust W04=80,90.9] [--add 140,150] [--approve-all] [--no-edge-snap]
|
|
601
|
+
gtrk composite status --project <dir> [--json]
|
|
602
|
+
gtrk composite scaffold --project <dir> [--only W03] [--force]
|
|
603
|
+
gtrk composite shots --project <dir> --material <material id or file> [--around <sec> --span <sec> | --from <sec> --to <sec>] [--every <sec>]
|
|
604
|
+
gtrk composite build --project <dir> [--only cp-w03] [--theme <css>] [--materials <json>]
|
|
605
|
+
gtrk composite lint --project <dir> [--only cp-w03] [--stills 26,86.6] [--no-browser]
|
|
606
|
+
gtrk composite lay --project <dir> [--only cp-w03] [--dry-run]
|
|
607
|
+
gtrk composite bake --project <dir> [--only cp-w03] [--fps 30] [--workers 4] [--install-browser] [--progress jsonl] [--json]
|
|
608
|
+
gtrk composite bake --input <snapshot.gtrk> --base <project gtrk dir> [--progress jsonl]
|
|
609
|
+
gtrk composite bake --abi
|
|
610
|
+
gtrk composite materials add <image> --project <dir> [--from-web-source <source id>] [--id <material id>] [--json]
|
|
611
|
+
gtrk composite materials list --project <dir> [--json]
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
- `plan`: writes candidate windows to `struct_meta.composite` in the `.gtrk` (that key only, atomic write-back; the same pattern as `gtrk split` writing `struct_meta.split`); the client outline's CP row draws them as proposal blocks. Also writes a review sheet `composite/plan.md`. Re-running keeps built windows and does not re-propose rejected ones. The text signals behind the suggested layout (lists / contrasts / numbers / steps) are recognised in Chinese and English; other languages rely on B-roll density only, and the review sheet says so. Every mode snaps window ends to sentence boundaries and the frame grid, then aligns them with **cuts**: when the top clip just outside a window end straddles that end (it was already playing inside the window) and cuts away within 0.6 s after the window, the window is extended to that cut (repeated until stable, at most up to an adjacent window, never past it); clips that only start after the window edge (a deliberate transition, say) are left alone. **Short inserts shrink the window instead**: when the top clip straddling a window end is shorter than 1 s, is not on the narration main track and has its other end inside the window (it starts inside and runs past the end, or ends inside after starting before the start) — a standalone short insert (a show opener, a transition, a beat-synced shot) rather than the tail of something already playing — the window is pulled back to its start (or end) so the insert shows in full, and that end is not extended. Every shrink and extension is listed in the receipt `edge_snaps` (end, `action`: `shrink` / `extend`, from/to, milliseconds, frames, the straddling clip, a readable `reason`), in the `plan.md` header and in the window reason. When either end of a window goes **past the narration** (the end after the last spoken sentence ends, or the start before the first one begins) by more than 1 s, the receipt `warnings` and `plan.md` say by how much and what the extra stretch covers (which clip on which track; solid-colour beds are called out as black / colour fill; no clip means an empty gap) and ask to confirm it is intended; the window itself is not changed.
|
|
615
|
+
- `review`: approve / reject / adjust / add windows, written back to the same key; later steps only act on approved windows. `--adjust` / `--add` take timeline seconds or sentence ids and snap to sentences, the frame grid and cuts the same way (shrink or extend, `edge_snaps` in the receipt), with the same past-the-narration warning (`warnings`). `--no-edge-snap` (only with `--adjust` / `--add`): the seconds you give are kept as they are (only projected onto the frame grid) — no sentence snapping, no cut alignment — and `warnings` says how normal snapping would have moved them; the window is marked `edge_snap: false` (cleared by a later adjust without the switch), and `lint` only warns about its `edge-flash` / `edge-insert` (`particles[].warnings`). A range that contains no spoken sentence is an error (sentence-id ranges still snap to sentences). `--adjust` also works on built (laid) windows, which stay built; when the window already has a scene, the `window` in the scene spec is updated too (receipt `scene_sync`: synced / unchanged / missing / unparsed) — then `build` → `lint` → `lay` (lay replaces the laid particle).
|
|
616
|
+
- `status`: read-only progress summary — window counts per state, `pending` (approved but not yet laid), `pending_cards` (how many of the `pending` windows are full-screen cards, counted from the window's `zero_slot` flag only), laid count, one row per window (full-screen cards carry `zero_slot: true`) with its span re-projected onto the current timeline via `source_ranges` (empty with a note when the speech was cut). All zeros when there is no composite key.
|
|
617
|
+
- **Full-screen cards (zero-slot windows)**: `plan --mode split` copies the storyboard window's `zero_slot` / `theme` / `bg` / `converted_from` / `covered_overlays` into the plan window and writes no `layout_hint`; when the dispatch has `layouts_declared: false` the receipt suggests following up with `--mode auto` (whose density budget does not count full-screen cards; the windows it adds never overlap them). `scaffold` gives a full-screen card only the subtitle input `subs` (no presenter slot even when the project has a presenter track), a fixed `takeover` of subtitles + overlays, and a `.bed` in the window's `bg`; its context file gains a "full-screen card (zero-slot)" section. `build`: a full-screen card whose scene declares a picture slot (`ref` / `ref-lane` / `own`) gets a warning (`warnings[]` in the receipt) and is built anyway; empty `slots` is refused by the composite particle profile (`$.slots` must be a non-empty object) with a hint to keep `subs`.
|
|
618
|
+
- `scaffold`: writes a scene skeleton `composite/scenes/cp-wNN.html` and a context sheet `cp-wNN.context.md` for each approved window; existing scenes are not overwritten (only `--force` restarts them), the context sheet is always refreshed. The skeleton is a starter template with the right slot contract for the window's shape (presenter / footage / full-screen card): a zero-slot window ⇒ full-screen card (only the `subs` text input; the whole card lands within 0.35 s of the window opening); the presenter main track showing for more than half the window ⇒ presenter segment (three same-source frosted-glass slots `frost` / `frost2` / `presenter`: `data-filter` fogs up within 0.6 s, `data-crop` left-crops pixel-aligned with each box's left edge, a semi-transparent scrim `#veil` feathered with `mask-image`); otherwise the non-main track showing longest ⇒ footage segment (footage full-frame via `ref-lane` plus a semi-transparent scrim). All three pre-fill one anchor per spoken sentence in the window (anchor name = sentence id; the keyword is taken verbatim from the sentence, resolved with the same rules as `build`, and the first sentence keeps a 0.6 s margin off the window start) and time their beats with `A()`; colors only use theme variables and class names carry an `s-` prefix; on a portrait stage the presenter / footage sits on top and the panel below. The receipt adds `shapes[]` (`{ id, shape: presenter|broll|card, track, why, anchors }`); the context sheet names the template shape.
|
|
619
|
+
- `--only` (scaffold / build / lint / lay / bake): accepts both the window id (`W21`) and the particle id (`cp-w21`), case-insensitively (`w21` and `CP-W21` mean the same; the number is padded to two digits); anything else matches as an id fragment. Selecting nothing is an error that lists what exists; when only some entries match, the rest proceed and the unmatched ones are warned about.
|
|
620
|
+
- `shots`: for picking footage — a contact sheet stamped with source time codes, shot cut points, and measured black bars (values for `data-crop`); it does not pick for you and does not touch the project.
|
|
621
|
+
- `build`: scene → self-contained particle `gtrk/assets/composite/<id>.html`. Resolution matches the infra `composite-particle-profile` rules byte for byte (frame-grid window, track identity, anchors, subtitle input, `inputs_hash`); style comes from `composite/theme.css` — the kit's default variables live on `:root`, so a theme writing `:root { … }` overrides them (the older `:root, #stage { … }` form still works); the kit's on-screen text classes default to at least 32px (the source credit `.credit` is 24px on a dark translucent strip). Write anchor keywords as they appear in the sentence: matching ignores spaces, punctuation and case on both sides, and English matches whole words (`"cold brew"` works as written; `tea` does not match `teas`). Before resolving, the scene script is parsed with the same grammar the browser uses: a syntax error fails that scene (`failed[].problems` give the line in the scene file, plus a "likely cause" line when an inline `//` comment swallows the closing brackets on the same line) and no particle is written. A scene `window` going past the narration by more than 1 s is warned about (`warnings[]` in the receipt) and built anyway.
|
|
622
|
+
- `lint` **contract checks** (reported before any still is rendered, each with the fix): `slot-css-ignored` (fatal) — a `[data-slot]` element's inline style, a style rule matching it, a scene-script assignment (including `wipe()`) or its per-frame computed style carries CSS that has no effect on the video (`filter` / `backdrop-filter` / `clip-path` / `mask` / `border-radius` / a rotating, skewing or perspective `transform` / `object-fit` / `mix-blend-mode`); use `data-filter` / `data-crop` / `data-shape` / `at()` instead. `slot-filter-unsupported` (fatal) — a `data-filter` outside the client allowlist (`blur(Npx)` / `brightness` / `contrast` / `saturate` / `grayscale`, numbers with an integer part, at most 5; the client drops the whole string while baking still applies it), checked statically for literal markup and per frame for values set in `render`. `slot-never-placed` (fatal) — a picture slot declared in the spec (`ref` / `ref-lane` / `own`) has no element in the markup, or is never placed by `at()` / `slot()` in `render`; placements static analysis cannot see (loops, built-up ids, CSS sizing) fall back to the per-frame check when a browser is available (sampled frames plus a frame-by-frame sweep; reported only if it never appears on stage) and are only a warning without a browser. `no-anchors` (warning) — the window has spoken sentences but the scene declares no anchors and never calls `A()`; names the hard-coded beat seconds. `kit-class-collision` (warning) — the theme or scene defines a generic class with the same name as a toolkit class (`.card` / `.rule` / `.pill` …; not the background `.bed` or caption `.cap`, nor toolkit-variant rules like `.bed.dark`), those rules touch none of the toolkit's styles for it, and the toolkit's background / height / radius / border / shadow for it is not overridden on the elements using it. `small-text` (warning) — on-screen text below 32px: computed from the styles without a browser (no font size = the browser default 16px), and from the per-frame effective size with one (computed size × ancestor scaling, SVG text by its viewBox scale, the largest value over the sampled frames where it is fully shown); the `.credit` card is exempt. Warnings go to `particles[].warnings` and do not change the exit code. The toolkit, the bake stage and particle bytes are unchanged.
|
|
623
|
+
- `lint`: static checks plus a per-frame layout check in the local Chrome / Edge (a lower picture's foreground border over an upper picture, a foreground line crossing a picture, a picture leaving the stage, an element inside a container that sets `left` / `top` offsets without being positioned — `unpositioned-offset`; give it `position:absolute` or the `.abs` class) and a **frame-purity** check (each sampled frame is rendered twice — once right after the previous frame, once after a distant frame — and element and slot geometry must match; impure scenes draw the wrong picture at bake chunk starts and after preview seeks), optionally rendering stills. **`--stills` takes timeline seconds** (a moment in the whole video), not seconds local to a composite window (`t` and `A()` in a scene are local); a value outside every window is an error that lists each window's timeline span and, when the value would fit a window as local seconds, the matching timeline second. Material containers the browser cannot play (m2ts / mts / ts / avi / mpg / wmv / flv) are not handed to the stage, so slots bound to them are empty in stills (a warning, receipt `stills_skipped_materials`; trust the bake or the client preview); if one still fails the rest are still rendered (receipt `stills_failed`). The static part also checks **edge flashes** `edge-flash` (same rule as plan snapping, read from the current timeline, laid particles included): the top clip straddling a window end shows only a few frames outside the window before a cut — reported with particle, end, track, clip and frame count plus a suggested `review --adjust Wnn=start,end`, counted as a problem; by the same rule, a window end that covers the start (or end) of a short insert is reported as `edge-insert` (suggesting to pull back to the insert's edge), also a problem; for windows kept as given with `--no-edge-snap` both are warnings only; the pre-`lay` check includes neither. The static part also parses the scene script inside the particle with the browser's grammar: a syntax error is `script-syntax` (with the particle HTML line and the likely cause; a problem, and the pre-`lay` check refuses it too). In the per-frame part, a script error thrown while the particle loads is `script-error` ("the scene script failed while the particle loaded", with the line), and a page whose `CP.render` is still the kit's empty default (the scene script never reached the assignment, or assigned an empty function) is `render-missing` — both are problems; `render` throwing on a sampled frame is still `script-error` with the original message. Particles whose scene script did not run (`script-syntax` / `render-missing`) get no stills; the receipt's `stills_failed` says why. Empty foreground paths (`<path d="">`, polylines with no points) are moved aside for the layout check and put back, with an `empty-path` warning (`particles[].warnings`); an error thrown by the kit's layout self-check on a frame is reported as `lint-error`, and a particle whose per-frame check could not finish as `lint-aborted` (both carry the browser's reason and count as problems, instead of a bare "particle not responding"). Exit code 0 pass / 1 problems / 3 layout not checked (no browser found; set `GTRK_CHROME`). When a particle binds a web material (an entry in `composite/materials.json` that carries `source`), the source credit is checked too: every such `own` slot needs a `data-credit-for="<slot>"` element whose text (trimmed, runs of whitespace collapsed) equals the entry's `credit`; a missing credit (`credit-missing`), a differing text (`credit-mismatch`), a `credit` that no longer matches what the current `web/sources.jsonl` produces (`credit-stale`) and a credit pointing at a slot that does not exist (`credit-orphan`) all count as problems. With a browser, a frame check also reports `credit-hidden` when the slot is visible but its credit is not — only as `particles[].warnings`, it does not change the exit code. Particles without web materials are checked exactly as before.
|
|
624
|
+
- `materials add <image>`: registers an image as an `own` material — only `png / jpg / jpeg / webp / gif / bmp / avif` whose width and height ffprobe can read; copies it to `<.gtrk dir>/assets/web/<material id>.<lower-case ext>`; atomically adds or updates one `{ id, path, kind: "image", width, height }` entry in `composite/materials.json` (`path` relative to the `.gtrk` dir; other entries untouched). The material id defaults to `web-<source id>` (with a source) or `img-<first 8 hex of the content hash>`; registering the same id with the same content again is a no-op, the same id with a different image is refused (use `--id`). `--from-web-source <source id>` reads `<project>/web/sources.jsonl` (the provenance the in-app AI's `web_fetch` writes, one `{id, kind, url, title, site_name, date, fetched_at, path, mime, bytes, sha256}` per line; the last line wins for a repeated id; a line without `url` is reported by number); `<image>` may then be omitted (the source's `path` is used and its `kind` must be `image`). The entry also gets `source` (copied verbatim: `id / url / title / site_name / date / fetched_at / path / sha256`) and `credit` (the credit text: `site_name|title`, either one if only one exists, otherwise the `url` host without `www.`; never translated, truncated or reworded), plus `derived_from` when the registered image is not the fetched file itself (or its hash differs). An image under `web/` registered without `--from-web-source` triggers a warning. Any error writes nothing.
|
|
625
|
+
- `materials list`: read-only list of the batch materials — whether each file exists, its source credit, and which scene slots (`<scene id>:<slot>`) use it.
|
|
626
|
+
- `lay`: idempotently lays onto the topmost beat track by producer identity, registers materials, marks windows built; refuses stale particles; never overwrites a same-id particle the user edited in the client. Before laying it also runs the **static part** of the three fatal contract rules (no browser): `slot-css-ignored`, a literal `slot-filter-unsupported` in the markup, and `slot-never-placed` (no element in the markup, or never mentioned in the script) — a refusal carries the same message and fix as `lint` and writes nothing; placements static analysis cannot see (loops, built-up ids, CSS sizing) are not blocked, and the receipt's `warnings[]` suggests running `gtrk composite lint` first.
|
|
627
|
+
- `bake`: bakes the laid composite particles **into opaque video locally**, written to `gtrk/assets/composite-bake/<key>.mp4`; inputs (slot pictures, subtitles, anchors) are computed from the **current timeline**. Purely local, zero billing.
|
|
628
|
+
- **Browser**: prefers the pinned chrome-headless-shell (deterministic frames, fastest); otherwise falls back to the local Chrome / Edge (screenshot mode, slower, one fewer worker by default). **Never downloads silently**: install only with `gtrk deps install --browser` or this command's explicit `--install-browser` (about 110 MB). `GTRK_CHROME` selects a browser.
|
|
629
|
+
- **Concurrency**: resident worker pages render chunks in parallel, default `min(logical cores/3, 6)`, overridden by `--workers`; chunked and sequential bakes are bit-identical.
|
|
630
|
+
- **Cache**: the key covers the particle, the computed inputs, material file fingerprints (size + mtime), fps, browser build and encode settings; hits are reused. Changing concurrency does not change the key.
|
|
631
|
+
- **Frame rate**: defaults to the project rate; `--fps` overrides (e.g. a 30fps export). Frame count = `ceil(window × fps)`, covering the whole window.
|
|
632
|
+
- **Exit codes**: 0 all succeeded (cache hits included) / 1 some composite failed (the rest still bake; reasons per composite) / 2 argument or environment error / 130 cancelled.
|
|
633
|
+
- **Machine-readable**: `--progress jsonl` prints one event per line with `type` in `start` / `browser` / `prep` / `progress` / `composite` / `cancelled` / `done`, at most 1 second apart; in this mode **closing stdin cancels** (other modes ignore stdin). `--abi` prints only `{abi, version, browser, overrides, stage, host_features}` without reading the project: `browser.pinned` says whether the pinned render component is installed; `overrides` lists the slot user overrides this version can bake (`fit` / `framing` / `crop` / `box` for the picture-in-picture window size and position / `slip_ms` for shifting a referenced clip's frames; `box_px` means the window's pixel offsets `dx_px` / `dy_px` can be baked), so the client can tell whether the adjustments in a project can be baked; `stage: "canvas"` means any stage size can be baked (the composite stage follows the project canvas, so portrait and square work the same way; older versions without this field only handle 1920×1080); `host_features`: `decor-boxes` (every apply carries the window overrides) and `slot-dewatermark` (frames taken for a slot get the clip's subtitle / watermark removal masks; the cache key includes the masks actually applied). `--input <snapshot> --base <dir>`: use the snapshot as the timeline (for the client's unsaved state); relative material paths and the output location resolve against `--base`; the snapshot is never written back.
|
|
634
|
+
- `gtrk render` / `gtrk project export` bake the project's composites first: a successfully baked span shows the baked video (in Jianying / Premiere, a video clip on that layer), and **MG / OV particles lying entirely inside a composite window are no longer pre-rendered or billed**; a composite that fails to bake (missing footage, no browser, …) falls back to the rough cut with its reason reported, and never blocks export.
|
|
635
|
+
|
|
636
|
+
### `gtrk project init` / `gtrk audio lay` / `gtrk audio tighten` — audio-first project atoms (voice-over first)
|
|
637
|
+
|
|
638
|
+
Project entry points that start from **a voice-over** instead of a talking-head raw: with the voice-over in hand (TTS-synthesized or self-recorded), `project init` builds the `.gtrk` project, and `gtrk split --project` continues the production pipeline as usual; `audio lay` adds an audio track (BGM/score) to any project; `audio tighten` tightens the pauses between sentences in the voice-over.
|
|
639
|
+
|
|
640
|
+
| Command | What it does |
|
|
641
|
+
|---|---|
|
|
642
|
+
| `gtrk project init --tts-task <task_id>` | **Main path**: references a completed `audio_tts_clone` task — the server hands over the audio and sentence timecodes directly (zero ASR, zero extra billing); the audio download lands in the project's `audio/` |
|
|
643
|
+
| `gtrk project init --audio <voice-over> --transcript <transcript.json>` | **Fallback path**: your own voice-over audio plus its sentence-timecoded transcript as a pair (produced by `gtrk transcript <voice-over> --json`; for TTS-synthesized voice-overs take the main path instead of re-running ASR) |
|
|
644
|
+
| `gtrk audio lay --project <dir> --file <bgm.mp3>` | Appends an audio track to the project; **idempotent same-source replacement** (re-running with the same source replaces instead of piling up tracks; zero-reference protection when stripping the old one); `--volume <0..1>` (default 0.1, bed volume — the contract carries linear gain only, never dB; the client's volume panel shows -20.0, the same scale on both sides; must be > 0 — `0` does not mute and is rejected, use `gtrk patch set --muted` to silence), `--offset <ms>` sets the in-point |
|
|
645
|
+
| `gtrk audio lay … --beat-align` | **Climax anchoring** (`audio_music_analyze`, billed once): pins the BGM’s emotional peak `H` (the server’s `highlight.time`) onto the cut’s climax `A`; the mapping is always `track_sec = A + (bgm_sec − H)`. **Both sides long enough ⇒ zero tiling** (exactly one clip); only a short side is tiled outward, with seams snapped to downbeats (the two hard track boundaries are cut without snapping). `A` comes from the criterion chain over `struct_meta.split.beats`: elevation → container flip → callback closure → `0.75×total` fallback, and **the CLI reports which rung was used — the fallback is explicitly flagged as a guess**. Without a key / on analysis failure / when the track has no highlight it degrades to no anchoring and the command never fails over it |
|
|
646
|
+
| `gtrk audio lay … --beat-align --climax <track-sec>` | Climax **escape hatch**: always overrides the chain above. Out of range (≤ `--offset` or ≥ the project end) or non-numeric **errors out immediately** rather than falling back silently — an explicitly wrong value should be visible at once. Must be used together with `--beat-align` |
|
|
647
|
+
| `gtrk audio lay … --no-loop` | No tiling: with `--beat-align` it lays only the anchored span and leaves head/tail silence (**the silent seconds are reported**); without `--beat-align` it keeps a single pass instead of looping to fill the project |
|
|
648
|
+
| `gtrk audio tighten --project <dir>` | Tightens the pauses **between sentences** in the voice-over track (**purely local, zero billing**): only silence that straddles a sentence boundary is compressed — **within-sentence breaths and quoted original-audio spans are left alone** — and the output honestly reports how many within-sentence breaths were skipped. `--keep <sec>` silence to keep after tightening, `--min-silence <sec>` leave anything shorter untouched, `--boundary-tol <sec>` tolerance for "sits on a sentence boundary", `--dry-run` report how many spots and how many seconds would be compressed without writing. For the three defaults see `gtrk audio tighten --help` (tune them for another subject or voice) |
|
|
649
|
+
|
|
650
|
+
`project init` also takes `--canvas <WxH>` (default 1080x1920), `-o/--out`, `--reupload`, `--no-open` and `--json` with the same semantics as `oralcut`; with `--json` both commands emit a single-line result JSON on stdout (human logs go to stderr).
|
|
651
|
+
|
|
652
|
+
### `gtrk project export` — export a refined project
|
|
653
|
+
|
|
654
|
+
Exports an already refined `.gtrk` project (after `matrix lay` / `mg` / `audio lay`) to Jianying, Premiere XML, FCPXML or OTIO without rewriting the source project. The default output directory is `export-<YYMMDD-HHMMSS>/` under the project directory.
|
|
655
|
+
|
|
656
|
+
```bash
|
|
657
|
+
gtrk project export --project <project-dir>
|
|
658
|
+
gtrk project export --gtrk <project-file> --formats jianying,xml --out <output-dir>
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
| Option | Purpose |
|
|
662
|
+
|---|---|
|
|
663
|
+
| `--project <dir>` / `--gtrk <path>` | Locate the standard `gtrk/project.gtrk`, or explicitly select a project file; use one of the two |
|
|
664
|
+
| `-f, --formats <list>` | `xml`, `fcpxml`, `otio`, `jianying`, `capcut`, `gtrk`; default `jianying,xml`; legacy fine-grained names are also accepted |
|
|
665
|
+
| `--jianying-draft-dir <dir>` | Jianying/CapCut draft root; when omitted, use user config and standard locations. The draft lands in `<draft root>/<output folder name>`; on a name clash it gets `-2`… with a warning, and the existing draft is left untouched |
|
|
666
|
+
| `--no-particles` | Skip MG particle pre-rendering while continuing structural export; skipped particles are recorded in the result |
|
|
667
|
+
| `--particle-concurrency <n>` | Particle qtrle pre-render concurrency, 1–8, default 6 |
|
|
668
|
+
|
|
669
|
+
There are two billing surfaces: structural project export is billed per task, while unique particles missing from `.tonghe-cache/particles/` are billed per minute. `gtrk project init` remains zero-credit; that does not apply to `export`. Particle cache keys and the client implementation are byte-compatible, so particles rendered by the client can be reused.
|
|
670
|
+
|
|
671
|
+
Before particle rendering, the command performs HTML, path and cache preflight; a preflight failure submits no cloud task. A single particle render or download failure is recorded in `result.json` while other formats continue. With `--json`, stdout contains one result JSON line and human logs go to stderr.
|
|
672
|
+
|
|
673
|
+
**Things only the client draws** (text, stickers, graphics and effects added in the client, and the canvas background) do not reach the exported project files: when the project has any, the command says once, before submitting, which kinds and how many; when there is text it points to exporting a Jianying draft from the client (the client carries text over as editable captions). `droppedByContract.clientOnly` in `result.json` holds the per-kind counts, and `clientVisualElementCount` is the number of elements (it used to count lanes by mistake).
|
|
674
|
+
|
|
675
|
+
**Clip background fill** (`background_fill`): the bottom track of Jianying / CapCut drafts carries it natively; on other tracks the cloud inserts a helper track beneath the clip — a solid color becomes a same-color solid image, a blur becomes the same footage (same time range, muted, scaled to cover the canvas) with Jianying's Blur effect. Premiere projects get the same treatment on every track, with a Gaussian Blur; FCPXML / OTIO only do solid colors, and a blur degrades to solid black there with a log notice (Jianying / Premiere also degrade when the footage size is unknown and it cannot be scaled to cover). Clips that already cover the whole canvas get no backdrop. The solid images are referenced as `solid-<rrggbb>-<W>x<H>.png` inside the output folder, and the command writes them before the project files — **moving or deleting the output folder takes those images offline**. `backgroundFill` in `result.json` records the written images and degradation notices (absent when the project has no fills).
|
|
676
|
+
|
|
677
|
+
### `gtrk project background` — clip background fill (blur / solid color)
|
|
678
|
+
|
|
679
|
+
By default writes a clip-level `background_fill` (gtrk contract field) on **every video / image clip of the main track**: beneath the clip, only for its duration, covering the whole canvas; blur = the clip's own picture scaled to cover and blurred. The typical use is a blurred fill instead of black bars when a landscape source sits on a portrait canvas. Users can change it per clip or for a multi-selection in the client; Jianying drafts exported from the client or `gtrk project export` carry it natively (the main track is the bottom track), Premiere projects use the same footage scaled to cover with a Gaussian Blur, FCPXML / OTIO degrade it to solid black with a notice, and local `gtrk render` carries it. Overlay-track clips and gaps are left alone, and `struct_meta.client_background` is not touched (the receipt says whether one is still present). Zero credits, no cloud access.
|
|
680
|
+
|
|
681
|
+
`--scope canvas` keeps the old canvas-level write: only `struct_meta.client_background` changes (the client renders the canvas background from it; Jianying / Premiere projects and local rendering do not carry it).
|
|
682
|
+
|
|
683
|
+
```bash
|
|
684
|
+
gtrk project background --gtrk <project-file> --blur
|
|
685
|
+
gtrk project background --project <project-dir> --blur --intensity 300
|
|
686
|
+
gtrk project background --gtrk <project-file> --color "#1A1A1A"
|
|
687
|
+
gtrk project background --gtrk <project-file> --clear
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
| Option | Purpose |
|
|
691
|
+
|---|---|
|
|
692
|
+
| `--project <dir>` / `--gtrk <path>` | Locate the project, same rules as `project export` |
|
|
693
|
+
| `--blur` | Blurred fill: the clip's own picture scaled to cover and blurred (canvas scope: a blurred copy of the main-track picture) |
|
|
694
|
+
| `--intensity <n>` | With `--blur`, 0–1000, default 200 (must be an integer per clip) |
|
|
695
|
+
| `--color <#RRGGBB>` | Solid color (six-digit hex) |
|
|
696
|
+
| `--clear` | Remove the fill (per clip: drop `background_fill` from main-track clips; canvas: delete `client_background` and return to the client's default black) |
|
|
697
|
+
| `--scope <clips\|canvas>` | Scope: `clips` (default) per main-track clip; `canvas` canvas level (old behavior) |
|
|
698
|
+
| `--dry-run` | Validate and report the value that would be written, without writing |
|
|
699
|
+
|
|
700
|
+
Exactly one mode is required. Writes go through atomic replace with the content-revision guard and leave everything else intact; nothing is written when the value is unchanged. The `--json` receipt includes the revisions before and after.
|
|
701
|
+
|
|
702
|
+
> **`--beat-align`**: follows the climax-anchor rule in the table above; an explicit `--climax` overrides the automatic selector. The mode calls `audio_music_analyze` and incurs its listed charge.
|
|
703
|
+
|
|
704
|
+
|
|
705
|
+
> **Run `tighten` before laying tracks**: it changes the voice-over track's length, and `gtrk split` / `gtrk matrix` reproject beat timecodes against the project as it stands — tighten first and you save a round of rework. To get it right at synthesis time instead, in-house voices accept `--fragment-interval` during TTS (see `audio_tts_clone` below); cloud voices do not support that parameter, which is when you tighten after synthesis instead.
|
|
706
|
+
|
|
707
|
+
### `gtrk tool <name> [inputs...]` — the single-shot tool family
|
|
708
|
+
|
|
709
|
+
Standalone single-request capabilities, kept separate from the pipeline's lane commands (`oralcut`/`split`/`matrix`/`mg`). **A top-level command dispatched by the first positional word** (no parent/child commands): `gtrk tool <name> [inputs...]` runs a tool (multi-file image tools accept several paths, and the order is the assembly order), `gtrk tool list` lists them all. One tool = one thin descriptor (input category / payload assembly / artifact mapping / billing / availability gate), sharing a runner that performs "validate → upload (fingerprint cache, auto-chunked ≥ 256 MiB) → submit → poll → stream-download to disk → `task.json`/`result.json` breadcrumbs" — adding a tool means adding one descriptor, never writing orchestration.
|
|
710
|
+
|
|
711
|
+
**Output-directory convention**: tools that take an input file default to `<input-name>-<tool-name>/` **next to the input**; `input=none` tools (e.g. `audio_tts_clone`) default to `<tool-name>-<timestamp>/` **under the current directory**. Both can be overridden with `--out <dir>`. When the default name collides with an existing directory a `-2`/`-3` suffix is appended, and artifact files colliding inside one directory get the last 6 characters of the taskId appended — **always take the path from the returned `outDir` / `files`, never reconstruct it from the name** (an explicit `--out` never grows a numeric suffix; re-running the same input overwrites idempotently).
|
|
712
|
+
|
|
713
|
+
| Tool | Input | Output | Billing | Status |
|
|
714
|
+
|---|---|---|---|---|
|
|
715
|
+
| `image_move` | One image; optional `--motion` picks one of 26 camera moves | Camera-move video (geometry derived from the source orientation: landscape 1920×1080 / portrait 1080×1920) | Queried live before the run | Live |
|
|
716
|
+
| `image_matting` | One image (phone photos with an EXIF orientation are uprighted to their display orientation before upload; the original is untouched) | Transparent-background png (`--param` can request a backing plate) | Queried live before the run | Live |
|
|
717
|
+
| `image_blackborder_remove` | One local image | Image with black borders removed | Queried live before the run | Live |
|
|
718
|
+
| `image_canvas_adapt` | One local image; optional target width/height and `normal` / `rectangle` / `square` | Aspect-adapted image | Queried live before the run | Live |
|
|
719
|
+
| `image_purify` | One local image; optional `full_screen` / `region` and region boxes, optional `--redraw` mode (only material you have the rights to process) | Image cleaned of watermarks, logos or overlays | Queried live before the run | Live |
|
|
720
|
+
| `video_matting` | One video (**≤ 10 minutes**, uploaded as-is with no proxy) | Transparent-background webm | Queried live before the run | Live |
|
|
721
|
+
| `video_blackborder_remove` | One local video | Video with black borders removed | Queried live before the run | Live |
|
|
722
|
+
| `video_canvas_adapt` | One local video; optional target width/height, clip range, canvas mode and audio-free output | Aspect-adapted video | Queried live before the run | Live |
|
|
723
|
+
| `video_stabilizer` | One local video; optional `fast` / `exp` / `turbo` | Stabilized video | Queried live before the run | Live |
|
|
724
|
+
| `video_vaporwave` | One local video; the filter takes an exact preset name | Vaporwave-filtered video | Queried live before the run | Live |
|
|
725
|
+
| `video_purify` | One local video; optional `full_screen` / `subtitle` / `custom` / `region`, `ffmpeg` / `raft`, a normalized ROI and region boxes with optional time ranges (only material you have the rights to modify) | One cleaned video | Queried live before the run | Live |
|
|
726
|
+
| `video_upscale` | One local video (**≤ 1 minute**); optional `2` / `3` / `4`× and `Reality` / `Anime` | One upscaled video | Queried live before the run | Live |
|
|
727
|
+
| `video_interpolate` | One local video; optional `2` / `3` / `4`×, with no extra one-minute limit | One frame-interpolated video | Queried live before the run | Live |
|
|
728
|
+
| `video_segment` | One local video; optional `--detector content\|adaptive`, `--threshold` | Shot-range structure in `result-output.json` (structured data, not a downloadable file) | Queried live before the run | Live |
|
|
729
|
+
| `video_ai_segment` | One local video; optional `--segment-mode scene\|shot_type\|narrative\|subject` | Semantic shot structure in `result-output.json` (structured data, not a downloadable file) | Queried live before the run | Live |
|
|
730
|
+
| `video_motion_cut` | One local video | Camera-move / highlight segment structure in `result-output.json` (structured data, not a downloadable file) | Queried live before the run | Live |
|
|
731
|
+
| `video_speaker_detect` | One local video; optional `--language`/`--max-faces-per-frame`/`--detect-body`/`--track-sample-fps` (GPU heavy) | Visible-speaker structure in `result-output.json` (the time base follows the server output) | Queried live before the run | Live |
|
|
732
|
+
| `video_face_track` | One local video; optional `--sample-fps`/`--max-faces`/`--min-face-ratio`/`--enable-body-match`/`--similarity-threshold`; `time_ranges` goes through `--params-json` (GPU heavy) | Person id / time span / trajectory structure in `result-output.json` (the time base follows the server output) | Queried live before the run | Live |
|
|
733
|
+
| `audio_tts_clone` | **No file**: one of `--text`/`--text-file` (≤ 5000 characters) plus a required `--speaker`; optional language/format/speed/segmentation/subtitles/**sentence pause** (`--fragment-interval <sec>`, **in-house voices only**; cloud voices **return an error** rather than silently ignoring it — the valid range is enforced server-side and stated in that error) | Voice-over audio wav/mp3 (plus optional subtitles); billed by character count — the unit and unit price come from what `gtrk tool list` shows live | Queried live before the run | Live |
|
|
734
|
+
| `video_ai_subtitle` | One video or audio file; `--language <code>` required; optional `--translate-language`, `--need-render`, `--need-pure`, `--subtitle-type`, `--subtitle-color`. By default only locally extracted audio is uploaded (the raw file never leaves your machine) | `.ass` subtitles + optional burned-in / subtitle-stripped `.mp4` + `result-output.json` (summary + word-level timeline) | Queried live before the run | Live |
|
|
735
|
+
| `subtitle_translate` | One **subtitle file** `.ass` / `.srt`; **both** `--language <code>` and `--translate-language <code>` are required; optional `--output-format`, `--line-mode`, `--bilingual`, `--subtitle-type`, `--subtitle-color`, `--canvas <WxH>`. No speech recognition | Translated subtitles `.ass` or `.srt` + `result-output.json` (entry counts + degradation flags) | Queried live before the run | Live |
|
|
736
|
+
| `video_translate_dub` | One video or audio file (**≤ 120 minutes**, uploaded whole); **all three of** `--language <source>`, `--translate-language <target>`, `--speaker <clone or voice code>` are required; optional `--ref <reference audio or video>` (only with `clone`; cloning someone else's voice requires that person's consent), `--ref-lang`, `--no-keep-bgm`, `--fit-policy`, `--speed-band <min,max>`, `--subtitle-mode`, `--subtitle-type`, `--project-formats <comma-separated>` (default: `.gtrk` only; add `jianying` to get a Jianying draft placed straight into your Jianying drafts folder — re-running the same source overwrites its previous draft, while a same-named source from another folder gets `…-2` instead), `--jianying-draft-dir`; valid values are decided server-side. Only the audio is replaced — the picture stays as it is (no lip sync); long sources take 15+ minutes | Dubbed video `<input-name>-dub.mp4` (`.mp3` for audio input) + `dub.wav` / `bgm.wav` + `.srt` subtitles + `transcript.json` + project files in per-format subfolders (`gtrk/`, `jianying/` …) + `result-output.json` (dub alignment report; includes `errors` when a side artifact is missing, without failing the run) | Queried live before the run | Live |
|
|
737
|
+
| `video_long2short_pro` | One long video (uploaded whole); `--language <code>` required; optional `--output-language`, `--main-topic`, `--output-size`, `--no-jump-cut`, `--duration-pref`, `--max-clip-sec`, `--split-screen`, `--split-orientation`, `--speed-factor`, `--no-camera-move`, `--no-subtitle`, `--subtitle-translate-language` | Finished clips `clip{i}.mp4` + the human-readable report `clips.md` (including polish-degradation details) + `result-output.json` | Queried live before the run | Live |
|
|
738
|
+
| `audio_separation` | One audio file; optional `--mode fast\|turbo` | Vocal and accompaniment audio (one or two items, depending on what is returned) | Queried live before the run | Live |
|
|
739
|
+
| `audio_speaker_split` | One audio file; optional `--only-struct` | Per-speaker `.wav` stems + a `spoken_list` timeline (`result-output.json`) | Queried live before the run | Live |
|
|
740
|
+
| `audio_stretch` | One audio file; optional `--semitones <n>`, `--speed <n>` (> 0) | Pitch/tempo-shifted audio | Queried live before the run | Live |
|
|
741
|
+
| `audio_noise_reduce` | One audio or video file; optional `--prop-decrease 0..1` | Denoised audio | Queried live before the run | Live |
|
|
742
|
+
| `audio_silence_remove` | One audio file; optional silence threshold and retained length | Silence-trimmed audio | Queried live before the run | Live |
|
|
743
|
+
| `piano_audio_to_midi` | One audio file | A MIDI file `.mid` | Queried live before the run | Live |
|
|
744
|
+
| `piano_audio_enhance` | One audio file | High-quality WAV + accompanying MIDI (two artifacts) | Queried live before the run | Live |
|
|
745
|
+
| `image_to_square` | One image; optional `--max-line <px>` (≤ 20000) | Square image | Queried live before the run | Live |
|
|
746
|
+
| `image_to_live` | One image | A short video of about 4 seconds `.mp4` (silent); or an Android motion photo `.jpg` plus the same clip as a companion `.mp4` | Queried live before the run | Live |
|
|
747
|
+
| `image_classic_template` | **Several images** + `--main-title` (required for covers; may be omitted with `--template-mode image`, collage only); optional subtitle/mode/ratio/quality/count/layout | Finished cover/collage (text/pic/render groups, possibly several images) | Queried live before the run | Live |
|
|
748
|
+
| `image_vertical_stitch` | **Several images** (order = top-to-bottom stitching order) | One vertically stitched long image | Queried live before the run | Live |
|
|
749
|
+
| `video_split_screen` | **2–16 video segments** (multiple positionals); the precise tier uses `--clips-json` (entries `{input:0-based index, begin_time_ms, end_time_ms, crop}`, millisecond time base); nine optional layout/aspect/audio parameters | One split-screen video (its length matches the shortest segment) | Queried live before the run | Live |
|
|
750
|
+
| `mad` | One material folder (3–10 videos) + optional `--bgm` | An AE master-composition project `.jsx` (AE only) | Only `--bgm` triggers a live price query | Live |
|
|
751
|
+
|
|
752
|
+
> Prices come from `gtrk tool list --json` and the anonymous live query printed to stderr before execution; this README stores no price snapshot. `video_matting` probes duration with ffprobe before uploading and rejects anything over 10 minutes outright (nothing is uploaded or submitted — trim it first).
|
|
753
|
+
> `mad` is the family's first **local-type "purely local tool with optional cloud extras"**: it runs without a key and triggers no billed job (technique data is delivered through a cloud manifest and cached in `~/.gitruck/mad-cache`, so **the first fetch needs the network and afterwards it runs offline**); only `--bgm` beat-syncing needs a key and triggers one cloud beat analysis. Three degradation tiers (key + beat sync / no key or bad BGM → fixed tempo / cloud failure → degraded) never crash. It produces only `.jsx` and supports AE only.
|
|
754
|
+
|
|
755
|
+
The seven shared video tools — black-border removal, aspect adaptation, stabilization, vaporwave, cleanup, upscaling and interpolation — accept only the server's current `video_ext`: `.mp4`, `.avi`, `.mpg`, `.mov`, `.flv`, `.mxf`, `.mpeg`, `.ogg`, `.3gp`, `.wmv`, `.h264`, `.m4v`, `.ts`; `.mkv` and `.webm` are rejected locally. Inputs must be local file paths — the CLI does not download remote videos.
|
|
756
|
+
|
|
757
|
+
- `gtrk tool list [--json]` — list every tool (name/description/input/output/live price/status); `--json` emits a single-line machine-readable array (including dynamic `billingHint`/`pricing`). **Works without an API key**; prices are queried anonymously through a public endpoint, and on failure the full list is still shown with an unavailable marker.
|
|
758
|
+
- `gtrk tool image_move ./photo.jpg [--motion zoom_in_center] [--json]` — image to camera move; artifacts land in `photo-image_move/`. `--motion` picks the camera move explicitly (26 values: 8 pans `up_to_down`/`down_to_up`/`left_to_right`/`right_to_left` plus four diagonals, 9 zoom-in anchors `zoom_in_{up,down,left,right,left_up,right_up,left_down,right_down,center}`, 9 zoom-out anchors `zoom_out_` at the same positions); when omitted the server picks one automatically. `--param width=1080 --param height=1920` overrides the derived geometry.
|
|
759
|
+
- `gtrk tool image_matting ./portrait.jpg` / `gtrk tool video_matting ./clip.mp4` — image/video matting.
|
|
760
|
+
- `gtrk tool image_blackborder_remove ./photo.jpg [--json]` — automatically crops black borders from one image.
|
|
761
|
+
- `gtrk tool image_canvas_adapt ./photo.jpg --canvas-width 1080 --canvas-height 1920 --canvas-type rectangle [--json]` — image aspect conversion; omitting the canvas parameters uses the server defaults. Per the actual runtime contract the canvas mode accepts only `normal`, `rectangle` and `square`, not the `fit` from older docs.
|
|
762
|
+
- `gtrk tool image_purify ./photo.jpg [--json]` — clean watermarks, logos or overlays from an image you have the rights to process.
|
|
763
|
+
- `gtrk tool image_purify ./photo.jpg --purify-scope region --purify-region 0.02,0.02,0.15,0.08 [--json]` — remove a box directly: no recognition, **everything inside the box is processed**; smaller boxes that fit the element tightly give better results.
|
|
764
|
+
- `gtrk tool image_purify ./photo.jpg --redraw [--json]` — Redraw mode: an image-editing model regenerates the whole image, which also clears semi-transparent or grid watermarks that cover it; with `--purify-scope region` only the inside of the boxes is replaced and everything outside stays identical to the original. **Priced separately** (the pre-run quote uses the redraw tier), with no free runs; the image is sent to a third-party model service outside mainland China and details may differ slightly from the original; if the content review refuses it, the task fails (error code 6054) and credits are refunded. `--params-json '{"purify_method":"redraw"}'` also works.
|
|
765
|
+
- `gtrk tool video_blackborder_remove ./clip.mp4 [--json]` — automatically crops black borders from one video while keeping the original audio.
|
|
766
|
+
- `gtrk tool video_canvas_adapt ./clip.mp4 --canvas-width 1080 --canvas-height 1920 --canvas-type rectangle --clip-start 1.5 --clip-end 4 --without-audio [--json]` — video aspect conversion; `--clip-start/--clip-end` are start/end times in seconds (decimals allowed; `--clip-start` must be less than the video duration, `--clip-end` must be greater than `--clip-start`, values past the end stop at the end), omitted fields use the server defaults, and the canvas mode accepts only `normal`, `rectangle`, `square`.
|
|
767
|
+
- `gtrk tool video_stabilizer ./clip.mp4 --stabilizer-method turbo [--json]` — video stabilization; supports `fast`, `exp` and `turbo`, where `exp` is experimental and you should check the result yourself.
|
|
768
|
+
- `gtrk tool video_vaporwave ./clip.mp4 --vaporwave-filter "灼熱苦夏" [--json]` — add a vaporwave filter using an exact preset name; omitting it explicitly uses `愈漸升溫`.
|
|
769
|
+
Before video cleanup, ask the user to choose fast FFmpeg blurring (basic results, visible traces possible) or slower RAFT content repair (usually more natural, not guaranteed lossless restoration). There is no default. Replace `<chosen-mode>` with the user-selected `ffmpeg` or `raft`; never switch modes after a failure without their agreement. The top-level `gtrk purify` uses `--purify-func-type`; detection, local editing and empty lists do not require a mode. Unsubmitted legacy journals need an explicit mode on resume; submitted jobs retain their original mode.
|
|
770
|
+
|
|
771
|
+
- `gtrk tool video_purify ./clip.mp4 --purify-scope custom --purify-method <chosen-mode> --purify-roi 0,0.78,1,0.2 [--json]` — clean a video you have the rights to modify; the ROI is a normalized `x,y,w,h` and is only used together with `custom`. `raft` supports videos under 20 minutes, `ffmpeg` has no such limit; restoring occluded content is not promised.
|
|
772
|
+
- `gtrk tool video_purify ./clip.mp4 --purify-method <chosen-mode> --purify-scope region --purify-region 0.8,0.02,0.18,0.08,0,5 --purify-region 0.3,0.85,0.4,0.1,120 [--json]` — remove boxes directly; repeat the option for more boxes (up to 16), each optionally followed by `start,end` in seconds (omit `end` to run to the end). No recognition — **everything inside the box is processed, including the main subject**; `ffmpeg` blurs the box while `raft` repaints it, and tighter boxes give better results. `--purify-region` only works with `region`.
|
|
773
|
+
- `gtrk tool video_upscale ./clip.mp4 --upscale-times 3 --upscale-type Anime [--json]` — experimental video upscaling; input up to 60 seconds, neither side may exceed 4000 px after scaling, supports `2`, `3`, `4`× and `Reality`, `Anime`.
|
|
774
|
+
- `gtrk tool video_interpolate ./clip.mp4 --interpolate-multiplier 3 [--json]` — frame interpolation; supports `2`, `3`, `4`×, does not apply the one-minute limit from older docs, and neither side of the source may exceed 4000 px.
|
|
775
|
+
- `gtrk tool video_segment ./clip.mp4 [--detector adaptive] [--threshold 27] [--json]` — mechanical shot segmentation; produces **structured** `result-output.json` (`scene_list` with each range's start/end/duration), not a downloadable file.
|
|
776
|
+
- `gtrk tool video_ai_segment ./clip.mp4 [--segment-mode shot_type] [--json]` — semantic shot segmentation; produces `result-output.json` (`categories[].shots[]` with shot size, tags, descriptions and second-level timecodes).
|
|
777
|
+
- `gtrk tool video_motion_cut ./clip.mp4 [--json]` — camera-move / highlight segments; produces `result-output.json` (`cut_points[]` with frame numbers, second-level timecodes and motion features).
|
|
778
|
+
- `gtrk tool video_ai_subtitle ./clip.mp4 --language zh [--translate-language en] [--need-render] [--subtitle-color 湖蓝]` — AI subtitles: `--language` is required, and it produces `.ass` subtitles + `result-output.json` (LLM summary + word-level timeline). **By default only locally extracted audio is uploaded** (the raw file never leaves your machine, and the geometry is sent along with the request); `--need-render` switches to **burning in locally with ffmpeg** (it errors out if `思源黑体 CN Bold` (Source Han Sans CN Bold) is missing rather than substituting another font); `--need-pure` needs the picture, so adding it uploads the whole video. The `subtitle_type`/`subtitle_color` enums and `content` are documented in the cloud API docs, and `--params-json '{"content":{...}}'` passes them through.
|
|
779
|
+
- `gtrk tool subtitle_translate ./movie.ass --language zh-CN --translate-language en-US [--bilingual] [--canvas 1080x1920]` — AI subtitle **translation**: move existing subtitles into another language; **both language parameters are required**. **The line between this and `video_ai_subtitle` is the input shape**: to recognize subtitles from audio or video use `video_ai_subtitle`; to move an existing `.ass`/`.srt` into another language use this one (no ASR re-run, and your existing proofreading is preserved). `--line-mode keep` keeps the timeline line for line with the input (so the track can directly replace the original), while the default `resegment` reads more naturally but changes line counts and timecodes. `.srt` files carry no canvas information, so **always pass `--canvas` for portrait output**, otherwise lines are wrapped for landscape and may run past the edge. Style options only apply to `ass` output; combining them with `srt` output is rejected server-side before any charge.
|
|
780
|
+
- `gtrk tool video_long2short_pro ./talk.mp4 --language zh-CN [--split-screen] [--speed-factor 1.1]` — long-to-short **fine cut**: finished clips in one shot, one `clip{i}.mp4` each plus the human-readable report `clips.md` (including polish-degradation details). **Division of labour with `gtrk long2short` (rough cut)**: the rough cut produces editable projects (gtrk/Jianying/Premiere), never uploads the raw file, and hands the result to a human for further editing; the fine cut produces only finished videos, uploads the whole file, and costs roughly twice as much. The deciding question: will you edit it afterwards? If yes, rough cut; if no, fine cut.
|
|
781
|
+
- The three above are **analysis-type tools**: their artifact is structured data in `result-output.json` (not downloadable media), so `result.json`'s `resultFile` points at it while `files` is empty and `ok=true` — that is normal.
|
|
782
|
+
- `gtrk tool audio_separation ./song.mp3 [--mode turbo]` — vocal/accompaniment separation; low-frequency fields such as `--param need_vocals=false` can still be passed through.
|
|
783
|
+
- `gtrk tool audio_speaker_split ./meeting.mp3 [--only-struct]` — speaker diarization: by default it produces per-speaker `.wav` files + `result-output.json` (the `spoken_list` timeline); `--only-struct` emits the structure without cutting files.
|
|
784
|
+
- `gtrk tool audio_stretch ./song.mp3 [--semitones -3] [--speed 1.5]` — pitch and tempo shifting; pitch and speed are independent, and `--speed` must be > 0.
|
|
785
|
+
- `gtrk tool audio_noise_reduce ./interview.mp4 [--prop-decrease 0.5]` — accepts audio or video and always outputs denoised audio.
|
|
786
|
+
- `gtrk tool audio_silence_remove ./talk.mp3 [--min-silence-len 800] [--desired-silence-len 200]` — removes over-long silences and writes only the processed audio.
|
|
787
|
+
- `gtrk tool piano_audio_to_midi ./piano.mp3` — transcribe piano audio into `.mid`.
|
|
788
|
+
- `gtrk tool piano_audio_enhance ./piano.mp3` — piano recording restoration, producing a high-quality WAV as the main artifact plus a companion MIDI.
|
|
789
|
+
- `gtrk tool image_to_square ./long.jpg [--max-line 8000]` — long image to square; `--max-line` defaults to 4000 and caps at 20000.
|
|
790
|
+
- `gtrk tool image_to_live ./photo.jpg [--output-format motion_photo]` — bring a still photo to life. By default the artifact is a silent `.mp4` video of about 4 seconds; `--output-format motion_photo` instead delivers an **Android motion photo** (a single `.jpg` with the clip embedded after the still image, so a gallery plays it on long-press), plus the same clip as a companion `.mp4`. Both formats cost the same. Compatibility: Android galleries that support the standard recognise and play it; **iOS does not** and shows a plain still image; a few Android models may only ever show the still.
|
|
791
|
+
- `gtrk tool image_classic_template a.jpg b.jpg c.jpg --main-title "新品速览"` — title + several images into a cover/collage; `--output-pic-count`/`--output-text-count` are clamped to ≤ 20 by the server. For a collage with no title, add `--template-mode image` and `--main-title` can be left out. A title containing characters the cover fonts cannot draw (emoji and the like) is rejected by the server before the task is created (error code 6046, no charge).
|
|
792
|
+
- `gtrk tool image_vertical_stitch top.png mid.png bottom.png` — stitch several images vertically in the order given.
|
|
793
|
+
- `gtrk tool video_split_screen a.mp4 b.mp4 --output-ratio 16:9` — simple tier: automatic split-screen layout over the whole clips (reaction / side-by-side comparison).
|
|
794
|
+
- `gtrk tool video_split_screen a.mp4 b.mp4 --clips-json '[{"input":0,"begin_time_ms":0,"end_time_ms":5000},{"input":1,"crop":{"x":0.1,"y":0,"width":0.8,"height":1}}]'` — precise tier: specify each segment's millisecond range and normalized crop box by 0-based index; the same file can appear several times to fill several windows.
|
|
795
|
+
- `gtrk tool video_speaker_detect ./talk.mp4 --language zh-CN` — detect who is speaking and when on screen, emitting structured JSON (GPU heavy).
|
|
796
|
+
- `gtrk tool video_face_track ./talk.mp4 --params-json '{"time_ranges":[{"begin_time":0,"end_time":30000}]}'` — face tracking / identity clustering, optionally limited to time ranges (**in milliseconds**; GPU heavy).
|
|
797
|
+
- `gtrk tool audio_tts_clone --text "欢迎收听本期节目" --speaker narrator` — text to voice-over audio (the voice list is in the website docs).
|
|
798
|
+
- `gtrk tool audio_tts_clone --text-file 稿子.txt --speaker sweet_female --output-format mp3` — long-form synthesis; by default it follows the speed and segmentation tuned for the chosen voice.
|
|
799
|
+
- `gtrk tool mad ./素材 [--bgm 歌.mp3] [--duration 20] [--seed 42] [--technique name,…] [--refresh] [--json]` — one-click MAD: scan the material folder → select techniques → a single `.jsx` (run it once in AE 2020+ to get the master-composition project). `--seed` makes it reproducible; `result.json` records the seed, data version, degradation tier and chosen techniques.
|
|
800
|
+
- `gtrk tool mad --technique <name | alias | pid,…>` — build from only the named techniques (without it, selection is rule-based sampling). An ambiguous or unknown name fails with a candidate list and writes nothing; a named technique with no windows in the pool is reported and skipped, the rest still build.
|
|
801
|
+
- `gtrk tool mad --search <keyword> [--json]` — look up the technique catalog without building anything: substring match over technique names, aliases and categories, listing name, category, `pid`, catalog frequency and pool window count. Mutually exclusive with `--technique`; both are free of charge and need no API key.
|
|
802
|
+
- Common flags: `--out <dir>` overrides the output folder, `--param k=v` (repeatable) / `--params-json '<object>'` pass cloud parameters through, `--reupload` ignores the upload cache, `--json` is machine-readable, `--ffmpeg-path <dir>` points at an ffmpeg directory.
|
|
803
|
+
- Cloud-type tools without a key → an error pointing you at `gtrk init`. A failed artifact download (e.g. an expired link 404) → `result.json` records `errors` with `ok=false`, and `task.json` is kept so you can recover by `taskId`.
|
|
804
|
+
- Cleanup, upscaling and interpolation are long-running GPU jobs, and their descriptors poll for up to 4 hours. A wait timeout does not mean the job was cancelled; keep `task.json` / `result.json` and recover by `taskId` instead of re-running and paying twice.
|
|
805
|
+
|
|
806
|
+
The companion skill is `/gtrk-tools` (one skill covering the whole tool family).
|
|
807
|
+
|
|
808
|
+
### `gtrk render <project.gtrk>` — render the finished video locally
|
|
809
|
+
|
|
810
|
+
```
|
|
811
|
+
gtrk render <gtrk> [-o <out.mp4>] [--crf <n>] [--codec <c>] [--ffmpeg-path <dir>]
|
|
812
|
+
[--no-qc] [--no-particles] [--particle-concurrency <n>] [-y|--yes]
|
|
813
|
+
[--no-open] [--json]
|
|
814
|
+
```
|
|
815
|
+
|
|
816
|
+
Treats the `.gtrk` as an EDL and renders it with local ffmpeg. **Footage always comes from the local originals** (`materials[].path`); the cloud never produces the finished file.
|
|
817
|
+
|
|
818
|
+
**What gets composited**: the base track (the lowest `track_index` that is not the black bed) plus every audio source, then **every visible overlay layer** stacked in contract z-order (ascending `track_index`, larger = closer to the front) — overlay video tracks (B-roll candidates, AI re-enactment) and the MG particles on `beat_track`. Composite particles are baked locally first (see `gtrk composite bake`, zero billing) and laid as the baked video on their layer; MG particles they fully cover are no longer cloud-rendered.
|
|
819
|
+
|
|
820
|
+
- **Visibility reads the `hidden` field only** (the client's "eye" toggle): a hidden track stays out of the cut entirely and is reported. The renderer never guesses which track belongs in the picture.
|
|
821
|
+
- **When several candidate tracks are visible, the topmost one wins** (exactly what the client preview shows). To pick a different one, hide or delete tracks in the client.
|
|
822
|
+
- Missing overlay footage (e.g. B-roll proxies not fully downloaded) **degrades instead of blocking**: that clip is not composited, a warning is printed, and the render still completes.
|
|
823
|
+
- **Things only the client draws stay out of the cut**: text added in the client (including captions laid by `gtrk subtitle lay`), stickers, graphics, effects, and the canvas background (`gtrk project background --scope canvas`). When the project has any, the command says once, before rendering, which kinds and how many, and points to local export in the client; it does not block or change the render. The `--json` result always carries `clientOnly` (`text / sticker / graphic / effect / other` counts and a `background` boolean, present even when all zero).
|
|
824
|
+
|
|
825
|
+
**The particle half is billed** (the only cloud egress of this command):
|
|
826
|
+
|
|
827
|
+
| Topic | How it works |
|
|
828
|
+
|---|---|
|
|
829
|
+
| Why the cloud | The CLI has no HTML render engine; particle pixels are authoritative in Gitruck Cloud's Hyperframes. Only the **particle HTML text** is uploaded — never the footage itself |
|
|
830
|
+
| Metering | **unique particles × cache misses** (`html_render_simple`, per minute). A particle used N times on the timeline is baked once |
|
|
831
|
+
| Cache | `<project dir>/.tonghe-cache/particles/<sha256>.mov`, sharing **the same key and location** as the client's Jianying export chain ⇒ whatever either side bakes, the other reuses |
|
|
832
|
+
| Confirmation | Any miss triggers an estimate (total / unique / misses / billed minutes) and a prompt; `--yes` skips it. **A full cache hit never prompts** (a free operation should not add friction) |
|
|
833
|
+
| `--json` | With misses and no `--yes`, the command **refuses** (machine mode has no stdin; it will not silently submit a billed task) |
|
|
834
|
+
| Escape hatch | `--no-particles` renders particle-free at zero cost; overlay video tracks are **still composited** (that part is purely local) |
|
|
835
|
+
| Declining | Exits with zero cloud calls and zero file writes |
|
|
836
|
+
|
|
837
|
+
`--particle-concurrency <n>` (1–8, default 6) tunes particle render concurrency.
|
|
838
|
+
|
|
839
|
+
The `--json` result carries `particles: {total,unique,cached,rendered,billedMinutes,skipped[]}` and
|
|
840
|
+
`overlay: {layers,particles,hiddenSkipped,missingMaterialSkipped,particleUnavailable}` — **everything skipped has a machine-readable path**, so "65 particles laid, none in the cut, exit code 0" cannot happen quietly.
|
|
841
|
+
|
|
842
|
+
A QC pass runs automatically afterwards and writes `.qc.json` (`--no-qc` skips it); QC findings are reported but never change the render's exit semantics (use `gtrk qc --fail-on` for a hard gate).
|
|
843
|
+
|
|
844
|
+
### Other
|
|
845
|
+
|
|
846
|
+
- `gtrk install [--api-key … -y --skill-agents codex,cursor --all-agents --copy-skills --skills-dir …]` — install everything in one command (skills + config + health check), modelled on Feishu's `lark-cli install`.
|
|
847
|
+
- `gtrk init [--api-key … --api-base … --jianying-draft-dir … -y]` — configuration only (interactive or not).
|
|
848
|
+
- `gtrk doctor` — health check (including the CLI version and whether a newer one exists).
|
|
849
|
+
- `gtrk cover embed <workbench.html> [--bg-16x9 <img>] [--bg-4x3 <img>] [--bg-3x4 <img>] -o <out.html>` — embed background images into the cover workbench: each image is compressed to JPEG for its size (long edge 16:9 ≤1280, 4:3 ≤1600, 3:4 ≤1400) and swapped in as base64 for `__BG_16_9__` / `__BG_4_3__` / `__BG_3_4__` (exporting PNG from a `file://` page requires embedded images). `-o` is required and may equal the input; placeholders for sizes without an image are kept and reported; the workbench gets a hint above 600 KB and a warning above 1 MB. Purely local, zero billing, no intermediate image files.
|
|
850
|
+
- `gtrk ai-drama validate <draft-storyboard.md> [...]` — production-side contract check for AI scene storyboards (same rules and output as `scripts/validate-storyboard.mjs` bundled with `/gtrk-ai-drama`): one JSON line per file; exit 0 when all pass, 1 when any fails, 2 when no file is given.
|
|
851
|
+
- `gtrk deps status` — show **where** ffmpeg/ffprobe, the render fonts and the composite-bake browser currently come from (`--ffmpeg-path` / `~/.gitruck` / system / missing), plus version, licence and source-code location.
|
|
852
|
+
- `gtrk deps install [--ffmpeg] [--font] [--browser] [--force]` — install runtime assets from the Gitruck Cloud mirror, **skipping anything already present**. Without flags it installs ffmpeg and fonts; `--browser` additionally installs the pinned chrome-headless-shell for composite baking (about 110 MB, into `~/.gitruck/browsers`, BSD licence, provenance and source in the mirror's `SOURCE.md`), **only when named explicitly**.
|
|
853
|
+
- **It never downloads silently**: any missing-dependency path only errors out and points at this command (the packages are 30–90 MB and the distributed artifacts carry licence obligations, so a user or agent must trigger it explicitly).
|
|
854
|
+
- Downloads are always https with **strict sha256 verification**; anything that fails verification is discarded and never lands. Extraction uses the **system tar** (bundled with Windows 10+/macOS/Linux), pulling in no third-party decompression dependency.
|
|
855
|
+
- The resolution order is unchanged: `--ffmpeg-path` → `~/.gitruck/ffmpeg` → system `PATH`. The mirror only fills the middle slot and **never overrides an ffmpeg you installed yourself**.
|
|
856
|
+
- Fonts come from the font catalog of the unified static-resource delivery (`https://api.ai-mcn.tv:9000/cloud/static/assets/fonts/catalog.json`, the same one the desktop client reads): `--font` installs the subtitle font the catalog names (Source Han Sans CN Bold, `sourcehansanscn-bold.otf`), `--font-family <family…>` installs whole families by `font_id` or Chinese / English family name; every file is checked against its sha256 and byte count, and a failed download errors out without leaving a partial file. An installed font is recognised by its normalised file name (the older `SourceHanSansCN-Bold.otf` counts too); `--force` re-downloads it under the catalog's name.
|
|
857
|
+
- Fonts land in `~/.gitruck/fonts` (that folder is the cache; no second copy goes to `~/.gitruck/cache/`) and are supplied to burn-in through the ffmpeg `ass` filter's `fontsdir` — **never installed into the system font table, never written to the registry, never requiring administrator rights**.
|
|
858
|
+
- The distributed ffmpeg is a GPLv3 build, and the corresponding source is provided alongside the binaries (see `SOURCE.md` at the distribution point); **downloads carry no additional usage restrictions**.
|
|
859
|
+
- `gtrk upgrade [--check]` — upgrade the CLI to the latest version + refresh skills (config preserved); `--check` only reports.
|
|
860
|
+
- `gtrk skills install [--agents codex,workbuddy,comate,…] [--all] [--copy] [--dir <skills dir>]` — install/refresh agent skills on their own; by default the generic adapter and the gtrk supplement layer detect hosts automatically.
|
|
861
|
+
- `gtrk skills recommend [--scene <id>] [--json]` — third-party skill catalog: without `--scene` lists the ten scenes (hook / mg-explainer / kinetic-text / data-viz / map / ai-drama / collage / caption / principles / technique); with a scene prints entries by tier (purpose / install command / license and dependencies / register command). **Recommend, never bundle**: the catalog ships with the package with a snapshot date; the command itself makes no network requests and keeps no state (usage statistics aside, see “Usage statistics, and how to turn them off”); stars and licenses are as of the snapshot, installing is your call. GPL / AGPL / non-commercial / unlicensed / MCP-SaaS-only skills are excluded. The catalog also lists Gitruck's own first-party MG layout-technique family (`--scene technique`, entries marked `origin: first-party`): techniques are not lane producers; the agent picks them per slot at the MG step.
|
|
862
|
+
- `gtrk skills add <owner/repo> [--skill <name>]... [--produces MG|AI_DRAMA|FILM_BROLL|script|none] [--column <id>] [--agents ...] [--all] [--copy]` — installs a third-party skill through the generic `skills` adapter and, on success, **appends** `{id, ref: "<owner/repo>#<skill>", produces, status: "third-party"}` (`"first-party"` for first-party entries) to the show config `style.skills` (idempotent per ref, nothing is registered on failure; `--produces` defaults to the catalog value, repos outside the catalog register with `routing:"none"`), after which `gtrk mg` / `/gtrk-ai-drama` resolve it by `produces`.
|
|
863
|
+
|
|
864
|
+
### Highlight discovery (internal preview)
|
|
865
|
+
|
|
866
|
+
`gtrk tool video_highlight <video> --out <project> [--no-audio] --json` uploads a locally generated 448p/4fps analysis proxy with a low-bitrate mono audio track by default (`--no-audio` to omit it); the original file is never uploaded. Inputs must be longer than 3 seconds and at most 30 minutes. Results contain three-second candidates grouped by request; scores cannot be compared across requests. Review candidates against the story and actual footage. Provider failure stays explicit; Vlog planning can continue with Agent material review. External billing is not enabled.
|