@gitruck/cli 1.0.8 → 1.1.1

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 CHANGED
@@ -253,7 +253,7 @@ gtrk transcript "D:/素材/采访视频.mp4" --json
253
253
  |---|---|---|
254
254
  | `<本地视频>` | 用户电脑上的视频文件;拒绝 URL、平台地址和远端下载 | 必填 |
255
255
  | `-o, --out <file>` | 唯一 Markdown 产物路径 | `<视频同目录>/<视频名>-transcript.md` |
256
- | `--lang <code>` | 识别语言 | `zh-CN` |
256
+ | `--lang <code>` | 识别语言(`zh-CN` 普通话 / `zh-HK` 粤语 / `en-US` / `ja-JP`…) | `zh-CN` |
257
257
  | `--ffmpeg-path <dir>` | 指定本地 ffmpeg/ffprobe | 自动解析 |
258
258
  | `--reupload` | 忽略上传缓存,强制重传抽取音频 | 关 |
259
259
  | `--json` | stdout 只留 `{ok,taskId,fileId,output,summaryPending}` | agent 必带 |
package/CHANGELOG.md ADDED
@@ -0,0 +1,66 @@
1
+ # 更新日志
2
+
3
+ ## 1.1.0(2026-09-02)
4
+
5
+ ### ⚠️ 升级须知:1.0.8 铺过的工程不会自愈
6
+
7
+ 1.0.8 有一处**槽位接缝**缺陷:铺出的主轨会带 −1 毫秒的同轨重叠,
8
+ `gtrk render` 检出后**硬拒**,成片渲不出来。
9
+
10
+ - **本版修掉了产生它的原因**,但**修不了已经铺坏的工程**。
11
+ - 手上有 1.0.8 铺的工程 ⇒ 重跑一次 `gtrk matrix lay --project <目录>`,
12
+ 或用 `gtrk patch trim` 逐颗修端点。
13
+ - 升级后打开旧工程仍渲不出,**不是新版没修好**,是那份工程还带着旧缺陷。
14
+
15
+ 另外:服务端的新编排逻辑 2026-09-01 已上线。**1.0.8 与它不配套**——
16
+ 本地复算自校验会判定不一致、弃用服务端产物改用本地编排,而那次调用**已经计费**。
17
+ 也就是说停在 1.0.8 的每一次云端编排都在白花钱。请尽快升级。
18
+
19
+ ### 快速模式不再留黑片
20
+
21
+ `--gap-fill fast` 的填充顺序从三级扩到五级:
22
+
23
+ 本 beat 候选 → 相邻颗粒延长 → **跨 beat 借候选** → **次地板补真画面** → 仍不够才黑片。
24
+
25
+ - **跨 beat 借**:某几句自己的候选被别的段先占光时,从全片没人用过的素材里取料。
26
+ 真机 `proj2-B` 的 B18 曾整段 8.952 秒落黑,而全片供给/需求是 4.10× ——
27
+ 不缺料,缺的是分配。借来的画面与那几句稿子相关性会弱一些,日志里**指名报出**。
28
+ - **次地板补真画面**:短于最小镜头长(1.2s)的残洞也填真画面。
29
+ 这些是快切,同样指名报出。真机三条片的黑片从 8 处降到 **0 处**。
30
+ - **逐步模式(`--gap-fill solid`)刻意保留黑片**——黑的地方就是没匹配上的地方,
31
+ 精修时一眼看得见。两档的差别现在不只是「停几次」,是**产物形态不同**。
32
+
33
+ ### 新增:`gtrk audio tighten`
34
+
35
+ 收紧配音的**句间**停顿,纯本地零计费。
36
+
37
+ ```bash
38
+ gtrk audio tighten --project <工程目录> --dry-run # 先看会压几处
39
+ gtrk audio tighten --project <工程目录> # 落盘
40
+ ```
41
+
42
+ - 真机实测:一条 203 秒的解说里 54 秒是句间静音(26.6%),收到 0.2 秒后全片缩到 171 秒。
43
+ - **只压跨句界的停顿**,句内换气与原声引用段一律不动。
44
+ - 产物是**原件多 clip 铺轨**,不烤新音频文件 —— 每处停顿都是可拖的刀口,随时能退回原样。
45
+ - ⚠️ 它会改变 beat 窗口,**跑完必须重铺**(命令会提醒)。建议在铺画面**之前**跑。
46
+
47
+ ### 新增:`--fragment-interval`(TTS 句间停顿)
48
+
49
+ ```bash
50
+ gtrk tool audio_tts_clone --text-file 稿.txt --speaker <音色> --fragment-interval 0.2
51
+ ```
52
+
53
+ **仅自训音色生效**;云引擎音色传了会**明确报错**,不会静默忽略。
54
+ 不传时产物与本版之前逐字节一致。云引擎音色请改用上面的 `gtrk audio tighten`。
55
+
56
+ ### 其它
57
+
58
+ - 幂等回放时不再误报「已执行并计费」——服务端命中缓存回放时本就不二次扣费,
59
+ 旧版会无条件断言已计费,把用户引向一笔不存在的账。
60
+ - 随包文档订正:`audio_tts_clone` 的文本上限是 **5000 字**(旧文写 2000);
61
+ 计量单位与单价一律以 `gtrk tool list` 实时显示为准,文档不再写死。
62
+
63
+ ### 已知问题
64
+
65
+ - 极少数情况下主轨会留下 **1 毫秒**级的黑片或裸缝(30fps 下 0.03 帧,渲染不可见)。
66
+ 已立案追踪,不影响出片。
package/README.en.md CHANGED
@@ -41,7 +41,7 @@
41
41
  | 🔎 | `gtrk matrix` | B-roll retrieval + **candidate track laying**: consumes the FILM_BROLL dispatch → produces a candidate list + downloads preview proxies and lays N candidate tracks (`--lay N`, default 1; open it in opencut and toggle track visibility to compare; `--lay 0` produces the list only); `matrix search "<query>"` is a one-off ad-hoc search; `matrix fetch <clip_id...>` pulls raw footage during the fine cut (free re-signing + download for already-granted materials, drag straight into Jianying); **local-footage mode**: `matrix index --dirs <folders>` builds a slice-free index → `--local --dirs` retrieves and lays tracks (**your footage never leaves your machine**) → `matrix lay` consumes the (editable) plan; `matrix describe` understands candidates on demand |
42
42
  | 🎨 | `gtrk mg` | MG motion-graphics particle laying: consumes the MG dispatch → lays html-particle assets (transparent overlay / full-screen bed, produced by your show's MG skill) into the `.gtrk` `beat_track`; `mg lint <particle.html>` runs the statically checkable subset of the house rules, `mg status --project <dir>` is an orchestration dashboard; `mg render <particle.html> --duration <sec>` renders a single particle in the cloud, independent of any project, into a Jianying-readable qtrle transparent MOV (the fine-cut supplement channel); aux overlay particles can be layered on the same span (one beat derives a main particle plus `-aux<n>`). The old name `gtrk rrv` remains as a deprecated alias |
43
43
  | 🎙️ | `gtrk project init` | Audio-first project bootstrap: build a `.gtrk` project from a voice-over — main path `--tts-task <task_id>` references a completed TTS task (fetches the audio plus sentence timecodes directly, zero ASR); fallback path `--audio`+`--transcript` takes your own voice-over as a pair. Once landed, `gtrk split --project` continues the production pipeline as usual |
44
- | 🎼 | `gtrk audio lay` | Audio-track atom: appends an audio track to a `.gtrk` project (BGM/score; idempotent same-source replacement, no track pile-up); `--beat-align` runs cloud beat analysis and snaps the in-point to the nearest downbeat (billed once; degrades gracefully without a key or on failure) |
44
+ | 🎼 | `gtrk audio lay` / `tighten` | Audio-track atoms: `lay` appends an audio track to a `.gtrk` project (BGM/score; idempotent same-source replacement, no track pile-up); `--beat-align` runs cloud beat analysis and snaps the in-point to the nearest downbeat (billed once; degrades gracefully without a key or on failure). `tighten` tightens the pauses between sentences in the voice-over (purely local, zero billing; only silence straddling a sentence boundary is compressed, within-sentence breaths untouched) |
45
45
  | 🎯 | `gtrk audio align` | Audio-video alignment part (fully local, zero billing): cross-correlates an external audio recording (lav mic / recorder) against the video to measure offset + confidence; high confidence swaps the track directly (video stream untouched byte-for-byte), low confidence emits an alignment project for the client timeline, then `--resume` reads the confirmed offset back; `--offset` swaps at an explicit offset |
46
46
  | 🧰 | `gtrk tool <name>` | Single-shot tool family: image-to-camera-move, image/video matting, image black-border removal / aspect adaptation / cleanup / square conversion / LivePhoto, smart collage covers and vertical stitching (multi-image input), video black-border removal / aspect adaptation / stabilization / vaporwave filter / mechanical & semantic shot segmentation / motion highlights / AI subtitles, vocal-accompaniment separation / speaker diarization / pitch-and-tempo shift, piano-to-MIDI and piano restoration, audio denoising, silence removal, MAD, and more; `gtrk tool list` shows every input/output/live price/status. Single request, single result, shared runner — adding a tool means adding one descriptor |
47
47
  | 💬 | `gtrk feedback` | Tell us what feels wrong: `gtrk feedback "<one line>" --command <command>`. **Disclosed submission** — when an assistant files it for you it must first read the exact content back to you and only add `--disclosed` once you agree; in a pipe or any non-interactive environment, sending without that declaration is refused outright. Content is redacted before it leaves your machine (local paths, credentials, e-mail addresses, phone numbers and the like are replaced by shape), so what you are shown is exactly what gets sent |
@@ -197,6 +197,13 @@ CLI 写 .gtrk ─▶ 客户端打开(自动感知外部改动、先存脏改再
197
197
 
198
198
  ## Upgrading
199
199
 
200
+ > **Read this first if you are coming from 1.0.x**: projects laid by 1.0.8 and earlier carry a slot-seam
201
+ > defect (a −1 ms same-track overlap on the main track, which `gtrk render` hard-rejects). **This release
202
+ > fixes the cause but cannot repair projects that were already laid** — re-run
203
+ > `gtrk matrix lay --project <dir>` on any existing project. If an old project still fails to render after
204
+ > upgrading, that is the old defect baked into that project, not a regression in this release.
205
+ > See the [CHANGELOG](./CHANGELOG.md).
206
+
200
207
  **CLI + skills** (config preserved as-is):
201
208
 
202
209
  ```bash
@@ -463,6 +470,8 @@ gtrk patch set --project <dir> --track audio:1 --at 3.0 --volume 0.5
463
470
  >
464
471
  > **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.
465
472
  >
473
+ > **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`.
474
+ >
466
475
  > **Material-on-disk self-check**: after writing back the project it verifies that every `materials[].path` really is on disk (**read-only, reports without touching anything**). Relative paths are always resolved against the **directory containing the `.gtrk` file** (`<output>/gtrk/`). `--json` emits `integrity:{ checked, counts, dangling:[…], danglingReferenced, danglingOrphan, external:[…], noPathIds:[…] }` — `dangling` is the complete list of **broken references** among project-owned materials (registered but missing on disk), each flagged with **whether the timeline references it** and where (a referenced one means that span has no media to show, far worse than an orphan); missing absolute paths are counted separately as `external` (an unmounted external drive looks like this too, so it does not pollute the main verdict); http(s) materials are only counted and **no network requests are made**. **This informs, it does not block**: broken references do not change `ok`, do not change the exit code, and no material entry or file is deleted. They are usually historical residue (e.g. an interrupted "confirm source clip" download); the fix is to re-confirm the source clip in the client or delete that clip. Runs that never wrote back (`--lay 0` / refused / missing project) **emit no `integrity` field** — absence means "not checked this time", not "checked and clean".
467
476
  >
468
477
  > **The solid black bed track**: by default a solid black track is laid beneath all candidate tracks and above the talking-head main track (`struct_meta.broll.black_track` records its `track_index`), covering the full landed beat envelope so that during B-roll (including the empty spots on candidate tracks) the talking-head picture underneath is not exposed. **The cost is "black holes"**: wherever candidate tracks are not filled, pure black covers the talking-head, and track laying computes exactly that — `--json` always emits `lay.blackBedHoleSec` plus per-span `lay.blackBedHoles`, and a non-fatal warning is added when a single span is ≥ 3 s or a single beat's ratio is ≥ 15 % (it does not change the exit code or block laying). Use it to adjust `--score-floor`, switch to `--no-black-bed`, or patch by hand in the client. The bytes land at `assets/builtin/solid-000000-<W>x<H>.png`, sharing an id namespace with the client's built-in solid material and reused idempotently. Do not delete it by accident when removing candidate tracks; to swap footage, drag onto a candidate track's clip and **not onto the black bed** — since client 0.2.10 (force-updated release on 2026-07-31) **dropping onto the black bed is rejected outright with a message**. On clients older than 0.2.10 (force update not yet pulled) the old behaviour silently creates a new video track and inserts there; if it lands in the lower half you cannot see it in the preview at all (one `Ctrl+Z` undoes the whole thing) — restart the client first to pick up the force update. If you do not want the black bed, re-run with `--no-black-bed` and it is stripped clean.
@@ -470,8 +479,8 @@ gtrk patch set --project <dir> --track audio:1 --at 3.0 --volume 0.5
470
479
  **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):
471
480
 
472
481
  ```bash
473
- gtrk matrix index --dirs <folder1,folder2> # ① build a slice-free index: content-fingerprint incremental, resumable; renames/moves are not recomputed
474
- gtrk matrix --local --dirs <folder1,folder2> --project <dir> # ② local retrieval + track laying (--lay 0 = plan only, no laying)
482
+ gtrk matrix index --dirs <folder-or-file,...> # ① build a slice-free index: content-fingerprint incremental, resumable; renames/moves are not recomputed
483
+ 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)
475
484
  gtrk matrix lay --project <dir> [--plan <path>] # ③ consume the (edited) plan and lay tracks, zero retrieval cost
476
485
  ```
477
486
 
@@ -479,9 +488,19 @@ gtrk matrix lay --project <dir> [--plan <path>] # ③ consume the
479
488
  - **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`.
480
489
  - **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.
481
490
  - **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`.
482
- - **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, results injected into the plan and cached locally, cache hits are free, >20 frames triggers a confirmation guard); `--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).
491
+ - **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).
483
492
  - **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.
484
493
 
494
+ **`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, `--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.
495
+
496
+ > ⚠️ **`is_copyright` means "may this be used commercially", not "is this under copyright"**: `true` = **commercially usable** (owned ∪ licensed), `false` = **not commercially usable**.
497
+ >
498
+ > **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.
499
+ >
500
+ > This warning comes from a real incident: on 2026-09-02 an AI operator **deliberately picked `false` twice in a row** as the "safe" option and laid non-commercial material into 5 projects, while the only safe value, `true`, was actively avoided. So under `--json` the CLI now **derives a plain-words label `copyright_label`** per result (`"可商用"` = commercially usable / `"不可商用"` = not) — derived from `is_copyright`, always in the same direction, absent whenever `is_copyright` is absent. Read either key; never infer from the field name.
501
+ >
502
+ > 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).
503
+
485
504
  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`.
486
505
 
487
506
  ### `gtrk mg` — MG motion-graphics particles (lay / lint / status / render)
@@ -521,23 +540,28 @@ Consumes the `dispatch.mg` dispatch landed by `gtrk split`, laying html-particle
521
540
  > **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".
522
541
  > **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.
523
542
 
524
- ### `gtrk project init` / `gtrk audio lay` — audio-first project atoms (voice-over first)
543
+ ### `gtrk project init` / `gtrk audio lay` / `gtrk audio tighten` — audio-first project atoms (voice-over first)
525
544
 
526
- 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.
545
+ 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.
527
546
 
528
547
  | Command | What it does |
529
548
  |---|---|
530
549
  | `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/` |
531
550
  | `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) |
532
- | `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.3, bed volume), `--offset <ms>` sets the in-point |
551
+ | `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), `--offset <ms>` sets the in-point |
533
552
  | `gtrk audio lay … --beat-align` | Cloud beat analysis (`audio_music_analyze`, billed once) snaps the in-point to the nearest downbeat; without a key / on analysis failure / out of range it degrades to no alignment — the command never fails over it |
553
+ | `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` (measured, accepted values — tune them for another subject or voice) |
534
554
 
535
555
  `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).
536
556
 
557
+ > **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.
558
+
537
559
  ### `gtrk tool <name> [inputs...]` — the single-shot tool family
538
560
 
539
561
  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.
540
562
 
563
+ **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).
564
+
541
565
  | Tool | Input | Output | Billing | Status |
542
566
  |---|---|---|---|---|
543
567
  | `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 |
@@ -558,7 +582,7 @@ Standalone single-request capabilities, kept separate from the pipeline's lane c
558
582
  | `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 |
559
583
  | `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 |
560
584
  | `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 |
561
- | `audio_tts_clone` | **No file**: one of `--text`/`--text-file` (≤ 5000 characters) plus a required `--speaker`; optional language/format/speed/segmentation/subtitles | 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 |
585
+ | `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 |
562
586
  | `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 |
563
587
  | `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 |
564
588
  | `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 |
package/README.md CHANGED
@@ -41,7 +41,7 @@
41
41
  | 🔎 | `gtrk matrix` | B-roll 检索+**候选铺轨**:消费 FILM_BROLL 派单 → 产候选清单 + 下载 preview 代理铺 N 条候选轨(`--lay N` 默认 1,opencut 打开即可用轨道小眼睛对比;`--lay 0` 只出清单);`matrix search "<词>"` 单条 ad-hoc;`matrix fetch <clip_id...>` 精剪期拉原片(已授予素材免费重签+下载落盘,直接拖进剪映);**本地素材模式**:`matrix index --dirs <素材夹>` 免切片建索引 → `--local --dirs` 检索铺轨(**素材本体不上云**)→ `matrix lay` 消费(可编辑的)plan;`matrix describe` 按需理解候选 |
42
42
  | 🎨 | `gtrk mg` | MG 动态图颗粒铺轨:消费 MG 派单 → 把 html-particle 颗粒(透明叠加 / 满屏底层,由你栏目的 MG 生产 skill 所产)铺进 `.gtrk` 的 beat_track;`mg lint <颗粒.html>` 铁律静态子集校验、`mg status --project <dir>` 编排看板(缺 HTML / 已产未铺 / 已铺);`mg render <颗粒.html> --duration <sec>` 脱离工程独立云渲单颗颗粒为剪映可读 qtrle 透明 MOV(精剪补给口);aux 叠层颗粒同段多铺(一 beat 派生主 + `-aux<n>`)。旧名 `gtrk rrv` 保留为弃用别名 |
43
43
  | 🎙️ | `gtrk project init` | 音频驱动工程起盘:从一条配音建 `.gtrk` 工程——主路 `--tts-task <task_id>` 引用已完成的 TTS 配音任务(直取产物音频+句级时码,零 ASR);兜底 `--audio`+`--transcript` 自备配音成对给。落好即可 `gtrk split --project` 接成片流水线 |
44
- | 🎼 | `gtrk audio lay` | 音频轨零件:往 `.gtrk` 工程追加一条音频轨(BGM/配乐上轨,同源幂等替换不堆轨);`--beat-align` 云端节拍分析把入点吸附最近 downbeat(计费一次,无 Key/失败自动降级不失败) |
44
+ | 🎼 | `gtrk audio lay` / `tighten` | 音频轨零件:`lay` 往 `.gtrk` 工程追加一条音频轨(BGM/配乐上轨,同源幂等替换不堆轨);`--beat-align` 云端节拍分析把入点吸附最近 downbeat(计费一次,无 Key/失败自动降级不失败)。`tighten` 收紧配音的句间停顿(纯本地零计费,只压跨句界的静音、句内换气不动) |
45
45
  | 🎯 | `gtrk audio align` | 音画对轨零件(纯本地零计费):外录音轨(领夹麦/录音笔)与视频互相关测偏移+置信度;高置信直接换轨(视频流零像素改动),低置信产对齐工程交客户端拖齐后 `--resume` 读回;`--offset` 显式偏移直换 |
46
46
  | 🧰 | `gtrk tool <name>` | 单点工具族:图转运镜、图片/视频抠像、图片去黑边/比例转换/净化/转方图/LivePhoto、智能拼图封面/拼长图(多图输入)、视频去黑边/比例转换/防抖/蒸汽波滤镜/机械·智能分镜/运镜高光/智能字幕、人声伴奏分离/说话人分轨/变调变速、钢琴转MIDI/修复、音视频降噪、静音移除、MAD 等;`gtrk tool list` 查全部输入/产物/实时价格/状态。单发单收、共享 runner,接新工具只加一个 descriptor |
47
47
  | 💬 | `gtrk feedback` | 把用得不顺手的地方反馈给我们:`gtrk feedback "<一句话>" --command <命令名>`。**告知式提交**——助手代提时必须先把要发的内容原样念给你、得到同意后才加 `--disclosed` 重跑;管道/非交互环境下没有这句声明会直接拒发。发送前内容会先做一遍脱敏(本机路径、凭据、邮箱、手机号等按形态替换),你看到的就是将要发出的那一份 |
@@ -195,6 +195,11 @@ CLI 写 .gtrk ─▶ 客户端打开(自动感知外部改动、先存脏改再
195
195
 
196
196
  ## 升级
197
197
 
198
+ > **从 1.0.x 升上来的先看这一条**:1.0.8 及更早版本铺出的工程带一处槽位接缝缺陷
199
+ > (主轨 −1 毫秒同轨重叠,`gtrk render` 会硬拒)。**本版修掉了产生它的原因,但修不了已经铺坏的工程**——
200
+ > 手上有旧工程就重跑一次 `gtrk matrix lay --project <目录>`。升级后旧工程仍渲不出,
201
+ > 不是新版没修好,是那份工程还带着旧缺陷。详见 [CHANGELOG](./CHANGELOG.md)。
202
+
198
203
  **CLI + skill**(配置原样保留):
199
204
 
200
205
  ```bash
@@ -481,6 +486,8 @@ gtrk patch set --project <dir> --track audio:1 --at 3.0 --volume 0.5
481
486
  >
482
487
  > **重跑会剥旧重铺,但不碰你改过的轨**:候选轨的身份按「素材前缀 + 上一轮登记指纹」认,不再认轨号(客户端保存会把 overlay 轨整体重编号)。一旦某条候选轨被判定「你编辑过」(改过 clip,或在客户端确认过原片使 material 变成 `broll-raw-*`),本次**整体不铺**:不剥任何轨、不追加新轨、`.gtrk` 逐字节不变,`broll-plan.json` 照常产出,命令给出「哪条轨 / 什么证据 / 下一步」并以非 0 退出码结束(`--json` 出 `{ok:false, refused:[…]}`)。要强行重铺加 `--force-relay`。
483
488
  >
489
+ > **机读账面:`counts.results` 是「去重前」口径**:`--json` 的 `counts.results` 恒是**逐 query 累加的检索响应条数**(既有口径不动)——15 条 query 各命中同一条素材时它就是 15,而 plan 落盘可能只有 8 行、只对应 1 个素材。要判「到底有多少料」读派单消费模式另出的三键:`counts.zero_yield`(**真·零产出**的 query 数,判据取**检索响应**为空,而非事后扫 plan 的 `results: []`——beat 内去重会把命中折进同 beat 的兄弟 query,折叠 ≠ 零产出)、`counts.plan_results`(plan **落盘后**的实际 result 行数,去重后)、`counts.distinct_clips`(plan 内 distinct `clip_id` 数)。这三键**只在派单消费模式**出现,ad-hoc `matrix search` 与 `matrix lay` 的 `counts` 逐字节不变(**缺席 = 没这个概念,不是「测出来是 0」**)。铺轨侧同理另出 `lay.beatsWithCandidates`(有候选的 beat 数)与 `lay.emptyBeats`(**零候选 beat 名单**——整段没有任何可铺的画面),两者恒满足 `beatsWithCandidates + emptyBeats.length = plan 的 beat 总数`。
490
+ >
484
491
  > **素材落盘自检**:写回工程之后自动查一遍 `materials[].path` 是不是真的都落盘了(**只读、只报不动**)。相对路径恒以 **`.gtrk` 文件所在目录**(`<产物目录>/gtrk/`)为基准解析。`--json` 出 `integrity:{ checked, counts, dangling:[…], danglingReferenced, danglingOrphan, external:[…], noPathIds:[…] }`——`dangling` 是工程自带素材的**悬空引用**(登记在、文件不在)全量清单,每条标出**是否被时间线引用**及引用位置(被引用 = 那一段没素材可放,比孤儿严重得多);绝对路径缺失另计 `external`(外接盘没挂载也会这样,不混进主判);http(s) 素材只计数、**不发网络请求**。**这是告知不是拦阻**:查出悬空不改 `ok`、不改退出码、不删任何素材条目或文件。悬空多半是历史遗留(如客户端「确认原片」下载中断),修法是在客户端重新确认原片或删掉那条 clip。没写回的运行(`--lay 0` / 拒铺 / 工程缺失)**不出 `integrity` 字段**——缺席 = 本次没查,不是「查过且干净」。
485
492
  >
486
493
  > **纯黑底垫轨**:默认在全部候选轨之下、口播主轨之上垫一条纯黑底轨(`struct_meta.broll.black_track` 记其 `track_index`),按已落成的 beat 包络整条铺满,使 B-roll 期间(含候选轨留空处)不漏出底下的口播画面。**代价是「黑底空洞」**:候选轨没填满的地方就是纯黑压口播,铺轨会把它算出来——`--json` 恒出 `lay.blackBedHoleSec` 与逐段的 `lay.blackBedHoles`,单段 ≥ 3s 或单 beat 占比 ≥ 15% 时另出一条非致命告警(不改退出码、不阻断铺轨),可据此调 `--score-floor`、改用 `--no-black-bed`、或到客户端手动补片。字节落 `assets/builtin/solid-000000-<W>x<H>.png`,与客户端内置纯色素材同 id 命名空间、幂等复用。删候选轨时别误删它;换片请拖到候选轨颗粒上、**别拖到黑底条上**——客户端 0.2.10 起(2026-07-31 发版强更)**拖到黑底条上会被直接拒绝并提示**。若客户端仍是 0.2.10 之前旧版(强更未拉到),旧行为是静默新建一条 video 轨插入、落点在下半区时预览完全看不见(按一次 `Ctrl+Z` 可整条撤销)——先重启客户端吃到强更。不想要黑底加 `--no-black-bed` 重跑即剥净。
@@ -488,8 +495,8 @@ gtrk patch set --project <dir> --track audio:1 --at 3.0 --volume 0.5
488
495
  **本地素材模式(`matrix index` / `--local`)**:素材不必入云端素材库,用你本地的素材文件夹(视频+图片混合)直接检索铺轨:
489
496
 
490
497
  ```bash
491
- gtrk matrix index --dirs <素材夹1,素材夹2> # ① 免切片建索引:内容指纹增量、断点续传,素材改名/移动不重算
492
- gtrk matrix --local --dirs <素材夹1,素材夹2> --project <目录> # ② 本地检索铺轨(--lay 0 = 只出 plan 不铺轨)
498
+ gtrk matrix index --dirs <素材夹或素材文件,...> # ① 免切片建索引:内容指纹增量、断点续传,素材改名/移动不重算
499
+ gtrk matrix --local --dirs <素材夹或素材文件,...> --project <目录> # ② 本地检索铺轨(--lay 0 = 只出 plan 不铺轨;传单个素材文件即把检索域收窄到它)
493
500
  gtrk matrix lay --project <目录> [--plan <path>] # ③ 消费(可编辑后的)plan 铺轨,零检索开销
494
501
  ```
495
502
 
@@ -497,9 +504,19 @@ gtrk matrix lay --project <目录> [--plan <path>] # ③ 消费(
497
504
  - **图片一视同仁**:图片可检索可铺轨;被选中时经云端 `image_move` 转 5 秒运镜视频入轨——**图片本体会上云**(2 积分/张,铺轨前汇总确认;同图同参恒复用不重复扣费)。零图片上云 → `--no-image-broll`。
498
505
  - **同素材不二用**:单轮铺轨一个素材单元全局只用一次(本地视频按场景、图片按文件),候选枯竭宁空不重复;`--dedup-scope material` 收严到文件级。
499
506
  - **含本地素材的工程不能云渲**:提交会被拒(`local_broll_cloud_render_rejected`)——走客户端本地出片或 `gtrk render`。
500
- - **可选零件**:`matrix describe --plan <path> [--top-k N]` / `--materials <a,b>` 按需理解候选(VLM 描述/标签/质量分/水印·字幕·黑边·模糊信号,1 积分/张、产物注入 plan 并本地缓存、缓存命中零计费、>20 张确认护栏);`--source-window <start,end>` 源时间窗过滤(仅 `--local`,影视解说式「第 N 段解说配影片第 N 段邻域画面」);`matrix lay --mark-weight <0..1>` 把 describe 的质量分融进候选排序(融合分 = sim×(1-w)+(mark/100)×w,只重排序不改准入,无缓存候选按中性处理)。
507
+ - **可选零件**:`matrix describe --plan <path> [--top-k N]` / `--materials <a,b>` 按需理解候选(VLM 描述/标签/质量分/水印·字幕·黑边·模糊信号,1 积分/张(**异步任务计费**:提交预扣→完成结算,失败自动退款;同合云内部成员豁免,跑时自动探测,`--json` 的 `credits_estimated` 即实耗、`credits_would_be` 为原价)、产物注入 plan 并本地缓存、缓存命中零计费、>20 张确认护栏)。**一条 describe 只代表一段**:`--plan` 形态每个候选只抽 `segments[0]` 的 best 一帧,产物带射程锚点 `describe.at_sec`(素材时基秒),跑完报「理解覆盖率 = 理解帧数 / 被理解候选携带的**段总数**」(`--json` 读 `describe_coverage`)——注入 N 条 ≠ 这 N 条候选都被看过;`--source-window <start,end>` 源时间窗过滤(仅 `--local`,影视解说式「第 N 段解说配影片第 N 段邻域画面」);`matrix lay --mark-weight <0..1>` 把 describe 的质量分融进候选排序(融合分 = sim×(1-w)+(mark/100)×w,只重排序不改准入,无缓存候选按中性处理)。
501
508
  - **索引参数与量纲**:`--scene-threshold` 调场景切分粒度、`--stability-threshold` 固定机位判稳收敛抽帧、`--rebuild` 强制重建(理解缓存不清);索引跨机不可移植(键=绝对路径,换机重跑 index 即可)。本地 score 量纲与云端不同(完美命中可低至 ~0.25),`--score-floor` 别按云端直觉调高。
502
509
 
510
+ **`gtrk matrix material "<词>"`(通用三态素材检索)**:与上面的 B-roll 检索并列的第二条线,出**整条素材**的下载直链(不是段落)——`--scope clip|image|audio`(缺省 `audio`,BGM 主场)、`--commercial-only` 只搜可商用、`--min-duration/--max-duration` 按成片时长挑、`--top-k`(缺省 5,服务端上限 50)、`--diversity` 去同质、`--json` 机读、`--out` 落盘。
511
+
512
+ > ⚠️ **`is_copyright` 读作「能不能商用」,不是「有没有被版权保护」**:`true` = **可商用**(自有 ∪ 已授权),`false` = **不可商用**。
513
+ >
514
+ > **`false` 不要读成「无版权、可以随便用」——它恰恰相反。** 决定性反证:他人版权的概念素材入库固定写 `is_copyright=0`;这个字段若真是「是否受版权保护」,那批必须是 1。
515
+ >
516
+ > 这条警示是真机踩出来的:2026-09-02 有 AI 执行方连着两轮**特意去挑 `false`** 当「安全选择」,把不可商用素材铺进了 5 个工程,而唯一安全的 `true` 反倒被主动避开。所以 `--json` 里 CLI 会逐条**派生一个人话标签 `copyright_label`**(`"可商用"` / `"不可商用"`)——它由 `is_copyright` 推出、与之恒同向、缺席同缺席,判读认这两个键之一即可,别靠字段名去猜。
517
+ >
518
+ > 该字段**只有矩阵成员口才有**:公开口没有它不是「不可商用」,而是服务端在源头就只放可商用素材(缺席即无需判,CLI 如实缺省、绝不补假值)。
519
+
503
520
  编排配方(纯匹配 / 先理解后铺 / 时间窗 / 素材先行编剧 / 三层层叠)与 plan 编辑口径见随包 skill `/gtrk-matrix`。
504
521
 
505
522
  ### `gtrk mg` — MG 动态图颗粒(铺轨 / lint / status / render)
@@ -539,23 +556,28 @@ gtrk matrix lay --project <目录> [--plan <path>] # ③ 消费(
539
556
  > **aux 叠层颗粒**:`gtrk split` 若在某 beat 的 `aux_layers` 派了 `overlay` 颗粒,会派生 `<beat>-aux<n>` 合成条目进 `dispatch.mg`——`gtrk mg` 一并铺,实现「同段既有底轨主视觉、又叠透明概念图解」。
540
557
  > **双读兼容**:`dispatch.mg`(读旧 `rrv_mg`)、源目录 `mg/`(读旧 `rrv/`)、素材前缀 `mg-`(读旧 `rrv-`)——去品牌化前的既有工程零迁移。
541
558
 
542
- ### `gtrk project init` / `gtrk audio lay` — 音频驱动工程零件(配音先行)
559
+ ### `gtrk project init` / `gtrk audio lay` / `gtrk audio tighten` — 音频驱动工程零件(配音先行)
543
560
 
544
- 不从口播毛片、而从**一条配音**起盘的工程入口:先有配音(TTS 合成或自己录的),`project init` 建好 `.gtrk` 工程,之后 `gtrk split --project` 投影拆分照常接成片流水线;`audio lay` 则给任意工程补音频轨(BGM/配乐)。
561
+ 不从口播毛片、而从**一条配音**起盘的工程入口:先有配音(TTS 合成或自己录的),`project init` 建好 `.gtrk` 工程,之后 `gtrk split --project` 投影拆分照常接成片流水线;`audio lay` 则给任意工程补音频轨(BGM/配乐);`audio tighten` 收紧配音的句间停顿。
545
562
 
546
563
  | 命令 | 作用 |
547
564
  |---|---|
548
565
  | `gtrk project init --tts-task <task_id>` | **主路**:引用一个已完成的 `audio_tts_clone` 配音任务——服务端直取产物音频与句级时码(零 ASR、零额外计费),音频下载落工程 `audio/` |
549
566
  | `gtrk project init --audio <配音> --transcript <transcript.json>` | **兜底路**:自备配音音频 + 句级时码稿成对给(时码稿由 `gtrk transcript <配音音频> --json` 产出;TTS 合成的配音请走主路,别重跑 ASR) |
550
- | `gtrk audio lay --project <目录> --file <bgm.mp3>` | 往工程追加一条音频轨;**同源幂等替换**(同一来源重跑替换不堆轨、零引用保护剥旧);`--volume <0..1>`(默认 0.3 垫底音量)、`--offset <ms>` 定入点 |
567
+ | `gtrk audio lay --project <目录> --file <bgm.mp3>` | 往工程追加一条音频轨;**同源幂等替换**(同一来源重跑替换不堆轨、零引用保护剥旧);`--volume <0..1>`(默认 0.1 垫底音量——契约 volume 只写线性增益、不写 dB;客户端音量面板显示 -20.0,两侧同一标尺)、`--offset <ms>` 定入点 |
551
568
  | `gtrk audio lay … --beat-align` | 云端节拍分析(`audio_music_analyze`,计费一次)把入点吸附最近 downbeat;无 Key / 分析失败 / 出界一律自动降级为不对齐,命令不失败 |
569
+ | `gtrk audio tighten --project <目录>` | 收紧配音轨的**句间**停顿(**纯本地、零计费**):只压跨句界的静音,**句内换气与原声引用段不动**,出参如实报「跳过句内换气 N 处」。`--keep <秒>` 收紧后保留的静音、`--min-silence <秒>` 短于此不动、`--boundary-tol <秒>` 判「贴着句界」的容差、`--dry-run` 只报会压几处共几秒、不写盘。三个缺省值见 `gtrk audio tighten --help`(实测认可值,换题材/音色可调) |
552
570
 
553
571
  `project init` 另有 `--canvas <WxH>`(默认 1080x1920)、`-o/--out`、`--reupload`、`--no-open`、`--json`,语义与 `oralcut` 一致;两命令 `--json` 恒出单行结果 JSON(人读日志走 stderr)。
554
572
 
573
+ > **`tighten` 该在铺轨之前跑**:它会改配音轨时长,`gtrk split` / `gtrk matrix` 的 beat 时码按当刻工程重投影——先收紧再铺轨,省一次返工。想要合成时就对,自训音色可在 TTS 阶段直接传 `--fragment-interval`(见下节 `audio_tts_clone`);云引擎音色不支持该参数,才用本命令在合成之后收。
574
+
555
575
  ### `gtrk tool <name> [输入...]` — 单点工具族
556
576
 
557
577
  单发单收的独立能力,与成片管线的车道命令(`oralcut`/`split`/`matrix`/`mg`)分家。**顶层命令 + 首个 positional 词分派**(不用父子命令):`gtrk tool <name> [输入...]` 跑工具(多文件图片工具可传多个路径,顺序即拼装顺序),`gtrk tool list` 查全部。一个工具 = 一个薄 descriptor(输入类别 / payload 拼装 / 产物映射 / 计费 / 可用门),共享 runner 跑「校验 → 上传(指纹缓存、≥256MiB 自动分片)→ 提交 → 轮询 → 流式下载落地 → `task.json`/`result.json` 面包屑」——接新工具只加一个 descriptor、不写编排。
558
578
 
579
+ **产物目录口径**:有输入文件的工具缺省落**输入同目录**下 `<输入名>-<工具名>/`;`input=none` 的工具(如 `audio_tts_clone`)缺省落**当前目录**下 `<工具名>-<时间戳>/`。两者都可用 `--out <dir>` 覆盖。缺省名撞上已有目录时自动带 `-2`/`-3` 序号后缀,同一目录内产物文件撞名时带 taskId 后 6 位后缀——**一律以回执的 `outDir` / `files` 为准,别按名字硬拼**(`--out` 显式落点不派生序号,重跑同一输入是幂等覆盖)。
580
+
559
581
  | 工具 | 输入 | 产物 | 计费 | 状态 |
560
582
  |---|---|---|---|---|
561
583
  | `image_move` | 单张图片;可选 `--motion` 指定 26 种运镜之一 | 运镜视频(几何按原图朝向推导:横 1920×1080 / 竖 1080×1920) | 运行前实时查询 | 已上线 |
@@ -576,7 +598,7 @@ gtrk matrix lay --project <目录> [--plan <path>] # ③ 消费(
576
598
  | `video_motion_cut` | 单条本地视频 | 运镜/高光片段结构 `result-output.json`(结构化数据,非下载文件) | 运行前实时查询 | 已上线 |
577
599
  | `video_speaker_detect` | 单条本地视频;可选 `--language`/`--max-faces-per-frame`/`--detect-body`/`--track-sample-fps`(重 GPU) | 可见说话人结构 `result-output.json`(时基以服务端输出为准) | 运行前实时查询 | 已上线 |
578
600
  | `video_face_track` | 单条本地视频;可选 `--sample-fps`/`--max-faces`/`--min-face-ratio`/`--enable-body-match`/`--similarity-threshold`;`time_ranges` 走 `--params-json`(重 GPU) | 人物 ID/时间段/轨迹结构 `result-output.json`(时基以服务端输出为准) | 运行前实时查询 | 已上线 |
579
- | `audio_tts_clone` | **无文件**:`--text`/`--text-file` 二选一(≤5000 字)+ `--speaker` 必填;可选语言/格式/语速/切分法/字幕 | 配音音频 wav/mp3(+ 可选字幕);按文本字符数计费,计量单位与单价以 `gtrk tool list` 实时显示为准 | 运行前实时查询 | 已上线 |
601
+ | `audio_tts_clone` | **无文件**:`--text`/`--text-file` 二选一(≤5000 字)+ `--speaker` 必填;可选语言/格式/语速/切分法/字幕/**句间停顿**(`--fragment-interval <秒>`,**仅自训音色**;云引擎音色传了会**报错**而非静默忽略,合法区间由服务端校验并在报错里给出) | 配音音频 wav/mp3(+ 可选字幕);按文本字符数计费,计量单位与单价以 `gtrk tool list` 实时显示为准 | 运行前实时查询 | 已上线 |
580
602
  | `video_ai_subtitle` | 单条视频或音频;`--language <码>` 必填;可选 `--translate-language`、`--need-render`、`--need-pure`、`--subtitle-type`、`--subtitle-color`。默认只传本地抽出的音频(毛片不上传) | `.ass` 字幕 + 可选烧录/去字幕 `.mp4` + `result-output.json`(摘要 + 字级时间轴) | 运行前实时查询 | 已上线 |
581
603
  | `subtitle_translate` | 单个**字幕文件** `.ass` / `.srt`;`--language <码>` 与 `--translate-language <码>` **双必填**;可选 `--output-format`、`--line-mode`、`--bilingual`、`--subtitle-type`、`--subtitle-color`、`--canvas <WxH>`。不含语音识别 | 译文字幕 `.ass` 或 `.srt` + `result-output.json`(条数统计 + 降级标记) | 运行前实时查询 | 已上线 |
582
604
  | `video_long2short_pro` | 单条长视频(整片上传);`--language <码>` 必填;可选 `--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` | 逐条成片 `clip{i}.mp4` + 人读报告 `clips.md`(含润色降级明细) + `result-output.json` | 运行前实时查询 | 已上线 |