From 0a049d97a9138fd4d5f324b21595ff64ce03850d Mon Sep 17 00:00:00 2001 From: Aditya Garud <153842990+yashranaway@users.noreply.github.com> Date: Thu, 29 Oct 2026 20:40:56 +0000 Subject: [PATCH] fix(web): preserve the original source for transcript backfills --- .../integration/transcribe-workflow.test.ts | 53 +++++++++++++++++++ apps/web/workflows/transcribe.ts | 10 ++-- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/apps/web/__tests__/integration/transcribe-workflow.test.ts b/apps/web/__tests__/integration/transcribe-workflow.test.ts index 3ca5d49b93e..838cb15d980 100644 --- a/apps/web/__tests__/integration/transcribe-workflow.test.ts +++ b/apps/web/__tests__/integration/transcribe-workflow.test.ts @@ -401,6 +401,59 @@ describe("backfillEditTranscriptWorkflow", () => { ); }); + it("never substitutes edited media when the original source is inaccessible", async () => { + const originalKey = "user-456/video-123/original.mp4"; + state.editRows = [ + { + sourceKey: originalKey, + editSpec: { + version: 1, + sourceDuration: 12, + keepRanges: [{ start: 8, end: 12 }], + }, + }, + ]; + mocks.getInternalSignedObjectUrl.mockImplementation((key: string) => + pipeValue(`https://storage.test/${key}`), + ); + vi.stubGlobal( + "fetch", + vi.fn( + async (url: string) => + new Response(url.endsWith(originalKey) ? null : "edited audio", { + status: url.endsWith(originalKey) ? 404 : 200, + }), + ), + ); + + const { backfillEditTranscriptWorkflow } = await import( + "@/workflows/transcribe" + ); + const result = await backfillEditTranscriptWorkflow({ + videoId: "video-123", + userId: "user-456", + requestId: "request-1", + }); + + expect(result).toEqual({ success: false }); + expect(mocks.transcribe).not.toHaveBeenCalled(); + expect(mocks.putObject).not.toHaveBeenCalled(); + expect(mocks.getInternalSignedObjectUrl).toHaveBeenCalledExactlyOnceWith( + originalKey, + ); + expect(mocks.updates).toContainEqual( + expect.objectContaining({ + metadata: expect.objectContaining({ + strings: expect.arrayContaining([ + expect.stringContaining( + "'$.editTranscriptBackfill.status', 'error'", + ), + ]), + }), + }), + ); + }); + it("does not run a backfill after its database claim is replaced", async () => { const { backfillEditTranscriptWorkflow } = await import( "@/workflows/transcribe" diff --git a/apps/web/workflows/transcribe.ts b/apps/web/workflows/transcribe.ts index 7be4f9171a1..fa42f68b1af 100644 --- a/apps/web/workflows/transcribe.ts +++ b/apps/web/workflows/transcribe.ts @@ -623,11 +623,11 @@ async function resolveVideoSourceUrl( .where(eq(videoUploads.videoId, videoId as Video.VideoId)) .limit(1); - const candidateKeys = [ - sourceKeyOverride, - `${userId}/${videoId}/result.mp4`, - upload[0]?.rawFileKey, - ].filter( + const candidateKeys = ( + sourceKeyOverride + ? [sourceKeyOverride] + : [`${userId}/${videoId}/result.mp4`, upload[0]?.rawFileKey] + ).filter( (value, index, values): value is string => Boolean(value) && values.indexOf(value) === index, );