ossclip 0.1.30 → 0.1.33

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.
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>ossclip editor</title>
7
- <script type="module" crossorigin src="/assets/index-DfTreNoE.js"></script>
7
+ <script type="module" crossorigin src="/assets/index-DA7vDWn_.js"></script>
8
8
  <link rel="stylesheet" crossorigin href="/assets/index-Bx2VQLP8.css">
9
9
  </head>
10
10
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ossclip",
3
- "version": "0.1.30",
3
+ "version": "0.1.33",
4
4
  "description": "Local-first CLI video producer: cuts silence and fillers, word-timed captions, face-aware framing, and LLM-planned code-rendered graphics — transcription and rendering never leave your machine",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -36,9 +36,9 @@
36
36
  "commander": "^12.1.0",
37
37
  "tsx": "^4.19.0",
38
38
  "zod": "^3.25.76",
39
- "@ossclip/core": "0.1.30",
40
- "@ossclip/renderer": "0.1.30",
41
- "@ossclip/scenes": "0.1.30"
39
+ "@ossclip/core": "0.1.33",
40
+ "@ossclip/renderer": "0.1.33",
41
+ "@ossclip/scenes": "0.1.33"
42
42
  },
43
43
  "homepage": "https://github.com/AhsanAyaz/ossclip#readme",
44
44
  "bugs": {
@@ -3,6 +3,7 @@ import {
3
3
  applyCaptionRangeEdits,
4
4
  applyCaptionWordHides,
5
5
  applyCaptionLineTiming,
6
+ applyCaptionLineWindows,
6
7
  captionEditsToKeep,
7
8
  isLegacyCaptionKey,
8
9
  migrateCaptionKeys,
@@ -14,6 +15,7 @@ import type {
14
15
  CaptionKeyMigration,
15
16
  CaptionLine,
16
17
  OverrideDoc,
18
+ TimeMap,
17
19
  } from "@ossclip/core";
18
20
 
19
21
  /**
@@ -288,10 +290,17 @@ export interface CaptionReconciliation {
288
290
  * (`produce.ts` parses it at the top of the run). On raw `JSON.parse` output a
289
291
  * literal `"__proto__"` key would be assigned THROUGH rather than kept, and
290
292
  * the migration would report nothing lost while losing it.
293
+ *
294
+ * `map` is the run's own cutlist map — the one `baseLines` were built through
295
+ * — and exists for the WINDOW layer alone (`applyCaptionLineWindows`): windows
296
+ * are stored in source seconds and these lines speak output seconds. Taken as
297
+ * a parameter rather than rebuilt here for the usual reason: two maps is how
298
+ * this pass and the render would come to place a caption differently.
291
299
  */
292
300
  export function reconcileCaptionEdits(
293
301
  doc: OverrideDoc,
294
302
  baseLines: readonly CaptionLine[],
303
+ map: TimeMap,
295
304
  ): CaptionReconciliation {
296
305
  const log: string[] = [];
297
306
  const migration = migrateCaptionKeys(doc.captions, baseLines);
@@ -351,5 +360,21 @@ export function reconcileCaptionEdits(
351
360
  const nudged = appliedCaptionEditCount(doc.captionLineTiming, timed.dropped);
352
361
  if (nudged > 0) log.push(`▸ ${nudged} caption timing nudge(s) applied`);
353
362
  for (const d of timed.dropped) log.push(captionTimingDropLine(d));
354
- return { doc: migrated, lines: timed.lines, reanchored: reanchored > 0, log };
363
+ // WINDOWS last of all — `applyCaptionLayers`' one authoritative order: an
364
+ // absolute window is the user's final answer about when a caption is on
365
+ // screen, so it runs after (and overrides) the nudge layer. Counted with
366
+ // `appliedCaptionEditCount` for the same reason the nudges are: this layer
367
+ // also reports a `duplicate-anchor` drop per EXTRA claimant, so a plain
368
+ // subtraction would erase the line for a window that did apply. No key
369
+ // migration: `captionLineWindows` postdates §137, and the write-back above
370
+ // spreads it through untouched. Drops reuse `captionTimingDropLine` rather
371
+ // than earning a fifth sentence: both records answer "when is this caption
372
+ // on screen", both drop for the SAME two reasons (no line starts there any
373
+ // more / a second claimant), and the fix — re-make it in the timing tool —
374
+ // is one gesture, which is the test that function's docstring sets.
375
+ const windowed = applyCaptionLineWindows(timed.lines, doc.captionLineWindows, map);
376
+ const placed = appliedCaptionEditCount(doc.captionLineWindows, windowed.dropped);
377
+ if (placed > 0) log.push(`▸ ${placed} caption window(s) placed by the editor`);
378
+ for (const d of windowed.dropped) log.push(captionTimingDropLine(d));
379
+ return { doc: migrated, lines: windowed.lines, reanchored: reanchored > 0, log };
355
380
  }