@gitruck/cli 1.0.6 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitruck/cli",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "同合云成片流水线 CLI —— agent 驱动云端任务、产物拉回本地、三方工程文件(客户端/剪映/PR)互通。",
5
5
  "license": "MIT",
6
6
  "author": "Gitruck (同合云)",
@@ -46,10 +46,10 @@
46
46
  ],
47
47
  "scripts": {
48
48
  "gtrk": "bun run src/index.ts",
49
- "build": "bun build ./src/index.ts --target=node --outfile dist/index.js",
49
+ "build": "bun build ./src/index.ts --target=node --minify --outfile dist/index.js",
50
50
  "typecheck": "tsc --noEmit",
51
51
  "prepublishOnly": "npm run typecheck && npm test && bun run build",
52
- "test": "esbuild src/lib/compliance-notice.ts src/lib/first-run-tutorial.ts src/lib/desktop-client-hint.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/column-config.ts src/lib/matrix.ts src/lib/matrix-material.ts src/lib/matrix-fetch.ts src/lib/matrix-lay.ts src/lib/embed-client.ts src/lib/describe.ts src/lib/local-index.ts src/lib/local-search.ts src/lib/qc.ts src/lib/image-move.ts src/lib/cloud-render-guard.ts src/lib/material-integrity.ts src/lib/solid-png.ts src/lib/mg-lint.ts src/lib/mg-lay.ts src/lib/mg-render.ts src/lib/tool-descriptors.ts src/lib/tool-runner.ts src/lib/tool-pricing.ts src/lib/transcript.ts src/lib/runtime-assets.ts src/lib/subtitle-lay.ts src/lib/audio-align.ts --bundle --platform=node --format=esm --external:bun:sqlite --outdir=.test-build --out-extension:.js=.mjs && esbuild src/commands/split.ts --bundle --platform=node --format=esm --outdir=.test-build --out-extension:.js=.mjs && esbuild src/commands/patch.ts --bundle --platform=node --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 --format=esm --outfile=.test-build/mg-cmd.mjs && esbuild src/commands/tool.ts --bundle --platform=node --format=esm --outfile=.test-build/tool-cmd.mjs && esbuild src/commands/transcript.ts --bundle --platform=node --format=esm --outfile=.test-build/transcript-cmd.mjs && esbuild src/commands/project.ts --bundle --platform=node --format=esm --outfile=.test-build/project-cmd.mjs && esbuild src/commands/audio.ts --bundle --platform=node --format=esm --outfile=.test-build/audio-cmd.mjs && esbuild src/commands/subtitle.ts --bundle --platform=node --format=esm --outfile=.test-build/subtitle-cmd.mjs && esbuild src/commands/feedback.ts --bundle --platform=node --format=esm --outfile=.test-build/feedback-cmd.mjs && esbuild src/commands/music-visualizer.ts --bundle --platform=node --format=esm --external:commander --outfile=.test-build/music-visualizer-cmd.mjs && esbuild src/commands/long2short.ts --bundle --platform=node --format=esm --external:commander --outfile=.test-build/long2short-cmd.mjs && esbuild src/commands/skills.ts --bundle --platform=node --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/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 --format=esm --outdir=.test-build/convert --out-extension:.js=.mjs && esbuild src/lib/mad/selector.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 --format=esm --outdir=.test-build/mad --out-extension:.js=.mjs && node --import ./test/helpers/test-home.mjs --test \"test/*.test.mjs\"",
52
+ "test": "esbuild src/lib/compliance-notice.ts src/lib/first-run-tutorial.ts src/lib/desktop-client-hint.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/column-config.ts src/lib/matrix.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-qc.ts src/lib/arrange-qc-bind.ts src/lib/embed-client.ts src/lib/describe.ts src/lib/local-index.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/material-integrity.ts src/lib/solid-png.ts src/lib/mg-lint.ts src/lib/mg-lay.ts src/lib/mg-render.ts src/lib/tool-descriptors.ts src/lib/tool-runner.ts src/lib/tool-pricing.ts src/lib/transcript.ts src/lib/runtime-assets.ts src/lib/subtitle-lay.ts src/lib/audio-align.ts --bundle --platform=node --format=esm --external:bun:sqlite --outdir=.test-build --out-extension:.js=.mjs && esbuild src/commands/split.ts --bundle --platform=node --format=esm --outdir=.test-build --out-extension:.js=.mjs && esbuild src/commands/patch.ts --bundle --platform=node --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 --format=esm --outfile=.test-build/mg-cmd.mjs && esbuild src/commands/tool.ts --bundle --platform=node --format=esm --outfile=.test-build/tool-cmd.mjs && esbuild src/commands/transcript.ts --bundle --platform=node --format=esm --outfile=.test-build/transcript-cmd.mjs && esbuild src/commands/project.ts --bundle --platform=node --format=esm --outfile=.test-build/project-cmd.mjs && esbuild src/commands/audio.ts --bundle --platform=node --format=esm --outfile=.test-build/audio-cmd.mjs && esbuild src/commands/subtitle.ts --bundle --platform=node --format=esm --outfile=.test-build/subtitle-cmd.mjs && esbuild src/commands/feedback.ts --bundle --platform=node --format=esm --outfile=.test-build/feedback-cmd.mjs && esbuild src/commands/music-visualizer.ts --bundle --platform=node --format=esm --external:commander --outfile=.test-build/music-visualizer-cmd.mjs && esbuild src/commands/long2short.ts --bundle --platform=node --format=esm --external:commander --outfile=.test-build/long2short-cmd.mjs && esbuild src/commands/oralcut.ts --bundle --platform=node --format=esm --external:commander --outfile=.test-build/oralcut-cmd.mjs && esbuild src/commands/skills.ts --bundle --platform=node --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/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 --format=esm --outdir=.test-build/convert --out-extension:.js=.mjs && esbuild src/lib/mad/selector.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 --format=esm --outdir=.test-build/mad --out-extension:.js=.mjs && node --import ./test/helpers/test-home.mjs --test \"test/*.test.mjs\"",
53
53
  "openspec:gate": "node openspec/gate.mjs"
54
54
  },
55
55
  "devDependencies": {
@@ -37,6 +37,30 @@ description: 美食解说垂类图纸(解说链示例)——把探店/密着
37
37
  检索所得与素材互证后才入稿、档案标注来源;
38
38
  - **做饭流程线**:步骤忠实、关键动作给特写位(刀工/火候/翻面)、成品定格收束。
39
39
 
40
+ ## 二′、L1 看点 rubric · 画面投影版(260828 新增,供 `--highlight-weight` 用)
41
+
42
+ `highlight` 是**镜头看点分**——服务端 VLM 对着一帧画面打 0–100。喂给它的评分准则
43
+ (`highlight_rubric`)按垂类走,美食这一档取下面这份:
44
+
45
+ ```
46
+ 判这一帧对美食短视频有没有「看点」,0-100:
47
+ - 大分量怼脸:食物占画面主体且分量夸张(堆尖的饭、溢出碗沿的面、整条鱼)
48
+ - 夸张数量与价格的实物:成排的锅/几十份摆盘/写着惊人价格的标牌
49
+ - 人山排队:门口长队、满座、等位人群
50
+ - 名场面动作:颠勺起火、切生鱼片、拉面甩水、铁板翻面
51
+ - 反差罕见:凌晨空店、后厨全景、老器物、店主的手
52
+ 低分:空镜过渡、无主体的墙面桌面、拍糊的中间帧、纯字幕帧
53
+ ```
54
+
55
+ > **分工注记(MUST 遵守)**:本 rubric 只判**镜头可见之物**。知识侧要素——店家来历、
56
+ > 行业内幕、地域饮食脉络、名人轶事——**不进画面 rubric**,它们归写稿与背景检索(§二 已列)。
57
+ > 把知识侧写进来会让 VLM 对着一碗面找「历史事件」,产出一堆无意义低分并拉偏排序。
58
+ >
59
+ > 两侧的分工是:**画面 rubric 管「这一帧值不值得看」,写稿管「这件事值不值得讲」。**
60
+
61
+ 个性化:不满意这份准则的用户走 `gtrk-style-maker` 建自己的美食 skill,把 rubric 换成自己的口味
62
+ (这正是 rubric 参数化的意义——L1 归垂类图纸持有,不硬编码在服务端)。
63
+
40
64
  ## 三、铺排与引用段(引用正本,垂类注记)
41
65
 
42
66
  - 铺排走正本 §三:有出处直排,无出处软窗(单调先验);做饭形态窗口更窄(工序容不得远跳)。
@@ -47,16 +71,24 @@ description: 美食解说垂类图纸(解说链示例)——把探店/密着
47
71
 
48
72
  命令序照正本 §五(索引/字幕锚 → 写稿+出处 → 检查点① → 基座 → 建工程 → 拆分 → 铺排 →
49
73
  字卡 → BGM → 字幕),配方口径(mark-weight 0.3 / BGM 0.10 / gap-fill fast)照旅拍 §五,引用不复制。
74
+ BGM 检索词照公约 §三′ 内容驱动(这家店的气质:地域/年代/客群/烟火感,禁通用词套路;
75
+ 候选给用户挑不许默认 top1;跨片避让自动生效)。
76
+ 看点加权:`--highlight-weight 0.2` 配 §二′ 的 rubric(**须先 `matrix describe --plan`**,
77
+ 否则全部候选中性、权重白传——lay 会就此告警)。
50
78
  BGM 选带人声歌曲(`audio_type:"song"`)时 **MUST 下载 `accompaniment_url` 伴奏版上轨**,
51
79
  不得直接用 `download_url` 原曲——人声与解说配音打架(260827 真机踩坑)。换已上轨的 BGM 文件时
52
80
  注意:`audio lay` 同源幂等按文件路径判定,**换不同文件不会替换旧轨**,须先剥旧 BGM 轨再 lay。
53
- 渲后 QC 铁则照公约 §二′(B-roll 覆盖链路粗剪也必过 QC,结论随交付呈现)。
81
+ 质检照公约 §二′「三级收敛前移」(260829 拍板,替代原「渲后必跑」):L1 结构自检恒开(零成本,含**闪帧风险不可判**的前置声明);L2 画音对齐在**落轨前**跑、`--arrange-qc` 用户可选且按帧计费;L3 渲后终检**不再逼渲**,本来就要本地渲交付时随渲附带。跑过的质检结论一律随交付呈现。
54
82
  字卡走 MG 临场泛化(公约 §三):店名条/菜名条/价格条为主,风格锚在这家店的气质上。
55
83
 
56
- ## 五、检查点①(必停一次)
84
+ ## 五、检查点①(拍板停一次;铺画面前另有一次用量确认)
57
85
 
58
86
  稿件(含引用窗口)+ 出处对照表(自备稿时)+ 画幅 + 音色(试听)+ BGM(试听)+ 字幕样式,
59
- 一屏一次拍板;此前零计费动作。
87
+ 一屏一次拍板;**此前零计费动作**(这条仍成立)。
88
+
89
+ > ⟲ **2026-08-31 订正**:本节原写「必停一次」。本地素材的编排自该日起默认走云端并按
90
+ > 「编排量」计费,`matrix lay` **跑前会再停一次**报预估——那次不是拍板,是花费确认。
91
+ > 详见 `gtrk-narration` 正本 §六 的 agent 纪律(先报用量拿同意,再带 `--yes`)。
60
92
 
61
93
  ## 六、个性化出路(垂类示例定位)
62
94
 
@@ -1,94 +1,99 @@
1
- ---
2
- name: gtrk-long2short
3
- description: 长剪短闭环——把一条长视频(课程/直播/播客/访谈毛片)通过同合云选段跳剪成多条高光短片工程,一次产出逐 clip 的 gtrk+剪映+PR 三方工程(可选智能分屏)。当用户想「长剪短 / 长视频切高光 / 直播切片 / 课程切短视频 / 播客出短片 / 两小时的课切成几条精华」时使用本 skill。凡涉及把长视频拆成多条可精修的短片工程,优先用本 skill 驱动 gtrk CLI 的 `long2short` 命令,不要手搓 ffmpeg、不要人工挑时间码。
4
- ---
5
-
6
- # 长剪短(gtrk-long2short)
7
-
8
- 把用户的一条长视频,用 `gtrk` CLI 跑通「**本地抽音频/720p 代理(毛片永不上传)** → 云端语义选段+跳剪(可选分屏)→ 逐 clip 拉回 gtrk/剪映/PR 三方工程」,再把产物目录回给用户。**CLI 是手、你是脑。**
9
-
10
- > 与智能剪口播(gtrk-oralcut)同一心智模型;差异是**一次任务出 N 条短片**,各自一份工程组落 `clip{i}/` 子目录。
11
-
12
- > **⚠️ 源片是「直播回放」?先去 `/gtrk-live-slicing`。** 直播回放有本 skill 不处理的场景约束:
13
- > **单次提交超 2 小时会被服务端直接拒**(`6019`,必须先分段)、选题必须经用户确认再出工程、
14
- > 按画面形态分段配分屏、源片自带的烧录贴片如实告知不动它。那张图纸编排完这些,
15
- > 最终仍然回到本 skill 的命令上——**它是场景图纸,这里是链路手册,配合用不冲突。**
16
-
17
- > **⚠️ 先确认用户要工程还是要成片。** 本 skill 是**粗剪**——出的是**可编辑工程**(gtrk + 剪映 + PR),
18
- > 给人二次精修用,毛片不上传。如果用户只要**能直接发布的成片**、不打算再剪,那该走**精剪**:
19
- > `gtrk tool video_long2short_pro`(走 `/gtrk-tools`,整片上传、云端渲染、计费约为粗剪两倍)。
20
- > 判断句:**「剪完还要不要再动?」要动 → 留在这儿;不动 → 转精剪。** 选错一次要白花积分重来。
21
-
22
- ## 前置:CLI 装没装 + 体检
23
-
24
- 先跑 `gtrk doctor`:
25
- - **`gtrk` 找不到** → 让用户装 `npm i -g @gitruck/cli@latest`(需先有 Node.js),再重试。
26
- - 报「缺 API Key」→ 让用户先跑一次 `gtrk init`(交互式、需真终端,你别替他跑)。
27
- - 全绿就往下走。
28
-
29
- ## 一条命令
30
-
31
- ```bash
32
- gtrk long2short "D:/毛片/课程.mp4" --language zh-CN --json
33
- ```
34
-
35
- 对谈/多人同框想要分屏:
36
-
37
- ```bash
38
- gtrk long2short "D:/毛片/对谈.mp4" --language zh-CN --split-screen --split-orientation tb --json
39
- ```
40
-
41
- ## 参数表
42
-
43
- | 参数 | 说明 |
44
- |---|---|
45
- | `--language <code>` | **必填**,源语种(如 zh-CN;取值以服务端支持列表为准,传错服务端会报枚举) |
46
- | `--split-screen` | 开启智能分屏:本地改传 **720p 代理**(否则只抽音频);云端检测多人同框段并烤 720p 分屏素材 |
47
- | `--split-orientation <o>` | 分屏方向 `auto|lr|tb`(缺省 auto=按内容可复现随机) |
48
- | `--main-topic <text>` | 主题引导,影响选段偏好 |
49
- | `--duration-pref <p>` / `--max-clip-sec <n>` | 成片时长偏好 / 单条上限秒。**成片条数由内容语义决定,不能指定条数** |
50
- | `--no-jump-cut` | 关闭跳剪(默认开:片内去水词冗余,只删不重排) |
51
- | `--subtitle-file <path>` | **现成单语字幕**(.srt/.ass)作转写来源,替代云端 ASR(用户手里有片源字幕/人工校对稿时用,省一次识别)。切点精度降为**字幕行边界**;双语/多层 .ass 会被拒;与 stt 类参数互斥 |
52
- | `--subtitle-out` | 逐 clip 另产**单语 .srt 字幕**(按目标画布档位智能拆行:横屏约 20 字/行、竖屏约 13 字/行),落 `clip{i}/srt/` |
53
- | `--keep-punctuation` | 字幕保留全部标点。缺省按统一口径去标点:逗号句号→空格、`?!` 等保留 |
54
- | `--output-size <s>` | 画布 `9:16|16:9|1:1` 或 `WxH`(缺省 9:16 竖版) |
55
- | `-f, --formats <list>` | 三方格式,缺省 `gtrk,jianying,xml`(云端逐 clip 直产;gtrk 恒有) |
56
- | `--jianying-draft-dir <dir>` | 剪映草稿根(或 `auto`);各 clip 草稿落 `<草稿根>/<产物根名>_clip{i}` |
57
- | `-o/--out`、`--no-open`、`--json`、`--reupload`、`--param/--params-json` | 与 oralcut 同口径 |
58
-
59
- ## 计费与跑前须知(每次都转述给用户)
60
-
61
- - 运行时 CLI 自动查询实时价格并在跑前打印——**把计费提示原样转述**;按**上传物音频时长**计费(≈原片时长),**长片先向用户确认再跑**。
62
- - 云端处理时长随片长涨(ASR+选段),CLI 轮询墙钟 60 分钟;超时不丢——产物根 `task.json` 里有 `task_id` 可恢复。
63
-
64
- ## 产物(跑完把这些讲给用户)
65
-
66
- - 产物根 `<毛片名>-long2short/`:`report.json`(选段报告)+ `result.json` + 逐 clip 子目录 `clip0/ clip1/ …`(各含 `gtrk/` 客户端工程、`jianying/` 草稿、`xml/` PR 工程;开了 `--subtitle-out` 另有 `srt/clip{i}.srt` 单语字幕)。
67
- - **先看 `clips.md`**(产物根,人读总览):一张表列全部切片的标题/时长/评分/一句话简介 —— 用它给用户复述「出了哪几条、各讲什么、建议先精修哪条」,别让用户自己开工程猜。逐条的入选理由、跳剪说明、高光词在 `clip{i}/clip.md`。
68
- - 开了 `--split-screen` 时:**分屏素材落在毛片旁的 `split_screen/` 子目录**(工程素材路径指向那里,别移动/删除,移动了工程会缺素材)——这点要提前告知用户。
69
- - 剪映草稿已拷入草稿根(给了 `--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`。
70
-
71
- ## 排错
72
-
73
- - **部分 clip 失败 / 个别分屏素材 404**:单点失败不连坐,`result.json` `errors` 有明细;把失败项如实告诉用户,其余产物照常可用。
74
- - **轮询超时/进程中断**:凭产物根 `task.json` 的 `task_id` 查询云端状态;任务在云端照常跑完,稍后可重取。
75
- - **clips 为空**:说明内容里没有可成片的高光段(纯语义选段),把 `report.json` 摘要给用户看原因。
76
- - **剪映里看不到草稿**:先看草稿目录里的**文件名**——必须是 `draft_content.json` + `draft_meta_info.json`,缺一件或带前缀剪映都不显示;`result.json` 里该 clip 的 `jianyingDraftPath` 为 `null` 即是此症。
77
-
78
- ---
79
-
80
- ## 改工程:走 `gtrk patch`,不要裸手改 JSON
81
-
82
- 跑完之后要**微调某个片段**(挪位置 / 改时长 / 切开 / 改音量)时,一律用 `gtrk patch`:
83
-
84
- ```bash
85
- gtrk patch move --project <dir> --clip <clip_id> --to 5.0
86
- gtrk patch trim --project <dir> --clip <clip_id> --out -1s
87
- ```
88
-
89
- **MUST NOT 直接编辑 `.gtrk` 的 JSON。** 片段时码是两套并存的(`clip_st`+`clip_ed` 与
90
- `clip_st`+`duration`):改一份不改另一份,客户端优先读 `clip_ed`、后端又不强校验它
91
- **没人报错,成片却用了陈旧出点**。`gtrk patch` 替你做恒等式同步 + 帧对齐 + 写前全档校验。
92
-
93
- > 参数手册在 `AGENT.md` 的「元素级编辑:`gtrk patch`」一节与 README 命令参考。
94
- > 本节**只指路不搬手册** —— 搬过来就会长出会漂移的副本。
1
+ ---
2
+ name: gtrk-long2short
3
+ description: 长剪短闭环——把一条长视频(课程/直播/播客/访谈毛片)通过同合云选段跳剪成多条高光短片工程,一次产出逐 clip 的 gtrk+剪映+PR 三方工程(可选智能分屏)。当用户想「长剪短 / 长视频切高光 / 直播切片 / 课程切短视频 / 播客出短片 / 两小时的课切成几条精华」时使用本 skill。凡涉及把长视频拆成多条可精修的短片工程,优先用本 skill 驱动 gtrk CLI 的 `long2short` 命令,不要手搓 ffmpeg、不要人工挑时间码。
4
+ ---
5
+
6
+ # 长剪短(gtrk-long2short)
7
+
8
+ 把用户的一条长视频,用 `gtrk` CLI 跑通「**本地抽音频/720p 代理(毛片永不上传)** → 云端语义选段+跳剪(可选分屏)→ 逐 clip 拉回 gtrk/剪映/PR 三方工程」,再把产物目录回给用户。**CLI 是手、你是脑。**
9
+
10
+ > 与智能剪口播(gtrk-oralcut)同一心智模型;差异是**一次任务出 N 条短片**,各自一份工程组落 `clip{i}/` 子目录。
11
+
12
+ > **⚠️ 源片是「直播回放」?先去 `/gtrk-live-slicing`。** 直播回放有本 skill 不处理的场景约束:
13
+ > **单次提交超 2 小时会被服务端直接拒**(`6019`,必须先分段)、选题必须经用户确认再出工程、
14
+ > 按画面形态分段配分屏、源片自带的烧录贴片如实告知不动它。那张图纸编排完这些,
15
+ > 最终仍然回到本 skill 的命令上——**它是场景图纸,这里是链路手册,配合用不冲突。**
16
+
17
+ > **⚠️ 先确认用户要工程还是要成片。** 本 skill 是**粗剪**——出的是**可编辑工程**(gtrk + 剪映 + PR),
18
+ > 给人二次精修用,毛片不上传。如果用户只要**能直接发布的成片**、不打算再剪,那该走**精剪**:
19
+ > `gtrk tool video_long2short_pro`(走 `/gtrk-tools`,整片上传、云端渲染、计费约为粗剪两倍)。
20
+ > 判断句:**「剪完还要不要再动?」要动 → 留在这儿;不动 → 转精剪。** 选错一次要白花积分重来。
21
+
22
+ ## 前置:CLI 装没装 + 体检
23
+
24
+ 先跑 `gtrk doctor`:
25
+ - **`gtrk` 找不到** → 让用户装 `npm i -g @gitruck/cli@latest`(需先有 Node.js),再重试。
26
+ - 报「缺 API Key」→ 让用户先跑一次 `gtrk init`(交互式、需真终端,你别替他跑)。
27
+ - 全绿就往下走。
28
+
29
+ ## 一条命令
30
+
31
+ ```bash
32
+ gtrk long2short "D:/毛片/课程.mp4" --language zh-CN --json
33
+ ```
34
+
35
+ 对谈/多人同框想要分屏:
36
+
37
+ ```bash
38
+ gtrk long2short "D:/毛片/对谈.mp4" --language zh-CN --split-screen --split-orientation tb --json
39
+ ```
40
+
41
+ ## 参数表
42
+
43
+ | 参数 | 说明 |
44
+ |---|---|
45
+ | `--language <code>` | **必填**,源语种(如 zh-CN;取值以服务端支持列表为准,传错服务端会报枚举) |
46
+ | `--split-screen` | 开启智能分屏:本地改传 **720p 代理**(否则只抽音频);云端检测多人同框段并烤 720p 分屏素材 |
47
+ | `--split-orientation <o>` | 分屏方向 `auto|lr|tb`(缺省 auto=按内容可复现随机) |
48
+ | `--main-topic <text>` | 主题引导,影响选段偏好 |
49
+ | `--duration-pref <p>` / `--max-clip-sec <n>` | 成片时长偏好 / 单条上限秒。**成片条数由内容语义决定,不能指定条数** |
50
+ | `--no-jump-cut` | 关闭跳剪(默认开:片内去水词冗余,只删不重排) |
51
+ | `--subtitle-file <path>` | **现成单语字幕**(.srt/.ass)作转写来源,替代云端 ASR(用户手里有片源字幕/人工校对稿时用,省一次识别)。切点精度降为**字幕行边界**;双语/多层 .ass 会被拒;与 stt 类参数互斥 |
52
+ | `--subtitle-out` | 逐 clip 另产**单语 .srt 字幕**(按目标画布档位智能拆行:横屏约 20 字/行、竖屏约 13 字/行),落 `clip{i}/srt/` |
53
+ | `--keep-punctuation` | 字幕保留全部标点。缺省按统一口径去标点:逗号句号→空格、`?!` 等保留 |
54
+ | `--output-size <s>` | 画布 `9:16|16:9|1:1` 或 `WxH`(缺省 9:16 竖版) |
55
+ | `-f, --formats <list>` | 三方格式,缺省 `gtrk,jianying,xml`(云端逐 clip 直产;gtrk 恒有) |
56
+ | `--jianying-draft-dir <dir>` | 剪映草稿根(或 `auto`);各 clip 草稿落 `<草稿根>/<产物根名>_clip{i}` |
57
+ | `-o/--out`、`--no-open`、`--json`、`--reupload`、`--param/--params-json` | 与 oralcut 同口径 |
58
+
59
+ ## 计费与跑前须知(每次都转述给用户)
60
+
61
+ - 运行时 CLI 自动查询实时价格并在跑前打印——**把计费提示原样转述**;按**上传物音频时长**计费(≈原片时长),**长片先向用户确认再跑**。
62
+ - **源片 > 2 小时跑不了**:CLI 在上传前就会拦下(零抽取、零上传、零扣费),不是跑到一半才失败。
63
+ 遇到超长源片(直播回放常见)**先分段再逐段跑**,建议 **40 分钟/段**——
64
+ 切段用流拷贝、秒级完成、不重编码:`ffmpeg -ss 0 -t 2400 -i "<源片>" -c copy "<源片名>_seg01.mp4"`。
65
+ 各段产出的 clip 事后汇总成一张选题清单即可。**分段是常态动作,不是降级方案**。
66
+ - 云端处理时长随片长涨(ASR+选段),CLI 轮询墙钟 60 分钟;超时不丢——产物根 `task.json` 里有 `task_id` 可恢复。
67
+ 这也是 40 分钟/段的由来:墙钟 60min ÷ 开分屏实测耗时比上界 1.25× 48min,取 40 留余量。
68
+
69
+ ## 产物(跑完把这些讲给用户)
70
+
71
+ - 产物根 `<毛片名>-long2short/`:`report.json`(选段报告)+ `result.json` + 逐 clip 子目录 `clip0/ clip1/ …`(各含 `gtrk/` 客户端工程、`jianying/` 草稿、`xml/` PR 工程;开了 `--subtitle-out` 另有 `srt/clip{i}.srt` 单语字幕)。
72
+ - **先看 `clips.md`**(产物根,人读总览):一张表列全部切片的标题/时长/评分/一句话简介 —— 用它给用户复述「出了哪几条、各讲什么、建议先精修哪条」,别让用户自己开工程猜。逐条的入选理由、跳剪说明、高光词在 `clip{i}/clip.md`。
73
+ - 开了 `--split-screen` 时:**分屏素材落在毛片旁的 `split_screen/` 子目录**(工程素材路径指向那里,别移动/删除,移动了工程会缺素材)——这点要提前告知用户。
74
+ - 剪映草稿已拷入草稿根(给了 `--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`。
75
+
76
+ ## 排错
77
+
78
+ - **部分 clip 失败 / 个别分屏素材 404**:单点失败不连坐,`result.json` 的 `errors` 有明细;把失败项如实告诉用户,其余产物照常可用。
79
+ - **轮询超时/进程中断**:凭产物根 `task.json` 的 `task_id` 查询云端状态;任务在云端照常跑完,稍后可重取。
80
+ - **clips 为空**:说明内容里没有可成片的高光段(纯语义选段),把 `report.json` 摘要给用户看原因。
81
+ - **剪映里看不到草稿**:先看草稿目录里的**文件名**——必须是 `draft_content.json` + `draft_meta_info.json`,缺一件或带前缀剪映都不显示;`result.json` 里该 clip 的 `jianyingDraftPath` 为 `null` 即是此症。
82
+
83
+ ---
84
+
85
+ ## 改工程:走 `gtrk patch`,不要裸手改 JSON
86
+
87
+ 跑完之后要**微调某个片段**(挪位置 / 改时长 / 切开 / 改音量)时,一律用 `gtrk patch`:
88
+
89
+ ```bash
90
+ gtrk patch move --project <dir> --clip <clip_id> --to 5.0
91
+ gtrk patch trim --project <dir> --clip <clip_id> --out -1s
92
+ ```
93
+
94
+ **MUST NOT 直接编辑 `.gtrk` 的 JSON。** 片段时码是两套并存的(`clip_st`+`clip_ed` 与
95
+ `clip_st`+`duration`):改一份不改另一份,客户端优先读 `clip_ed`、后端又不强校验它 ⇒
96
+ **没人报错,成片却用了陈旧出点**。`gtrk patch` 替你做恒等式同步 + 帧对齐 + 写前全档校验。
97
+
98
+ > 参数手册在 `AGENT.md` 的「元素级编辑:`gtrk patch`」一节与 README 命令参考。
99
+ > 本节**只指路不搬手册** —— 搬过来就会长出会漂移的副本。