From e1978c61e353d68a1d7e936ec422c456f5dd302a Mon Sep 17 00:00:00 2001 From: Arham Wani Date: Tue, 4 Aug 2026 05:44:48 +0530 Subject: [PATCH 1/2] fix(timeline): prefer exact segment clip matches --- .../timeline/virtual-preview.test.ts | 18 ++++++++++++++++++ src/lib/ai-edition/timeline/virtual-preview.ts | 5 ++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/lib/ai-edition/timeline/virtual-preview.test.ts b/src/lib/ai-edition/timeline/virtual-preview.test.ts index f3dd64888..bb100f16e 100644 --- a/src/lib/ai-edition/timeline/virtual-preview.test.ts +++ b/src/lib/ai-edition/timeline/virtual-preview.test.ts @@ -5,6 +5,7 @@ import { formatSeconds } from "./format"; import { clampVirtualTime, findNextKeptSegment, + findRawClipForSegment, getRawVirtualStartTime, keptWordIdSet, locateKeptSegment, @@ -371,6 +372,23 @@ describe("virtual-preview pure functions", () => { expect(getRawVirtualStartTime(segClip2Part1, rawClips)).toBe(13.2); }); + it("findRawClipForSegment prefers an exact raw id over an earlier prefix match", () => { + const rawClips: AxcutClip[] = [ + { ...clips[0], id: "clip" }, + { + ...clips[1], + id: "clip_seg1", + }, + ]; + const segment = { ...rawClips[1] }; + + expect(findRawClipForSegment(segment, rawClips)?.id).toBe("clip_seg1"); + expect(getRawVirtualStartTime(segment, rawClips)).toBe(10); + expect(findRawClipForSegment({ ...segment, id: "clip_seg1_seg2" }, rawClips)?.id).toBe( + "clip_seg1", + ); + }); + it("findNextKeptSegment finds next kept segment across multi-clip trim boundary", () => { const rawClips: AxcutClip[] = [ { diff --git a/src/lib/ai-edition/timeline/virtual-preview.ts b/src/lib/ai-edition/timeline/virtual-preview.ts index 1cdc5d2f6..be04b5e1c 100644 --- a/src/lib/ai-edition/timeline/virtual-preview.ts +++ b/src/lib/ai-edition/timeline/virtual-preview.ts @@ -58,7 +58,10 @@ export function findRawClipForSegment( rawClips: AxcutClip[], ): AxcutClip | undefined { return ( - rawClips.find((c) => c.id === segment.id || segment.id.startsWith(`${c.id}_seg`)) ?? + rawClips.find((clip) => clip.id === segment.id) ?? + [...rawClips] + .sort((a, b) => b.id.length - a.id.length) + .find((clip) => segment.id.startsWith(`${clip.id}_seg`)) ?? rawClips.find( (c) => c.assetId === segment.assetId && From feab5e9bf1b434326e920e50f058c70a2c51ce38 Mon Sep 17 00:00:00 2001 From: Arham Wani Date: Tue, 4 Aug 2026 06:05:24 +0530 Subject: [PATCH 2/2] perf(timeline): scan segment parents once --- src/lib/ai-edition/timeline/virtual-preview.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lib/ai-edition/timeline/virtual-preview.ts b/src/lib/ai-edition/timeline/virtual-preview.ts index be04b5e1c..1859f78f4 100644 --- a/src/lib/ai-edition/timeline/virtual-preview.ts +++ b/src/lib/ai-edition/timeline/virtual-preview.ts @@ -59,9 +59,10 @@ export function findRawClipForSegment( ): AxcutClip | undefined { return ( rawClips.find((clip) => clip.id === segment.id) ?? - [...rawClips] - .sort((a, b) => b.id.length - a.id.length) - .find((clip) => segment.id.startsWith(`${clip.id}_seg`)) ?? + rawClips.reduce((longest, clip) => { + if (!segment.id.startsWith(`${clip.id}_seg`)) return longest; + return !longest || clip.id.length > longest.id.length ? clip : longest; + }, undefined) ?? rawClips.find( (c) => c.assetId === segment.assetId &&