@gitruck/cli 1.3.5 → 1.3.6

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/CHANGELOG.md CHANGED
@@ -11,6 +11,11 @@
11
11
 
12
12
  ## 未发布
13
13
 
14
+ ## 1.3.6(2026-10-18)
15
+
16
+ - `gtrk composite bake` 认合成槽位的用户覆盖 `crop` / `box` / `slip_ms`:校验与输入快照和服务端参考实现同口径,出片台按「颗粒几何 → box → crop → 适配 / 构图 → 形状圆角」绘制,ref 槽取帧加 `slip_ms`;`--abi` 新增 `overrides` 能力位。**客户端 1.2.13 起会写这些覆盖**,旧版 CLI 遇到带覆盖的合成按粗剪出片并提示升级。
17
+ - 烘焙取消或出错时,满载机器上也能很快收尾:先提高被结束进程的优先级再结束,浏览器遗留子进程合并一次查询收掉,删除工作目录限时。
18
+
14
19
  ## 1.3.5(2026-10-17)
15
20
 
16
21
  - 新增合成层命令族 `gtrk composite`:`plan` / `review` / `scaffold` / `shots` 把候选窗口写进 `struct_meta.composite`(客户端大纲 CP 行),支持整片铺满 / AI 判定 / 指定区间三种入口;`build` 把场景构建成自包含合成颗粒(随包工具箱 `composite-kit@1`);`lint` 做静态校验加本机 Chrome / Edge 逐帧排版机检(穿模 / 线条穿画面 / 越界);`lay` 按自产身份幂等铺进 beat 轨最上层。新增 `/gtrk-composite` skill,口播图纸挂可选合成步。
@@ -143,7 +143,8 @@ function sourceFor(b, T, f) {
143
143
  const hit = byClip.get(b.clip_id); if (!hit) return null;
144
144
  const c = hit.clip;
145
145
  const tt = Math.min(Math.max(T, c.track_st), lastFrameT(c));
146
- return { material: c.material, sec: clipSrc(c, tt) };
146
+ // slip_ms:源时钟上整体前后挪取帧(add-composite-slot-user-overrides);超过素材末尾由 locate 的 eof 段取末帧
147
+ return { material: c.material, sec: Math.max(0, clipSrc(c, tt) + (b.slip_ms || 0) / 1000) };
147
148
  }
148
149
  if (b.kind === "ref-lane") {
149
150
  const hit = byClip.get(b.lane_clip_id); if (!hit) return null;
@@ -160,6 +161,21 @@ function sourceFor(b, T, f) {
160
161
  }
161
162
  return null;
162
163
  }
164
+ /**
165
+ * 用户覆盖套到颗粒回报的几何上(add-composite-slot-user-overrides,与客户端 `applySlotOverrides` 逐值相同):
166
+ * box = 以槽位中心缩放 scale_pm/1000 倍、中心位移舞台宽高的 dx_pm / dy_pm 千分比,圆角同乘缩放;
167
+ * crop = 替换颗粒的 data-crop([上, 右, 下, 左] 比例)。
168
+ */
169
+ function applySlotOverrides(g, b) {
170
+ let out = g;
171
+ if (b.box) {
172
+ const s = b.box.scale_pm / 1000, w = g.w * s, h = g.h * s;
173
+ const cx = g.x + g.w / 2 + (b.box.dx_pm / 1000) * 1920, cy = g.y + g.h / 2 + (b.box.dy_pm / 1000) * 1080;
174
+ out = { ...out, x: cx - w / 2, y: cy - h / 2, w, h, radius: (g.radius || 0) * s };
175
+ }
176
+ if (b.crop) out = { ...out, crop: [b.crop.t_pm / 1000, b.crop.r_pm / 1000, b.crop.b_pm / 1000, b.crop.l_pm / 1000] };
177
+ return out;
178
+ }
163
179
  /** fit / framing / crop 合成的绘制矩形(与客户端 `slotDrawRect` 逐值相同;源或槽位尺寸为 0 时返回 null,不画)。 */
164
180
  function drawRect(g, sw0, sh0, fit, framing) {
165
181
  const [top, right, bottom, left] = g.crop;
@@ -245,7 +261,8 @@ window.renderAt = async (T) => {
245
261
  });
246
262
  const ready = (await Promise.all(jobs)).filter(Boolean);
247
263
  ctx.clearRect(0, 0, 1920, 1080);
248
- for (const { g, b, v, k, tag, img } of ready) {
264
+ for (const { g: g0, b, v, k, tag, img } of ready) {
265
+ const g = applySlotOverrides(g0, b);
249
266
  // 中间文件底部的帧号条不进画面:源高度按去掉条带算
250
267
  const r = img ? drawRect(g, img.naturalWidth, img.naturalHeight, b.fit || g.fit, b.framing) : drawRect(g, v.videoWidth, v.videoHeight - (tag || 0), b.fit || g.fit, b.framing);
251
268
  if (!r) continue;