@gitruck/cli 1.3.3 → 1.3.4

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.
@@ -187,7 +187,7 @@ Common entry points: `gtrk oralcut` edits talking heads, `gtrk long2short` selec
187
187
 
188
188
  ### `gtrk long2short` / `gtrk pip` / `gtrk qc` — Additional commands
189
189
 
190
- - `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. Run landscape and portrait separately; content determines the number of clips. See `gtrk long2short --help` for all options.
190
+ - `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. See `gtrk long2short --help` for all options.
191
191
  - `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.
192
192
  - `gtrk qc <video>`: inspect flash frames, black/frozen frames, volume and synchronization. Add `--gtrk` for project context and `--fail-on` for pipeline gating. Findings locate issues; they do not automatically repair the video.
193
193
 
@@ -475,6 +475,28 @@ There are two billing surfaces: structural project export is billed per task, wh
475
475
 
476
476
  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.
477
477
 
478
+ ### `gtrk project background` — client canvas background (blur / solid color)
479
+
480
+ Changes only `struct_meta.client_background` in the `.gtrk`; the client renders the canvas background from it when the project opens, and the user can change it back in the client settings. The typical use is a blurred fill instead of black bars when a landscape source sits on a portrait canvas. Zero credits, no cloud access; Jianying / Premiere projects and local `gtrk render` do not carry this setting.
481
+
482
+ ```bash
483
+ gtrk project background --gtrk <project-file> --blur
484
+ gtrk project background --project <project-dir> --blur --intensity 300
485
+ gtrk project background --gtrk <project-file> --color "#1A1A1A"
486
+ gtrk project background --gtrk <project-file> --clear
487
+ ```
488
+
489
+ | Option | Purpose |
490
+ |---|---|
491
+ | `--project <dir>` / `--gtrk <path>` | Locate the project, same rules as `project export` |
492
+ | `--blur` | Blurred fill: a blurred copy of the visible main-track picture underneath |
493
+ | `--intensity <n>` | With `--blur`, 0–1000, default 200 |
494
+ | `--color <#RRGGBB>` | Solid color (six-digit hex) |
495
+ | `--clear` | Remove the setting and return to the client's default black |
496
+ | `--dry-run` | Validate and report the value that would be written, without writing |
497
+
498
+ 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.
499
+
478
500
  > **`--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.
479
501
 
480
502
 
package/docs/reference.md CHANGED
@@ -1,12 +1,12 @@
1
- # Agent、配置与命令参考
2
-
3
- `project compose --list <分段清单.json> --out <新工程目录> --canvas 1920x1080` 在本地组装分段工程,不上传原片、不自动合成声音。清单示例:
4
-
5
- ```json
6
- {"version":1,"segments":[{"kind":"live","source":"原片.mp4","in":3,"out":11},{"kind":"narration","source":"旁白.wav","transcript":"旁白.json"},{"kind":"image","source":"照片.jpg","duration":4}]}
7
- ```
8
-
9
- 路径相对清单;视频默认保留独立同期声,`keep_audio:false` 关闭;旁白段留同长画面空档。图片段为静帧,运镜先经 `tool image_move` 产视频。文稿用源时基 `utterances:[{st,ed,text}]`;合并文稿逐句绑定素材,供 `split`、`subtitle lay` 随剪辑重投影,切点截断的整句会省略并报告。输出目录必须不存在,已有工程精修走 `patch`,避免覆盖。
1
+ # Agent、配置与命令参考
2
+
3
+ `project compose --list <分段清单.json> --out <新工程目录> --canvas 1920x1080` 在本地组装分段工程,不上传原片、不自动合成声音。清单示例:
4
+
5
+ ```json
6
+ {"version":1,"segments":[{"kind":"live","source":"原片.mp4","in":3,"out":11},{"kind":"narration","source":"旁白.wav","transcript":"旁白.json"},{"kind":"image","source":"照片.jpg","duration":4}]}
7
+ ```
8
+
9
+ 路径相对清单;视频默认保留独立同期声,`keep_audio:false` 关闭;旁白段留同长画面空档。图片段为静帧,运镜先经 `tool image_move` 产视频。文稿用源时基 `utterances:[{st,ed,text}]`;合并文稿逐句绑定素材,供 `split`、`subtitle lay` 随剪辑重投影,切点截断的整句会省略并报告。输出目录必须不存在,已有工程精修走 `patch`,避免覆盖。
10
10
 
11
11
  `matrix describe` 的本地视觉交接:`--prepare <工程内目录>` 生成带时码、源指纹与图片哈希的审阅任务,零豆包调用;当前 Agent 看图填写回执后,以相同 `--materials` 或 `--plan` 参数加 `--review <visual-review.json>` 导入。仅明确标记无法完成并给出原因的条目回退豆包;缺答、素材变化或准则不一致会报错,不自动上云。这个接力由 Agent 完成,不要求用户填表。纯本地完成时无需 API Key,回退豆包时需要云端配置。
12
12
 
@@ -190,7 +190,7 @@ GITRUCK_CRASH_REPORT=0 gtrk oralcut a.mp4 # 环境变量,临时关一次(
190
190
 
191
191
  ### `gtrk long2short` / `gtrk pip` / `gtrk qc` — 常用补充
192
192
 
193
- - `gtrk long2short <input>`:按话题选段并跳剪,逐 clip 输出 gtrk / 剪映 / XML 工程;`--split-screen` 使用 720p 代理做智能分屏;`--output-size` 选择画幅;`--subtitle-out` 另产逐 clip 字幕。每次只选一种画幅,横竖屏分别运行;成片条数由内容决定。完整参数见 `gtrk long2short --help`。
193
+ - `gtrk long2short <input>`:按话题选段并跳剪,逐 clip 输出 gtrk / 剪映 / XML 工程;`--split-screen` 使用 720p 代理做智能分屏;`--output-size` 选择画幅;`--subtitle-out` 另产逐 clip 字幕;`--speed-factor 0.5–2.0` 把整体调速(保音高)写进逐 clip 工程(云端不渲染、不加价);`--camera-move` 让云端把推 / 拉镜头写成主轨片段的缩放关键帧(客户端与剪映可见可改,本地 `gtrk render` 与 PR 工程不呈现;`clips.md` 标「运镜 N 处」),之后 `gtrk patch` 裁剪 / 切分会同步维护关键帧。产物根另落整片转写 `json/transcript.json`,可对任一 clip 上客户端字幕轨:`gtrk subtitle lay --gtrk <clip 目录>/gtrk/<工程>.gtrk --transcript <产物根>/json/transcript.json --language <源语种>`(`--language` 为云端拆行语种,缺省 zh-CN)。每次只选一种画幅,横竖屏分别运行;成片条数由内容决定。完整参数见 `gtrk long2short --help`。
194
194
  - `gtrk pip lay`:把同步录制的屏录或第二机位按口播剪点铺成画中画。两源需有可对齐的公共声音;低置信时先在客户端校准,再按提示恢复。运行 `gtrk pip lay --help` 查看输入、形状、位置和偏移参数。
195
195
  - `gtrk qc <成片>`:检查闪帧、黑帧、冻结、音量和同步问题;用 `--gtrk` 提供工程上下文,`--fail-on` 控制管线门槛。检查结论供定位问题,不自动替你修片。
196
196
 
@@ -291,8 +291,8 @@ gtrk patch set --project <dir> --track audio:1 --at 3.0 --volume 0.5
291
291
  | `--to <sec\|Nf>` | `move` 的落点 | — |
292
292
  | `--in` / `--out` / `--set-in` / `--set-out` / `--slip` | `trim` 的五种语义(前两个相对、中两个绝对、`--slip` 只换源窗) | — |
293
293
  | `--cut <sec\|Nf>` | `split` 的切点。⚠️ 与寻址用的 `--at` 是两个参数 | — |
294
- | `--muted` / `--volume <gain>` / `--opaque` | `set` 的元素级参数(`--volume` 是线性增益不是 dB) | — |
295
- | `--audio-track <index>` | `set`:将音频片段转入已有音轨;时码、素材和有效音量/静音不变,拒绝重叠或无法保真的轨级设置,移除变空的原轨 | — |
294
+ | `--muted` / `--volume <gain>` / `--opaque` | `set` 的元素级参数(`--volume` 是线性增益不是 dB) | — |
295
+ | `--audio-track <index>` | `set`:将音频片段转入已有音轨;时码、素材和有效音量/静音不变,拒绝重叠或无法保真的轨级设置,移除变空的原轨 | — |
296
296
  | `--total <sec\|Nf\|max>` | `set` 的顶层总长(工程级 op,与元素寻址互斥) | — |
297
297
  | `--ops <file\|->` | 批量事务:一次读、全算、全校验、一次写;任一条失败**零写** | 关 |
298
298
  | `--dry-run` | 只算与校验、不写文件 | 关 |
@@ -507,6 +507,28 @@ gtrk project export --gtrk <工程文件> --formats jianying,xml --out <产物
507
507
 
508
508
  颗粒预渲前会先完成 HTML、路径和缓存预检;预检失败不会提交任何云任务。单颗粒渲染或下载失败会记录在 `result.json`,其余格式继续导出。`--json` 输出单行结果 JSON,人读日志走 stderr。
509
509
 
510
+ ### `gtrk project background` — 客户端画布背景(模糊底 / 纯色)
511
+
512
+ 只改 `.gtrk` 的 `struct_meta.client_background` 一个键:客户端打开工程即按它呈现画布背景,可在客户端设置里改回。典型用途是横屏源进竖屏画布时用模糊底替代黑边。零计费、不访问云端;剪映 / PR 工程与本地 `gtrk render` 不承接该设置。
513
+
514
+ ```bash
515
+ gtrk project background --gtrk <工程文件> --blur
516
+ gtrk project background --project <工程目录> --blur --intensity 300
517
+ gtrk project background --gtrk <工程文件> --color "#1A1A1A"
518
+ gtrk project background --gtrk <工程文件> --clear
519
+ ```
520
+
521
+ | 参数 | 作用 |
522
+ |---|---|
523
+ | `--project <dir>` / `--gtrk <path>` | 定位工程,规则同 `project export` |
524
+ | `--blur` | 模糊底:主轨可见画面的模糊副本垫底 |
525
+ | `--intensity <n>` | 配合 `--blur`,0–1000,缺省 200 |
526
+ | `--color <#RRGGBB>` | 纯色底(六位十六进制) |
527
+ | `--clear` | 删除该设置,回到客户端缺省黑底 |
528
+ | `--dry-run` | 只校验并回执将写入的值,不写文件 |
529
+
530
+ 三种模式恰好选一个。写回走原子替换与内容 revision 守卫,其余内容原样保留;值未变时不写盘。`--json` 回执含写前写后 revision。
531
+
510
532
  > **`--beat-align`**:按表格中的高潮点锚定规则工作;显式 `--climax` 会覆盖自动判据。该模式会调用 `audio_music_analyze` 并产生相应计费。
511
533
 
512
534
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitruck/cli",
3
- "version": "1.3.3",
3
+ "version": "1.3.4",
4
4
  "description": "同合云成片流水线 CLI —— agent 驱动云端任务、产物拉回本地、三方工程文件(客户端/剪映/PR)互通。",
5
5
  "license": "MIT",
6
6
  "author": "Gitruck (同合云)",
@@ -57,7 +57,7 @@
57
57
  "build": "bun build ./src/index.ts --target=node --minify --outfile dist/index.js",
58
58
  "typecheck": "tsc --noEmit",
59
59
  "prepublishOnly": "npm run typecheck && npm test && bun run build",
60
- "test": "node scripts/workspace-pollution-gate.mjs --snapshot && esbuild src/lib/compliance-notice.ts src/lib/config.ts src/lib/crash-report.ts src/lib/log.ts src/lib/read-json.ts src/lib/sidecar-write.ts src/lib/user-config.ts src/lib/enum-catalog.ts src/lib/first-run-tutorial.ts src/lib/desktop-client-hint.ts src/lib/command-path.ts src/lib/user-path.ts src/lib/runtime-channel.ts src/lib/self-install.ts src/lib/chunk-upload.ts src/lib/upload-cache.ts src/lib/upload-submit.ts src/lib/render.ts src/lib/cloud.ts src/lib/materialize.ts src/lib/jianying.ts src/lib/clip-brief.ts src/lib/media.ts src/lib/projection.ts src/lib/reproject.ts src/lib/splitdoc.ts src/lib/gtrk-writeback.ts src/lib/gtrk-patch.ts src/lib/frame-domain.ts src/lib/clock-adapter.ts src/lib/gtrk-invariants.ts src/lib/column-config.ts src/lib/third-party-catalog.ts src/lib/mg-adopt.ts src/lib/mg-registry.ts src/lib/matrix.ts src/lib/online-broll-client.ts src/lib/online-search-journal.ts src/lib/matrix-material.ts src/lib/matrix-fetch.ts src/lib/matrix-lay.ts src/lib/arrange-metering.ts src/lib/arrange-wire.ts src/lib/arrange-apply.ts src/lib/arrange-client.ts src/lib/arrange-gate.ts src/lib/arrange-decision-pin.ts src/lib/arrange-qc.ts src/lib/arrange-qc-bind.ts src/lib/rate-limit-wait.ts src/lib/embed-client.ts src/lib/describe.ts src/lib/highlight-rubric.ts src/lib/local-index.ts src/lib/character-input.ts src/lib/index-decode.ts src/lib/local-search.ts src/lib/qc.ts src/lib/alignment-qc.ts src/lib/bgm-history.ts src/lib/image-move.ts src/lib/cloud-render-guard.ts src/lib/outdir-guard.ts src/lib/landing-wait.ts src/lib/material-integrity.ts src/lib/project-health.ts src/lib/contact-sheet.ts src/lib/solid-png.ts src/lib/mask-raster.ts src/lib/mg-lint.ts src/lib/mg-visual-job.ts src/lib/mg-track-identity.ts src/lib/particle-identity.ts src/lib/text-ir/compile.ts src/lib/text-ir/validate.ts src/lib/text-ir/compile-local.ts src/lib/text-templates.ts src/lib/text-ir-client.ts src/lib/mg-lay.ts src/lib/mg-render.ts src/lib/particle-qtrle.ts src/lib/tool-descriptors.ts src/lib/tool-runner.ts src/lib/tool-batch.ts src/lib/tool-pricing.ts src/lib/transcript.ts src/lib/runtime-assets.ts src/lib/subtitle-lay.ts src/lib/caption-align.ts src/lib/subtitle-line-split-client.ts src/lib/audio-align.ts src/lib/audio-tighten.ts src/lib/cut-snap.ts src/lib/mg-coverage.ts src/lib/ai-drama-lay.ts src/lib/ai-drama-pack.ts src/lib/desk-locate.ts src/lib/pip-lay.ts --bundle --platform=node --format=esm --external:bun:sqlite --outdir=.test-build --out-extension:.js=.mjs && esbuild src/lib/text-ir/compile.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/text-ir-compile.mjs && esbuild src/commands/split.ts --bundle --platform=node --external:bun:sqlite --format=esm --outdir=.test-build --out-extension:.js=.mjs && esbuild src/commands/patch.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/patch-cmd.mjs && esbuild src/commands/matrix.ts --bundle --platform=node --format=esm --external:bun:sqlite --outfile=.test-build/matrix-cmd.mjs && esbuild src/commands/mg.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/mg-cmd.mjs && esbuild src/commands/mg-text.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/mg-text-cmd.mjs && esbuild src/commands/tool.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/tool-cmd.mjs && esbuild src/commands/transcript.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/transcript-cmd.mjs && esbuild src/commands/project.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/project-cmd.mjs && esbuild src/commands/audio.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/audio-cmd.mjs && esbuild src/commands/subtitle.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/subtitle-cmd.mjs && esbuild src/commands/ai-drama.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/ai-drama-cmd.mjs && esbuild src/commands/feedback.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/feedback-cmd.mjs && esbuild src/commands/music-visualizer.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/music-visualizer-cmd.mjs && esbuild src/commands/long2short.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/long2short-cmd.mjs && esbuild src/commands/oralcut.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/oralcut-cmd.mjs && esbuild src/commands/oralcut-result.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/oralcut-result-cmd.mjs && esbuild src/commands/skills.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/skills-cmd.mjs && esbuild src/commands/qc.ts --bundle --platform=node --format=esm --external:commander --external:bun:sqlite --outfile=.test-build/qc-cmd.mjs && esbuild src/commands/doctor.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/doctor-cmd.mjs && esbuild src/lib/convert/ir_to_jsx.ts src/lib/convert/ir_to_am.ts src/lib/convert/ir_to_nv.ts src/lib/convert/am_parse.ts src/lib/convert/nv_parse.ts src/lib/convert/parse.ts src/lib/convert/download.ts src/lib/convert/bake_ops.ts --bundle --platform=node --external:bun:sqlite --format=esm --outdir=.test-build/convert --out-extension:.js=.mjs && esbuild src/lib/mad/selector.ts src/lib/mad/techniques.ts src/lib/mad/beat.ts src/lib/mad/scan.ts src/lib/mad/data.ts src/lib/mad/pool.ts src/lib/mad/cloud-beat.ts src/lib/mad/mad.ts --bundle --platform=node --external:bun:sqlite --format=esm --outdir=.test-build/mad --out-extension:.js=.mjs && esbuild src/commands/purify.ts --bundle --platform=node --format=esm --external:bun:sqlite --outfile=.test-build/purify-cmd.mjs && node --import ./test/helpers/test-home.mjs --test \"test/*.test.mjs\" && node scripts/workspace-pollution-gate.mjs --verify",
60
+ "test": "node scripts/workspace-pollution-gate.mjs --snapshot && esbuild src/lib/compliance-notice.ts src/lib/config.ts src/lib/crash-report.ts src/lib/log.ts src/lib/read-json.ts src/lib/sidecar-write.ts src/lib/user-config.ts src/lib/enum-catalog.ts src/lib/first-run-tutorial.ts src/lib/desktop-client-hint.ts src/lib/command-path.ts src/lib/user-path.ts src/lib/runtime-channel.ts src/lib/self-install.ts src/lib/chunk-upload.ts src/lib/upload-cache.ts src/lib/upload-submit.ts src/lib/render.ts src/lib/cloud.ts src/lib/materialize.ts src/lib/jianying.ts src/lib/clip-brief.ts src/lib/media.ts src/lib/projection.ts src/lib/reproject.ts src/lib/splitdoc.ts src/lib/gtrk-writeback.ts src/lib/project-background.ts src/lib/gtrk-patch.ts src/lib/frame-domain.ts src/lib/clock-adapter.ts src/lib/gtrk-invariants.ts src/lib/clip-speed.ts src/lib/clip-keyframes.ts src/lib/column-config.ts src/lib/third-party-catalog.ts src/lib/mg-adopt.ts src/lib/mg-registry.ts src/lib/matrix.ts src/lib/online-broll-client.ts src/lib/online-search-journal.ts src/lib/matrix-material.ts src/lib/matrix-fetch.ts src/lib/matrix-lay.ts src/lib/arrange-metering.ts src/lib/arrange-wire.ts src/lib/arrange-apply.ts src/lib/arrange-client.ts src/lib/arrange-gate.ts src/lib/arrange-decision-pin.ts src/lib/arrange-qc.ts src/lib/arrange-qc-bind.ts src/lib/rate-limit-wait.ts src/lib/embed-client.ts src/lib/describe.ts src/lib/highlight-rubric.ts src/lib/local-index.ts src/lib/character-input.ts src/lib/index-decode.ts src/lib/local-search.ts src/lib/qc.ts src/lib/alignment-qc.ts src/lib/bgm-history.ts src/lib/image-move.ts src/lib/cloud-render-guard.ts src/lib/outdir-guard.ts src/lib/landing-wait.ts src/lib/material-integrity.ts src/lib/project-health.ts src/lib/contact-sheet.ts src/lib/solid-png.ts src/lib/mask-raster.ts src/lib/mg-lint.ts src/lib/mg-visual-job.ts src/lib/mg-track-identity.ts src/lib/particle-identity.ts src/lib/text-ir/compile.ts src/lib/text-ir/validate.ts src/lib/text-ir/compile-local.ts src/lib/text-templates.ts src/lib/text-ir-client.ts src/lib/mg-lay.ts src/lib/mg-render.ts src/lib/particle-qtrle.ts src/lib/composite-particle.ts src/lib/tool-descriptors.ts src/lib/tool-runner.ts src/lib/tool-batch.ts src/lib/tool-pricing.ts src/lib/transcript.ts src/lib/runtime-assets.ts src/lib/subtitle-lay.ts src/lib/caption-align.ts src/lib/subtitle-line-split-client.ts src/lib/audio-align.ts src/lib/audio-tighten.ts src/lib/cut-snap.ts src/lib/mg-coverage.ts src/lib/ai-drama-lay.ts src/lib/ai-drama-pack.ts src/lib/desk-locate.ts src/lib/pip-lay.ts --bundle --platform=node --format=esm --external:bun:sqlite --outdir=.test-build --out-extension:.js=.mjs && esbuild src/lib/text-ir/compile.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/text-ir-compile.mjs && esbuild src/commands/split.ts --bundle --platform=node --external:bun:sqlite --format=esm --outdir=.test-build --out-extension:.js=.mjs && esbuild src/commands/patch.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/patch-cmd.mjs && esbuild src/commands/matrix.ts --bundle --platform=node --format=esm --external:bun:sqlite --outfile=.test-build/matrix-cmd.mjs && esbuild src/commands/mg.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/mg-cmd.mjs && esbuild src/commands/mg-text.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/mg-text-cmd.mjs && esbuild src/commands/tool.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/tool-cmd.mjs && esbuild src/commands/transcript.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/transcript-cmd.mjs && esbuild src/commands/project.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/project-cmd.mjs && esbuild src/commands/audio.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/audio-cmd.mjs && esbuild src/commands/subtitle.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/subtitle-cmd.mjs && esbuild src/commands/ai-drama.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/ai-drama-cmd.mjs && esbuild src/commands/feedback.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/feedback-cmd.mjs && esbuild src/commands/music-visualizer.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/music-visualizer-cmd.mjs && esbuild src/commands/long2short.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/long2short-cmd.mjs && esbuild src/commands/oralcut.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/oralcut-cmd.mjs && esbuild src/commands/oralcut-result.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/oralcut-result-cmd.mjs && esbuild src/commands/skills.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/skills-cmd.mjs && esbuild src/commands/qc.ts --bundle --platform=node --format=esm --external:commander --external:bun:sqlite --outfile=.test-build/qc-cmd.mjs && esbuild src/commands/doctor.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/doctor-cmd.mjs && esbuild src/lib/convert/ir_to_jsx.ts src/lib/convert/ir_to_am.ts src/lib/convert/ir_to_nv.ts src/lib/convert/am_parse.ts src/lib/convert/nv_parse.ts src/lib/convert/parse.ts src/lib/convert/download.ts src/lib/convert/bake_ops.ts --bundle --platform=node --external:bun:sqlite --format=esm --outdir=.test-build/convert --out-extension:.js=.mjs && esbuild src/lib/mad/selector.ts src/lib/mad/techniques.ts src/lib/mad/beat.ts src/lib/mad/scan.ts src/lib/mad/data.ts src/lib/mad/pool.ts src/lib/mad/cloud-beat.ts src/lib/mad/mad.ts --bundle --platform=node --external:bun:sqlite --format=esm --outdir=.test-build/mad --out-extension:.js=.mjs && esbuild src/commands/purify.ts --bundle --platform=node --format=esm --external:bun:sqlite --outfile=.test-build/purify-cmd.mjs && node --import ./test/helpers/test-home.mjs --test \"test/*.test.mjs\" && node scripts/workspace-pollution-gate.mjs --verify",
61
61
  "test:linux": "node scripts/test-linux.mjs",
62
62
  "openspec:gate": "node openspec/gate.mjs",
63
63
  "mg-registry:snapshot": "node scripts/mg-registry-snapshot.mjs",
@@ -5,7 +5,7 @@ description: 直播切片图纸——把一场数小时的直播回放,拆成
5
5
 
6
6
  # gtrk-live-slicing(直播切片 · 组合成片图纸)
7
7
 
8
- 把**一场直播回放**(1–4 小时)变成**一批可编辑的逐 clip 粗剪工程**:四问定策略 → 分段 → 逐段选段 → **选题清单必停** → 出工程。
8
+ 把**一场直播回放**(1–4 小时)变成**一批可编辑的逐 clip 粗剪工程**:五问定策略 → 分段 → 逐段选段 → **选题清单必停** → 出工程。
9
9
 
10
10
  > **定位**:第三张 **structure 级组合图纸**(前两张=`gtrk-travel-recap` 旅拍解说、`gtrk-vlog-docu` Vlog 纪实)。不新增任何命令,只编排既有零件。参数细节以 `gtrk-long2short` 与 `--help` 为准,**本图纸引用不复制**;**编排次序、分段规约、检查点**以本图纸为准。**CLI 是手,你是脑。**
11
11
 
@@ -17,17 +17,18 @@ description: 直播切片图纸——把一场数小时的直播回放,拆成
17
17
 
18
18
  - ❌ 不去水印、❌ 不去烧录贴片、❌ 不做画面清理美化、❌ 不调色不裁切
19
19
  - 源片长什么样,切片就长什么样。要不要动那些元素,是**用户在客户端二次编辑时的决定**,不是你的。
20
- - 分段所需的时间轴裁切**必须用 `ffmpeg -c copy` 流拷贝**(不重编码)。
20
+ - 分段所需的时间轴裁切**必须用 `ffmpeg -c copy` 流拷贝**(不重编码)。
21
+ - **工程层设置不算像素改动**:变速倍率(`--speed-factor`)、运镜关键帧(`--camera-move`)、客户端字幕轨(`gtrk subtitle lay`)、画布模糊底(`gtrk project background`)都写在工程里、可在客户端撤销,源片本身一个像素不动——与本条不冲突。
21
22
 
22
23
  > **用户只要能直接发的成片、不打算再剪?** 那不是本图纸的活,转 `gtrk tool video_long2short_pro`(精剪,整片上传、云端渲染、计费约两倍)。判断句同 `gtrk-long2short`:**「剪完还要不要再动?」要动 → 留这儿;不动 → 转精剪。**
23
24
 
24
- ## 一、输入契约与开工四问
25
+ ## 一、输入契约与开工五问
25
26
 
26
27
  **输入**:一条直播回放的**本地文件**(`.ts` / `.mp4` 等均可)。
27
28
 
28
29
  **MUST NOT 执行录制或下载**——平台动作与版权责任归用户。用户给什么文件就用什么。
29
30
 
30
- 开工前先答四问,答案决定后面全部策略:
31
+ 开工前先答五问,答案决定后面全部策略:
31
32
 
32
33
  | # | 问 | 怎么取证 | 决定什么 |
33
34
  |---|---|---|---|
@@ -35,28 +36,30 @@ description: 直播切片图纸——把一场数小时的直播回放,拆成
35
36
  | ② | 画面形态是否单一 | **问用户**——全程主播口播位?还是含实景走播/换机位? | **哪些段开分屏**(§四) |
36
37
  | ③ | 有无烧录贴片 | 抽 2–3 帧看(开头/中段/尾段各一) | **交付时要如实告知什么**(§五) |
37
38
  | ④ | 入选切片要不要叠 MG 动画 | **问用户**——缺省不叠(粗剪定位) | **选题清单敲定后是否走 MG 车道**(§七) |
39
+ | ⑤ | 入选切片要不要加运镜(推拉镜头) | **问用户**——缺省不加 | **逐段提交是否带 `--camera-move`**(§七「运镜」) |
38
40
 
39
- > **②④ MUST 问用户、MUST NOT 代猜。** ②猜错的代价是白跑一轮分屏(几十分钟 + 积分);
40
- > ④缺省是**不叠**——用户没要就零 MG 动作,MUST NOT 硬塞。
41
+ > **②④⑤ MUST 问用户、MUST NOT 代猜。** ②猜错的代价是白跑一轮分屏(几十分钟 + 积分);
42
+ > ④缺省是**不叠**——用户没要就零 MG 动作,MUST NOT 硬塞;⑤缺省是**不加**——用户没要就全程不带 `--camera-move`、不再追问。
43
+ > ⑤ 必须在提交前问:运镜是云端任务参数,交上去之后改不了(没入选的 clip 带了运镜也无害,随 clip 一起丢弃)。
41
44
  > **③ 的取证目的只是「告知」,不是「处置」**——看到贴片不要动手,见定位铁律。
42
45
  > ② 与 `/gtrk-long2short`、`/gtrk-tools` 精剪开工的「多人同框」一问同口径:是就开、不确定按否;
43
46
  > 分屏单段最长 8 秒、每条最多 3 处。
44
47
 
45
- > **推荐面(公约 §三‴)**:问答收口时可问一句「要不要看看第三方 skill?」;题材命中场景触发词才定向推荐,读取 `gtrk skills recommend --scene <id> --json`;用户拒绝后不执行推荐动作。
48
+ > **推荐面(公约 §三‴)**:问答收口时可问一句「要不要看看第三方 skill?」;题材命中场景触发词才定向推荐,读取 `gtrk skills recommend --scene <id> --json`;用户拒绝后不执行推荐动作。
46
49
 
47
50
  ## 二、分段规约(本图纸的骨干)
48
51
 
49
- ### 两道闸
52
+ ### 两道闸
50
53
 
51
54
  | | 闸 | 值 | 命中时的表现 |
52
55
  |---|---|---|---|
53
56
  | **闸一** | 服务端媒体探测层全局业务限制 | **2 小时** | **建单期直接拒**:`6019 媒体时长无效或超过业务限制`。**任务不创建、不计费** |
54
57
  | **闸二** | CLI 轮询墙钟 | **60 分钟** | 轮询超时报错(任务在云端照常跑完,可取回) |
55
58
 
56
- **处理耗时 / 源时长比值按分屏与否分档**:
59
+ **处理耗时 / 源时长比值按分屏与否分档**:
57
60
 
58
- - **不开分屏**:墙钟压力较小;
59
- - **开分屏**:处理耗时明显增加,优先按较短段切分。
61
+ - **不开分屏**:墙钟压力较小;
62
+ - **开分屏**:处理耗时明显增加,优先按较短段切分。
60
63
 
61
64
  ⇒ **单段 MUST ≤ 2h(硬拒线),开分屏时 SHOULD ≤ 48min(墙钟线)。**
62
65
 
@@ -75,7 +78,7 @@ ffmpeg -ss 3600 -t 2400 -i "<直播回放>" -c copy "<工作区>/inputs/<名>_se
75
78
 
76
79
  ### ⚠️ 两条必须在动手前告诉用户
77
80
 
78
- 1. **切段是新文件,工程指向它、不指向原片。** 逐 clip 工程的 `materials[].path` 实指切段;用户删掉切段文件,工程就素材脱机。让他把 `inputs/` 留着。
81
+ 1. **切段是新文件,工程指向它、不指向原片。** 逐 clip 工程的 `materials[].path` 实指切段;用户删掉切段文件,工程就素材脱机。让他把 `inputs/` 留着。
79
82
  2. **超过 2 小时整条提交会被直接拒**,不是慢、是拒。好消息是零计费(不进队列),但会白抽白传一个大文件——所以先分段。
80
83
 
81
84
  ### 超时兜底
@@ -96,7 +99,7 @@ gtrk oralcut-result <task_id> --out <目录> # task_id 在产物根 task.json
96
99
 
97
100
  | 模式 | 停点 |
98
101
  |---|---|
99
- | **快速成片** | 四问 + 分段方案确认 → 逐段跑 → **【必停】选题清单** → 确认后一路出工程 |
102
+ | **快速成片** | 五问 + 分段方案确认 → 逐段跑 → **【必停】选题清单** → 确认后一路出工程 |
100
103
  | **逐步推进模式** | 上述基础上每步都停(分段方案 / 逐段选段结果 / 逐条工程产物) |
101
104
 
102
105
  两模式共用同一套分段规约与参数配方,**差别只在停几次,不在停不停**。
@@ -121,7 +124,7 @@ gtrk oralcut-result <task_id> --out <目录> # task_id 在产物根 task.json
121
124
  > **判断分屏是否真的生效,MUST 看产物证据,MUST NOT 按「没报错」推定。**
122
125
  > 证据 = `report.json` 的 `split_manifest` 条数 + 毛片旁 `split_screen/` 目录里的素材(可抽帧看)。
123
126
 
124
- **分屏在子轨、主轨原片可回退**:分屏素材落在独立子轨上叠放,
127
+ **分屏在子轨、主轨原片可回退**:分屏素材落在独立子轨上叠放,
125
128
  主轨的原片全程完整在场——用户对某段分屏不满意时,在客户端隐藏/删除子轨该段即回退原片,
126
129
  零重跑。交付时把这条回退动线告诉用户。⚠️ 连带边界:本地 `gtrk render` 是快照渲染、
127
130
  **不合成子轨**——渲出来没有分屏画面;要分屏成片走客户端出片(或剪映导出)。
@@ -129,9 +132,11 @@ gtrk oralcut-result <task_id> --out <目录> # task_id 在产物根 task.json
129
132
  其余参数配方:
130
133
 
131
134
  - `--language` **必填**,缺失在上传前就报错(省一次白上传)
132
- - 竖屏直播源通常**无需转比例**,`--output-size` 缺省即可
135
+ - 竖屏直播源通常**无需转比例**,`--output-size` 缺省即可
133
136
  - `--duration-pref` / `--max-clip-sec` 按投放平台口径给档
134
- - `--subtitle-out` 产逐 clip **独立 `.srt`**(不烧进画面——符合粗剪工程定位)
137
+ - `--subtitle-out` 产逐 clip **独立 `.srt`**(不烧进画面)——**可选**,给要拿去 PR 精修的用户;客户端用户走 §七 的字幕上轨
138
+ - `--speed-factor` **只在用户主动要求时加**(见 §七「调速」);开工问询里不问速度
139
+ - `--camera-move` 按开工⑤:用户要运镜才带(见 §七「运镜」),各段一致
135
140
 
136
141
  > 完整参数表在 `gtrk-long2short`,本节只给直播场景的**配方差异**,不搬手册。
137
142
 
@@ -145,7 +150,7 @@ gtrk oralcut-result <task_id> --out <目录> # task_id 在产物根 task.json
145
150
  | **时效信息贴片**(价格 / 截止日期) | 切片再发布时是**过期信息** | 额外点一句,让用户自行判断是否适合再发 |
146
151
  | **无叠加** | — | 不必提 |
147
152
 
148
- > 贴片可能贯穿全场且与切片主题无关,也可能包含会过期的价格或日期;交付时按实际画面如实告知。
153
+ > 贴片可能贯穿全场且与切片主题无关,也可能包含会过期的价格或日期;交付时按实际画面如实告知。
149
154
 
150
155
  **这一节不含任何去除动作。** 用户问「能不能去掉」→ 告诉他这超出本图纸射程,可在客户端二次编辑时自行处理。
151
156
 
@@ -158,9 +163,9 @@ gtrk oralcut-result <task_id> --out <目录> # task_id 在产物根 task.json
158
163
  - **格式**:B站式 `.xml` 是 `<d p="秒数,…">用户:文本</d>`,**`p` 首字段即距开播秒数 = 源片时码**;平台导出 `.txt` 通常是时钟列。归一化成「秒 + 文本 + 用户」三元组即可。
159
164
  - **两个信号**:**复述密度**(同一句话被多个用户在短窗口内重复——观众自发复述的往往就是金句)、**刷屏密度**(互动符号瞬时峰值)。
160
165
 
161
- ### ⚠️ 别高估它:弹幕对「选哪些段」通常只是辅助
166
+ ### ⚠️ 别高估它:弹幕对「选哪些段」通常只是辅助
162
167
 
163
- **结论**:弹幕主要用于验证选段、提取观众原句标题和微调边界,不是必需输入:
168
+ **结论**:弹幕主要用于验证选段、提取观众原句标题和微调边界,不是必需输入:
164
169
 
165
170
  - ❌ **不要**为了「更准地选段」去要用户补弹幕(没有就没有,主干照跑)
166
171
  - ✅ 它真正剩下的价值是 **取候选标题原句**:观众自发复述出来的那句话(如「大脑不接受否定」被 15 人复述),
@@ -180,9 +185,53 @@ gtrk oralcut-result <task_id> --out <目录> # task_id 在产物根 task.json
180
185
  看板点名的三件,都不碰源片:
181
186
 
182
187
  - **标题钩子**:文本建议。有弹幕时优先取观众复述的原句。
183
- - **字幕**:`--subtitle-out` 已产独立 `.srt`,交用户在客户端决定烧不烧。
188
+ - **字幕**:见下「字幕上轨」——选题确认后对入选 clip **缺省做**。
189
+ - **模糊底**:见下「模糊底」——源片与画布横竖不一致时,对入选 clip **缺省做**。
184
190
  - **封面**:走 `/gtrk-cover`(另出图,不改片)。
185
191
 
192
+ ### 字幕上轨(缺省做,只对入选 clip)
193
+
194
+ 选题清单敲定之后,对**每条入选 clip** 跑一次(用户明确说不要字幕才跳过;没入选的不做):
195
+
196
+ ```bash
197
+ gtrk subtitle lay --gtrk "<产物根>/clip{i}/gtrk/<该 clip 的 .gtrk>" --transcript "<产物根>/json/transcript.json" --language <该段提交时的源语种>
198
+ ```
199
+
200
+ - `json/transcript.json` 是该段任务落下的**整片**转写,一份服务该段全部 clip;分了几段就各用各段产物根里的那份。
201
+ - `--language` 跟该段 `gtrk long2short` 的 `--language` 一致(英文直播就 `en-US`),否则云端会按中文断句。
202
+ - 交付时说清三件事:① 字幕在**客户端字幕轨**上,可换样式、可整轨删,不烧进画面;② 云端产出的剪映 / PR 工程是在上字幕**之前**生成的,**不含**这条字幕轨,要带字幕的剪映草稿请从客户端导出;③ 用了 `--subtitle-file` 的段,字幕按行出现、词级时间是近似值(`clips.md` 会提示)。
203
+ - 该段产物根里**没有** `json/transcript.json`(老服务端或下载失败,CLI 日志会说):如实告诉用户这一段没法自动上字幕,其余段照常。**MUST NOT** 拿弹幕或别的文本凑一份当字幕来源(见 §六 红线)。
204
+
205
+ ### 模糊底(横竖互转时缺省做,只对入选 clip)
206
+
207
+ 横屏直播切成竖屏(缺省 9:16)时,粗剪工程上下是黑边。选题清单敲定之后,对每条**入选** clip 判断源片朝向与该段画布朝向:
208
+
209
+ - 源片几何:该段 `gtrk long2short` 日志里的源分辨率,或 `ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0 "<源片>"`;
210
+ - 画布:该段提交时的 `--output-size`(没传就是 9:16 竖屏)。
211
+
212
+ **朝向不一致**(横屏源进竖屏画布,或反之)⇒ 缺省跑(用户说要保持黑边才跳过):
213
+
214
+ ```bash
215
+ gtrk project background --gtrk "<产物根>/clip{i}/gtrk/<该 clip 的 .gtrk>" --blur
216
+ ```
217
+
218
+ **朝向一致**(竖屏直播进竖屏画布)⇒ **不跑**。
219
+
220
+ 交付时说清:模糊底是**客户端画布设置**(主轨画面的模糊副本垫在底下),在客户端设置里可改回黑底;剪映 / PR 工程与本地 `gtrk render` **不带**模糊底。强度缺省 200,用户嫌太虚或不够虚可加 `--intensity <0–1000>` 重跑(幂等覆盖)。零计费、不访问云端。
221
+
222
+ ### 运镜(仅当开工⑤用户要了才做)
223
+
224
+ ⑤答「要」⇒ 逐段提交都带 `--camera-move`(细项如幅度、概率不另开旗标,确有需要走 `--params-json '{"camera_move":{"enable":true,"amplitude":0.1}}'`)。云端按与精剪同一套调度给主轨片段写推 / 拉镜头关键帧,零渲染、不加价。
225
+
226
+ 交付时说清:
227
+ - 运镜写在工程里:**客户端与剪映**打开可见、可在关键帧面板改或删;**本地 `gtrk render` 与 PR 工程看不到运镜**(按静态画面出片),要成片带运镜请从客户端或剪映导出;
228
+ - `clips.md` 每条的「运镜 N 处」是实际写入数,**0 处属正常**(按概率抽取);有「未能加运镜的切片」小节就点名告知;
229
+ - 之后用 `gtrk patch` 裁剪 / 切分带运镜的片段,关键帧会跟着调整,不用手改。
230
+
231
+ ### 调速(只在用户主动要求时)
232
+
233
+ 用户说「切片都加速到 1.2 倍」这类话时,逐段提交带 `--speed-factor 1.2`(范围 `0.5–2.0`,保音高)。倍率写进逐 clip 工程,客户端 / 剪映 / PR 打开都按倍率播放,可在客户端逐条改回;交付时把这句告诉用户,`clips.md` 里若有「未能变速的切片」小节就点名告知。用户没提就**全程不加、不追问**;要超出 `0.5–2.0` 的倍率,告诉他在客户端对具体片段拖边变速。
234
+
186
235
  ### MG 动画(仅当开工④用户要了才做)
187
236
 
188
237
  - **时机**:选题清单敲定**之后**、只对**入选** clip 做——没入选的切片不白做颗粒。
@@ -200,18 +249,18 @@ gtrk oralcut-result <task_id> --out <目录> # task_id 在产物根 task.json
200
249
  ## 八、计费与预算速查(跑前转述给用户)
201
250
 
202
251
  - 计费基 = **上传物音频流时长**(≈源片时长),**2 积分/分钟**。
203
- - **分段不改总量**:切段总时长≈原片,所以分不分段花的钱差不多,分段买的是「能跑通」和「粒度更细的选题清单」。费用以实时价格和音频时长为准。
252
+ - **分段不改总量**:切段总时长≈原片,所以分不分段花的钱差不多,分段买的是「能跑通」和「粒度更细的选题清单」。费用以实时价格和音频时长为准。
204
253
  - **建单期被拒是零计费的**(如超 2h 硬闸)——试探性提交不会烧钱,但会白传一个大文件。
205
- - **任务失败按服务端回执处理**;只有回执明确退款时才向用户说明可重跑。
254
+ - **任务失败按服务端回执处理**;只有回执明确退款时才向用户说明可重跑。
206
255
  - 运行时 CLI 自动查实时价格并打印,**把提示原样转述**;长片先向用户确认再跑。
207
256
 
208
257
  ## 九、排错
209
258
 
210
- - **`超过最大重试次数`** → 这句是**通用兜底文案**;优先检查外部 ASR 查询接口状态。
259
+ - **`超过最大重试次数`** → 这句是**通用兜底文案**;优先检查外部 ASR 查询接口状态。
211
260
  - **判据**:失败很快(1–2 分钟内就报,而正常 40 分钟段要跑 4–20 分钟)⇒ 卡在开头的转写阶段。
212
- - **处置:先原样重跑一次**。若仍失败,说明故障可能不是瞬时的。
261
+ - **处置:先原样重跑一次**。若仍失败,说明故障可能不是瞬时的。
213
262
  - **重试仍失败时,别死磕同一段**:换个切点重切该时段(边界挪几分钟)、或先跑其他段把能出的先出了,
214
- 把这一段单独挂起问客服/换时间再试。**MUST NOT 反复重跑**——每次都会重新等待,是否退款以回执为准。
263
+ 把这一段单独挂起问客服/换时间再试。**MUST NOT 反复重跑**——每次都会重新等待,是否退款以回执为准。
215
264
  - **别改参数、别一味切更短**——那会掩盖问题;先确认是不是 ASR 侧的事。
216
265
  - 分段跑的好处在这里体现:**只需处理失败的那一段**,其余段的成果不受影响。
217
266
  - **`6019 媒体时长无效或超过业务限制`** → 单次提交超服务端 2 小时硬闸。**分段**,别重试。
@@ -22,7 +22,7 @@ description: 长剪短闭环——把一条长视频(课程/直播/播客/访
22
22
  > **⚠️ 开工再问一句:素材是不是多人同框(对谈 / 访谈 / 多人直播)?** 与 `/gtrk-tools` 精剪同一问、同一措辞,
23
23
  > 和上一问**一起问、一次答完**,MUST NOT 代猜。
24
24
  > 答「是」⇒ 带 `--split-screen`,**并在同一句里告知**:本地会改传一份压过的 720p 代理(否则只传抽出的音频、
25
- > 毛片不出本地),处理时间明显变长;分屏素材落毛片旁 `split_screen/`。
25
+ > 毛片不出本地),处理时间明显变长;分屏素材落毛片旁 `split_screen/`。
26
26
  > 答「否 / 不确定」⇒ 不带(「不确定」按「否」)。分屏是点缀:单段最长 8 秒、每条最多 3 处,落在子轨、
27
27
  > 不合心意在客户端隐藏该段即回退原片。
28
28
 
@@ -58,6 +58,8 @@ gtrk long2short "D:/毛片/对谈.mp4" --language zh-CN --split-screen --split-o
58
58
  | `--subtitle-file <path>` | **现成单语字幕**(.srt/.ass)作转写来源,替代云端 ASR(用户手里有片源字幕/人工校对稿时用,省一次识别)。切点精度降为**字幕行边界**;双语/多层 .ass 会被拒;与 stt 类参数互斥 |
59
59
  | `--subtitle-out` | 逐 clip 另产**单语 .srt 字幕**(按目标画布档位智能拆行:横屏约 20 字/行、竖屏约 13 字/行),落 `clip{i}/srt/` |
60
60
  | `--keep-punctuation` | 字幕保留全部标点。缺省按统一口径去标点:逗号句号→空格、`?!` 等保留 |
61
+ | `--speed-factor <n>` | 整体调速 `0.5–2.0`(保音高)。倍率**写进逐 clip 工程**(每个片段带 `speed`),客户端 / 剪映 / PR 都按倍率播放、可在客户端改回;云端不渲染、不加价。**只在用户主动要求时加**;更高倍率请在客户端对具体片段拖边变速 |
62
+ | `--camera-move` | 运镜:云端按与精剪同一套调度给主轨片段写推 / 拉镜头关键帧(概率抽取、推拉交替、幅度克制),零渲染、不加价。客户端与剪映可见可改;本地 `gtrk render` 与 PR 工程不呈现。**缺省不加**,直播切片图纸开工会问;细项走 `--params-json` |
61
63
  | `--output-size <s>` | 画布 `9:16|16:9|1:1` 或 `WxH`(缺省 9:16 竖版) |
62
64
  | `-f, --formats <list>` | 三方格式,缺省 `gtrk,jianying,xml`(云端逐 clip 直产;gtrk 恒有) |
63
65
  | `--jianying-draft-dir <dir>` | 剪映草稿根(或 `auto`);各 clip 草稿落 `<草稿根>/<产物根名>_clip{i}` |
@@ -71,11 +73,17 @@ gtrk long2short "D:/毛片/对谈.mp4" --language zh-CN --split-screen --split-o
71
73
  切段用流拷贝、秒级完成、不重编码:`ffmpeg -ss 0 -t 2400 -i "<源片>" -c copy "<源片名>_seg01.mp4"`。
72
74
  各段产出的 clip 事后汇总成一张选题清单即可。**分段是常态动作,不是降级方案**。
73
75
  - 云端处理时长随片长涨(ASR+选段),CLI 轮询墙钟 60 分钟;超时不丢——产物根 `task.json` 里有 `task_id` 可恢复。
74
- 40 分钟/段是稳妥起步值;若分屏段仍接近墙钟上限,再继续缩短分段。
76
+ 40 分钟/段是稳妥起步值;若分屏段仍接近墙钟上限,再继续缩短分段。
75
77
 
76
78
  ## 产物(跑完把这些讲给用户)
77
79
 
78
80
  - 产物根 `<毛片名>-long2short/`:`report.json`(选段报告)+ `result.json` + 逐 clip 子目录 `clip0/ clip1/ …`(各含 `gtrk/` 客户端工程、`jianying/` 草稿、`xml/` PR 工程;开了 `--subtitle-out` 另有 `srt/clip{i}.srt` 单语字幕)。
81
+ - 产物根 `json/transcript.json`:**整片**源时基转写(一份服务全部 clip)。要给某条 clip 上客户端字幕轨(可换样式、可整轨删、不烧进画面):
82
+ `gtrk subtitle lay --gtrk <产物根>/clip{i}/gtrk/clip{i}_project.gtrk --transcript <产物根>/json/transcript.json --language <源语种>`
83
+ (clip 工程文件名以 `clip{i}/gtrk/` 下实际文件为准)。上完字幕的是**客户端工程**;云端早先产出的剪映 / PR 工程不含这条字幕轨,要带字幕的剪映草稿请从客户端导出。老服务端没有这份文件时,CLI 会提示「无法自动上字幕」。
84
+ - 横屏源进竖屏画布(缺省 9:16)时工程上下是黑边;要模糊底:`gtrk project background --gtrk <产物根>/clip{i}/gtrk/clip{i}_project.gtrk --blur`(客户端画布设置,可在设置里改回黑底;剪映 / PR 与本地渲染不带;零计费)。
85
+ - 用了 `--camera-move` 时:`clips.md` 每条时长后标「运镜 N 处」(0 处属正常);若有 clip 未能加运镜,`clips.md` 会单列「未能加运镜的切片」;告诉用户运镜在客户端 / 剪映里看,本地渲染与 PR 看不到。之后用 `gtrk patch` 裁剪 / 切分带运镜的片段,关键帧会跟着调整。
86
+ - 用了 `--speed-factor` 时:`clips.md` 的时长是**变速后**的时长并标注倍率;若有 clip 未能变速,`clips.md` 会单列「未能变速的切片」,如实告诉用户。
79
87
  - **先看 `clips.md`**(产物根,人读总览):一张表列全部切片的标题/时长/评分/一句话简介 —— 用它给用户复述「出了哪几条、各讲什么、建议先精修哪条」,别让用户自己开工程猜。逐条的入选理由、跳剪说明、高光词在 `clip{i}/clip.md`。
80
88
  - 开了 `--split-screen` 时:**分屏素材落在毛片旁的 `split_screen/` 子目录**(工程素材路径指向那里,别移动/删除,移动了工程会缺素材)——这点要提前告知用户。
81
89
  - 剪映草稿已拷入草稿根(给了 `--jianying-draft-dir` 时),剪映里直接可见 `<产物根名>_clip{i}`。**判据**:草稿目录里必须是 `draft_content.json` + `draft_meta_info.json` 两个精确文件名(云端产物侧的 `clip{i}_` 前缀在拷进草稿根这一跳被剥掉,产物目录 `clip{i}/jianying/` 里保留带前缀的归档原名)。CLI 日志按实际齐全条数报「N/M 条两件套齐全」,不齐的记进 `result.json` 的 `errors`、该 clip 的 `jianyingDraftPath` 为 `null`。