From ed72d24f5729e98ccdb5e3cdf3bb1b484fe983cf Mon Sep 17 00:00:00 2001 From: Saloni Date: Mon, 25 May 2026 23:57:03 +0800 Subject: [PATCH 1/3] Add paths methods --- scripts/config/paths.test.ts | 213 +++++++++++++++++++++++++++++++++++ scripts/config/paths.ts | 158 ++++++++++++++++++++++++++ 2 files changed, 371 insertions(+) create mode 100644 scripts/config/paths.test.ts create mode 100644 scripts/config/paths.ts diff --git a/scripts/config/paths.test.ts b/scripts/config/paths.test.ts new file mode 100644 index 0000000..9bb2166 --- /dev/null +++ b/scripts/config/paths.test.ts @@ -0,0 +1,213 @@ +import path from 'path'; +import { + projectFile, + artifactDir, + transcribeInput, + transcribeRawDir, + transcriptRaw, + diarizationOutput, + hookQaDir, + transcriptOutput, + transcriptDoc, + syncVideoDir, + syncAudioDir, + syncOutputDir, + syncedVideo, + syncedVideoAngle, + cameraProfilesDir, + cameraProfiles, + shortsDir, + shortClipDir, + shortTranscript, + shortDoc, + shortsCameraProfiles, + shortsTranscribeRawDir, + shortsTranscriptRaw, + carouselDir, + carouselClipDir, + carouselTranscript, + carouselDoc, + thumbnailDir, + thumbnailCameraProfiles, +} from './paths'; + +const ROOT = '/project/root'; + +describe('project / artifact', () => { + it('projectFile', () => { + expect(projectFile(ROOT)).toBe(path.join(ROOT, '.ragtech', 'project.json')); + }); + + it('artifactDir', () => { + expect(artifactDir(ROOT)).toBe(path.join(ROOT, '.ragtech', 'artifacts')); + }); +}); + +describe('transcribe pipeline', () => { + it('transcribeInput', () => { + expect(transcribeInput(ROOT)).toBe(path.join(ROOT, 'public', 'transcribe', 'input')); + }); + + it('transcribeRawDir', () => { + expect(transcribeRawDir(ROOT)).toBe(path.join(ROOT, 'public', 'transcribe', 'output', 'raw')); + }); + + it('transcriptRaw', () => { + expect(transcriptRaw(ROOT)).toBe( + path.join(ROOT, 'public', 'transcribe', 'output', 'raw', 'transcript.raw.json'), + ); + }); + + it('diarizationOutput', () => { + expect(diarizationOutput(ROOT)).toBe( + path.join(ROOT, 'public', 'transcribe', 'output', 'raw', 'diarization.json'), + ); + }); + + it('hookQaDir', () => { + expect(hookQaDir(ROOT)).toBe( + path.join(ROOT, 'public', 'transcribe', 'output', 'hook-qa'), + ); + }); +}); + +describe('edit / longform output', () => { + it('transcriptOutput', () => { + expect(transcriptOutput(ROOT)).toBe(path.join(ROOT, 'public', 'edit', 'transcript.json')); + }); + + it('transcriptDoc', () => { + expect(transcriptDoc(ROOT)).toBe(path.join(ROOT, 'public', 'edit', 'transcript.doc.txt')); + }); +}); + +describe('sync pipeline', () => { + it('syncVideoDir', () => { + expect(syncVideoDir(ROOT)).toBe(path.join(ROOT, 'public', 'sync', 'video')); + }); + + it('syncAudioDir', () => { + expect(syncAudioDir(ROOT)).toBe(path.join(ROOT, 'public', 'sync', 'audio')); + }); + + it('syncOutputDir', () => { + expect(syncOutputDir(ROOT)).toBe(path.join(ROOT, 'public', 'sync', 'output')); + }); + + it('syncedVideo', () => { + expect(syncedVideo(ROOT)).toBe( + path.join(ROOT, 'public', 'sync', 'output', 'synced-output.mp4'), + ); + }); + + it('syncedVideoAngle — index 1', () => { + expect(syncedVideoAngle(1, ROOT)).toBe( + path.join(ROOT, 'public', 'sync', 'output', 'synced-output-1.mp4'), + ); + }); + + it('syncedVideoAngle — index 2', () => { + expect(syncedVideoAngle(2, ROOT)).toBe( + path.join(ROOT, 'public', 'sync', 'output', 'synced-output-2.mp4'), + ); + }); +}); + +describe('camera', () => { + it('cameraProfilesDir', () => { + expect(cameraProfilesDir(ROOT)).toBe(path.join(ROOT, 'public', 'camera')); + }); + + it('cameraProfiles', () => { + expect(cameraProfiles(ROOT)).toBe( + path.join(ROOT, 'public', 'camera', 'camera-profiles.json'), + ); + }); +}); + +describe('shorts pipeline', () => { + it('shortsDir', () => { + expect(shortsDir(ROOT)).toBe(path.join(ROOT, 'public', 'shorts')); + }); + + it('shortClipDir', () => { + expect(shortClipDir('clip-01', ROOT)).toBe( + path.join(ROOT, 'public', 'shorts', 'clip-01'), + ); + }); + + it('shortTranscript', () => { + expect(shortTranscript('clip-01', ROOT)).toBe( + path.join(ROOT, 'public', 'shorts', 'clip-01', 'transcript.json'), + ); + }); + + it('shortDoc', () => { + expect(shortDoc('clip-01', ROOT)).toBe( + path.join(ROOT, 'public', 'shorts', 'clip-01', 'transcript.doc.txt'), + ); + }); + + it('shortsCameraProfiles', () => { + expect(shortsCameraProfiles(ROOT)).toBe( + path.join(ROOT, 'public', 'shorts', 'camera-profiles.json'), + ); + }); + + it('shortsTranscribeRawDir', () => { + expect(shortsTranscribeRawDir(ROOT)).toBe( + path.join(ROOT, 'public', 'shorts', 'transcribe', 'output', 'raw'), + ); + }); + + it('shortsTranscriptRaw', () => { + expect(shortsTranscriptRaw(ROOT)).toBe( + path.join(ROOT, 'public', 'shorts', 'transcribe', 'output', 'raw', 'transcript.raw.json'), + ); + }); +}); + +describe('carousel pipeline', () => { + it('carouselDir', () => { + expect(carouselDir(ROOT)).toBe(path.join(ROOT, 'public', 'carousel')); + }); + + it('carouselClipDir', () => { + expect(carouselClipDir('ep-42', ROOT)).toBe( + path.join(ROOT, 'public', 'carousel', 'ep-42'), + ); + }); + + it('carouselTranscript', () => { + expect(carouselTranscript('ep-42', ROOT)).toBe( + path.join(ROOT, 'public', 'carousel', 'ep-42', 'transcript.json'), + ); + }); + + it('carouselDoc', () => { + expect(carouselDoc('ep-42', ROOT)).toBe( + path.join(ROOT, 'public', 'carousel', 'ep-42', 'transcript.doc.txt'), + ); + }); +}); + +describe('thumbnail pipeline', () => { + it('thumbnailDir', () => { + expect(thumbnailDir(ROOT)).toBe(path.join(ROOT, 'public', 'thumbnail')); + }); + + it('thumbnailCameraProfiles', () => { + expect(thumbnailCameraProfiles(ROOT)).toBe( + path.join(ROOT, 'public', 'thumbnail', 'camera-profiles.json'), + ); + }); +}); + +describe('cwd defaults', () => { + it('helpers use process.cwd() when cwd is omitted', () => { + // Just verify the call doesn't throw and returns an absolute path + const result = transcriptOutput(); + expect(path.isAbsolute(result)).toBe(true); + expect(result).toContain(path.join('public', 'edit', 'transcript.json')); + }); +}); diff --git a/scripts/config/paths.ts b/scripts/config/paths.ts new file mode 100644 index 0000000..5e0c570 --- /dev/null +++ b/scripts/config/paths.ts @@ -0,0 +1,158 @@ +/** + * Centralized path resolution for all pipeline scripts. + * + * All helpers are pure functions — no filesystem reads, no side effects. + * Pass `cwd` (defaults to `process.cwd()`) to get absolute paths. + */ + +import path from 'path'; + +// --------------------------------------------------------------------------- +// Project / artifact store +// --------------------------------------------------------------------------- + +export function projectFile(cwd: string = process.cwd()): string { + return path.join(cwd, '.ragtech', 'project.json'); +} + +export function artifactDir(cwd: string = process.cwd()): string { + return path.join(cwd, '.ragtech', 'artifacts'); +} + +// --------------------------------------------------------------------------- +// Transcribe pipeline +// --------------------------------------------------------------------------- + +export function transcribeInput(cwd: string = process.cwd()): string { + return path.join(cwd, 'public', 'transcribe', 'input'); +} + +export function transcribeRawDir(cwd: string = process.cwd()): string { + return path.join(cwd, 'public', 'transcribe', 'output', 'raw'); +} + +export function transcriptRaw(cwd: string = process.cwd()): string { + return path.join(transcribeRawDir(cwd), 'transcript.raw.json'); +} + +export function diarizationOutput(cwd: string = process.cwd()): string { + return path.join(transcribeRawDir(cwd), 'diarization.json'); +} + +export function hookQaDir(cwd: string = process.cwd()): string { + return path.join(cwd, 'public', 'transcribe', 'output', 'hook-qa'); +} + +// --------------------------------------------------------------------------- +// Edit / longform output +// --------------------------------------------------------------------------- + +export function transcriptOutput(cwd: string = process.cwd()): string { + return path.join(cwd, 'public', 'edit', 'transcript.json'); +} + +export function transcriptDoc(cwd: string = process.cwd()): string { + return path.join(cwd, 'public', 'edit', 'transcript.doc.txt'); +} + +// --------------------------------------------------------------------------- +// Sync pipeline +// --------------------------------------------------------------------------- + +export function syncVideoDir(cwd: string = process.cwd()): string { + return path.join(cwd, 'public', 'sync', 'video'); +} + +export function syncAudioDir(cwd: string = process.cwd()): string { + return path.join(cwd, 'public', 'sync', 'audio'); +} + +export function syncOutputDir(cwd: string = process.cwd()): string { + return path.join(cwd, 'public', 'sync', 'output'); +} + +/** Single-angle synced video. */ +export function syncedVideo(cwd: string = process.cwd()): string { + return path.join(syncOutputDir(cwd), 'synced-output.mp4'); +} + +/** Multi-angle synced video (1-based index). */ +export function syncedVideoAngle(index: number, cwd: string = process.cwd()): string { + return path.join(syncOutputDir(cwd), `synced-output-${index}.mp4`); +} + +// --------------------------------------------------------------------------- +// Camera +// --------------------------------------------------------------------------- + +export function cameraProfilesDir(cwd: string = process.cwd()): string { + return path.join(cwd, 'public', 'camera'); +} + +export function cameraProfiles(cwd: string = process.cwd()): string { + return path.join(cameraProfilesDir(cwd), 'camera-profiles.json'); +} + +// --------------------------------------------------------------------------- +// Shorts pipeline +// --------------------------------------------------------------------------- + +export function shortsDir(cwd: string = process.cwd()): string { + return path.join(cwd, 'public', 'shorts'); +} + +export function shortClipDir(clipId: string, cwd: string = process.cwd()): string { + return path.join(shortsDir(cwd), clipId); +} + +export function shortTranscript(clipId: string, cwd: string = process.cwd()): string { + return path.join(shortClipDir(clipId, cwd), 'transcript.json'); +} + +export function shortDoc(clipId: string, cwd: string = process.cwd()): string { + return path.join(shortClipDir(clipId, cwd), 'transcript.doc.txt'); +} + +export function shortsCameraProfiles(cwd: string = process.cwd()): string { + return path.join(shortsDir(cwd), 'camera-profiles.json'); +} + +export function shortsTranscribeRawDir(cwd: string = process.cwd()): string { + return path.join(shortsDir(cwd), 'transcribe', 'output', 'raw'); +} + +export function shortsTranscriptRaw(cwd: string = process.cwd()): string { + return path.join(shortsTranscribeRawDir(cwd), 'transcript.raw.json'); +} + +// --------------------------------------------------------------------------- +// Carousel pipeline +// --------------------------------------------------------------------------- + +export function carouselDir(cwd: string = process.cwd()): string { + return path.join(cwd, 'public', 'carousel'); +} + +export function carouselClipDir(carouselId: string, cwd: string = process.cwd()): string { + return path.join(carouselDir(cwd), carouselId); +} + +export function carouselTranscript(carouselId: string, cwd: string = process.cwd()): string { + return path.join(carouselClipDir(carouselId, cwd), 'transcript.json'); +} + +export function carouselDoc(carouselId: string, cwd: string = process.cwd()): string { + return path.join(carouselClipDir(carouselId, cwd), 'transcript.doc.txt'); +} + +// --------------------------------------------------------------------------- +// Thumbnail pipeline +// --------------------------------------------------------------------------- + +export function thumbnailDir(cwd: string = process.cwd()): string { + return path.join(cwd, 'public', 'thumbnail'); +} + +export function thumbnailCameraProfiles(cwd: string = process.cwd()): string { + return path.join(thumbnailDir(cwd), 'camera-profiles.json'); +} From c29e099e8d55cc0788d2a7b1b69b4adff08ae311 Mon Sep 17 00:00:00 2001 From: Saloni Date: Tue, 26 May 2026 00:12:45 +0800 Subject: [PATCH 2/3] optimize code --- scripts/config/paths.test.ts | 133 ++++++++++++----------------------- scripts/config/paths.ts | 60 ++++++++++------ 2 files changed, 85 insertions(+), 108 deletions(-) diff --git a/scripts/config/paths.test.ts b/scripts/config/paths.test.ts index 9bb2166..d0f32c2 100644 --- a/scripts/config/paths.test.ts +++ b/scripts/config/paths.test.ts @@ -1,9 +1,7 @@ -import path from 'path'; import { projectFile, artifactDir, transcribeInput, - transcribeRawDir, transcriptRaw, diarizationOutput, hookQaDir, @@ -14,20 +12,16 @@ import { syncOutputDir, syncedVideo, syncedVideoAngle, - cameraProfilesDir, cameraProfiles, shortsDir, shortClipDir, shortTranscript, shortDoc, shortsCameraProfiles, - shortsTranscribeRawDir, shortsTranscriptRaw, - carouselDir, carouselClipDir, carouselTranscript, carouselDoc, - thumbnailDir, thumbnailCameraProfiles, } from './paths'; @@ -35,179 +29,144 @@ const ROOT = '/project/root'; describe('project / artifact', () => { it('projectFile', () => { - expect(projectFile(ROOT)).toBe(path.join(ROOT, '.ragtech', 'project.json')); + expect(projectFile(ROOT)).toBe('/project/root/.ragtech/project.json'); }); it('artifactDir', () => { - expect(artifactDir(ROOT)).toBe(path.join(ROOT, '.ragtech', 'artifacts')); + expect(artifactDir(ROOT)).toBe('/project/root/.ragtech/artifacts'); }); }); describe('transcribe pipeline', () => { it('transcribeInput', () => { - expect(transcribeInput(ROOT)).toBe(path.join(ROOT, 'public', 'transcribe', 'input')); - }); - - it('transcribeRawDir', () => { - expect(transcribeRawDir(ROOT)).toBe(path.join(ROOT, 'public', 'transcribe', 'output', 'raw')); + expect(transcribeInput(ROOT)).toBe('/project/root/public/transcribe/input'); }); it('transcriptRaw', () => { - expect(transcriptRaw(ROOT)).toBe( - path.join(ROOT, 'public', 'transcribe', 'output', 'raw', 'transcript.raw.json'), - ); + expect(transcriptRaw(ROOT)).toBe('/project/root/public/transcribe/output/raw/transcript.raw.json'); }); it('diarizationOutput', () => { - expect(diarizationOutput(ROOT)).toBe( - path.join(ROOT, 'public', 'transcribe', 'output', 'raw', 'diarization.json'), - ); + expect(diarizationOutput(ROOT)).toBe('/project/root/public/transcribe/output/raw/diarization.json'); }); it('hookQaDir', () => { - expect(hookQaDir(ROOT)).toBe( - path.join(ROOT, 'public', 'transcribe', 'output', 'hook-qa'), - ); + expect(hookQaDir(ROOT)).toBe('/project/root/public/transcribe/output/hook-qa'); }); }); describe('edit / longform output', () => { it('transcriptOutput', () => { - expect(transcriptOutput(ROOT)).toBe(path.join(ROOT, 'public', 'edit', 'transcript.json')); + expect(transcriptOutput(ROOT)).toBe('/project/root/public/edit/transcript.json'); }); it('transcriptDoc', () => { - expect(transcriptDoc(ROOT)).toBe(path.join(ROOT, 'public', 'edit', 'transcript.doc.txt')); + expect(transcriptDoc(ROOT)).toBe('/project/root/public/edit/transcript.doc.txt'); }); }); describe('sync pipeline', () => { it('syncVideoDir', () => { - expect(syncVideoDir(ROOT)).toBe(path.join(ROOT, 'public', 'sync', 'video')); + expect(syncVideoDir(ROOT)).toBe('/project/root/public/sync/video'); }); it('syncAudioDir', () => { - expect(syncAudioDir(ROOT)).toBe(path.join(ROOT, 'public', 'sync', 'audio')); + expect(syncAudioDir(ROOT)).toBe('/project/root/public/sync/audio'); }); it('syncOutputDir', () => { - expect(syncOutputDir(ROOT)).toBe(path.join(ROOT, 'public', 'sync', 'output')); + expect(syncOutputDir(ROOT)).toBe('/project/root/public/sync/output'); }); it('syncedVideo', () => { - expect(syncedVideo(ROOT)).toBe( - path.join(ROOT, 'public', 'sync', 'output', 'synced-output.mp4'), - ); + expect(syncedVideo(ROOT)).toBe('/project/root/public/sync/output/synced-output.mp4'); }); it('syncedVideoAngle — index 1', () => { - expect(syncedVideoAngle(1, ROOT)).toBe( - path.join(ROOT, 'public', 'sync', 'output', 'synced-output-1.mp4'), - ); + expect(syncedVideoAngle(1, ROOT)).toBe('/project/root/public/sync/output/synced-output-1.mp4'); }); it('syncedVideoAngle — index 2', () => { - expect(syncedVideoAngle(2, ROOT)).toBe( - path.join(ROOT, 'public', 'sync', 'output', 'synced-output-2.mp4'), - ); + expect(syncedVideoAngle(2, ROOT)).toBe('/project/root/public/sync/output/synced-output-2.mp4'); }); -}); -describe('camera', () => { - it('cameraProfilesDir', () => { - expect(cameraProfilesDir(ROOT)).toBe(path.join(ROOT, 'public', 'camera')); + it('syncedVideoAngle — index 0 throws', () => { + expect(() => syncedVideoAngle(0, ROOT)).toThrow(RangeError); }); + it('syncedVideoAngle — negative index throws', () => { + expect(() => syncedVideoAngle(-1, ROOT)).toThrow(RangeError); + }); +}); + +describe('camera', () => { it('cameraProfiles', () => { - expect(cameraProfiles(ROOT)).toBe( - path.join(ROOT, 'public', 'camera', 'camera-profiles.json'), - ); + expect(cameraProfiles(ROOT)).toBe('/project/root/public/camera/camera-profiles.json'); }); }); describe('shorts pipeline', () => { it('shortsDir', () => { - expect(shortsDir(ROOT)).toBe(path.join(ROOT, 'public', 'shorts')); + expect(shortsDir(ROOT)).toBe('/project/root/public/shorts'); }); it('shortClipDir', () => { - expect(shortClipDir('clip-01', ROOT)).toBe( - path.join(ROOT, 'public', 'shorts', 'clip-01'), - ); + expect(shortClipDir('clip-01', ROOT)).toBe('/project/root/public/shorts/clip-01'); }); it('shortTranscript', () => { - expect(shortTranscript('clip-01', ROOT)).toBe( - path.join(ROOT, 'public', 'shorts', 'clip-01', 'transcript.json'), - ); + expect(shortTranscript('clip-01', ROOT)).toBe('/project/root/public/shorts/clip-01/transcript.json'); }); it('shortDoc', () => { - expect(shortDoc('clip-01', ROOT)).toBe( - path.join(ROOT, 'public', 'shorts', 'clip-01', 'transcript.doc.txt'), - ); + expect(shortDoc('clip-01', ROOT)).toBe('/project/root/public/shorts/clip-01/transcript.doc.txt'); }); it('shortsCameraProfiles', () => { - expect(shortsCameraProfiles(ROOT)).toBe( - path.join(ROOT, 'public', 'shorts', 'camera-profiles.json'), - ); - }); - - it('shortsTranscribeRawDir', () => { - expect(shortsTranscribeRawDir(ROOT)).toBe( - path.join(ROOT, 'public', 'shorts', 'transcribe', 'output', 'raw'), - ); + expect(shortsCameraProfiles(ROOT)).toBe('/project/root/public/shorts/camera-profiles.json'); }); it('shortsTranscriptRaw', () => { expect(shortsTranscriptRaw(ROOT)).toBe( - path.join(ROOT, 'public', 'shorts', 'transcribe', 'output', 'raw', 'transcript.raw.json'), + '/project/root/public/shorts/transcribe/output/raw/transcript.raw.json', ); }); }); describe('carousel pipeline', () => { - it('carouselDir', () => { - expect(carouselDir(ROOT)).toBe(path.join(ROOT, 'public', 'carousel')); - }); - it('carouselClipDir', () => { - expect(carouselClipDir('ep-42', ROOT)).toBe( - path.join(ROOT, 'public', 'carousel', 'ep-42'), - ); + expect(carouselClipDir('ep-42', ROOT)).toBe('/project/root/public/carousel/ep-42'); }); it('carouselTranscript', () => { - expect(carouselTranscript('ep-42', ROOT)).toBe( - path.join(ROOT, 'public', 'carousel', 'ep-42', 'transcript.json'), - ); + expect(carouselTranscript('ep-42', ROOT)).toBe('/project/root/public/carousel/ep-42/transcript.json'); }); it('carouselDoc', () => { - expect(carouselDoc('ep-42', ROOT)).toBe( - path.join(ROOT, 'public', 'carousel', 'ep-42', 'transcript.doc.txt'), - ); + expect(carouselDoc('ep-42', ROOT)).toBe('/project/root/public/carousel/ep-42/transcript.doc.txt'); }); }); describe('thumbnail pipeline', () => { - it('thumbnailDir', () => { - expect(thumbnailDir(ROOT)).toBe(path.join(ROOT, 'public', 'thumbnail')); - }); - it('thumbnailCameraProfiles', () => { - expect(thumbnailCameraProfiles(ROOT)).toBe( - path.join(ROOT, 'public', 'thumbnail', 'camera-profiles.json'), - ); + expect(thumbnailCameraProfiles(ROOT)).toBe('/project/root/public/thumbnail/camera-profiles.json'); }); }); describe('cwd defaults', () => { - it('helpers use process.cwd() when cwd is omitted', () => { - // Just verify the call doesn't throw and returns an absolute path + it('uses process.cwd() as root when cwd is omitted', () => { const result = transcriptOutput(); - expect(path.isAbsolute(result)).toBe(true); - expect(result).toContain(path.join('public', 'edit', 'transcript.json')); + expect(result.startsWith(process.cwd())).toBe(true); + expect(result.endsWith('/public/edit/transcript.json')).toBe(true); + }); +}); + +describe('id guards', () => { + it('shortClipDir — empty string throws', () => { + expect(() => shortClipDir('', ROOT)).toThrow(TypeError); + }); + + it('carouselClipDir — empty string throws', () => { + expect(() => carouselClipDir('', ROOT)).toThrow(TypeError); }); }); diff --git a/scripts/config/paths.ts b/scripts/config/paths.ts index 5e0c570..4a1c7f4 100644 --- a/scripts/config/paths.ts +++ b/scripts/config/paths.ts @@ -3,31 +3,37 @@ * * All helpers are pure functions — no filesystem reads, no side effects. * Pass `cwd` (defaults to `process.cwd()`) to get absolute paths. + * + * Internal dir helpers (not exported) are kept private to allow restructuring + * without breaking callers. Export only the paths scripts actually reference. */ import path from 'path'; +import { PROJECT_DIR, PROJECT_FILENAME } from './project'; +import { ARTIFACTS_DIR } from './artifacts'; // --------------------------------------------------------------------------- // Project / artifact store // --------------------------------------------------------------------------- export function projectFile(cwd: string = process.cwd()): string { - return path.join(cwd, '.ragtech', 'project.json'); + return path.join(cwd, PROJECT_DIR, PROJECT_FILENAME); } export function artifactDir(cwd: string = process.cwd()): string { - return path.join(cwd, '.ragtech', 'artifacts'); + return path.join(cwd, ARTIFACTS_DIR); } // --------------------------------------------------------------------------- // Transcribe pipeline // --------------------------------------------------------------------------- +/** Directory where raw audio/video input files are placed before transcription. */ export function transcribeInput(cwd: string = process.cwd()): string { return path.join(cwd, 'public', 'transcribe', 'input'); } -export function transcribeRawDir(cwd: string = process.cwd()): string { +function transcribeRawDir(cwd: string): string { return path.join(cwd, 'public', 'transcribe', 'output', 'raw'); } @@ -67,17 +73,26 @@ export function syncAudioDir(cwd: string = process.cwd()): string { return path.join(cwd, 'public', 'sync', 'audio'); } +/** Directory containing synced output videos. Use for readdir; prefer {@link syncedVideo} or {@link syncedVideoAngle} for specific files. */ export function syncOutputDir(cwd: string = process.cwd()): string { return path.join(cwd, 'public', 'sync', 'output'); } -/** Single-angle synced video. */ +/** + * Single-angle synced video (`synced-output.mp4`). + * For multi-angle recordings use {@link syncedVideoAngle} instead. + */ export function syncedVideo(cwd: string = process.cwd()): string { return path.join(syncOutputDir(cwd), 'synced-output.mp4'); } -/** Multi-angle synced video (1-based index). */ +/** + * Multi-angle synced video — produces `synced-output-{index}.mp4`. + * Index is 1-based. Throws if index < 1. + * For single-angle recordings use {@link syncedVideo} instead. + */ export function syncedVideoAngle(index: number, cwd: string = process.cwd()): string { + if (index < 1) throw new RangeError(`syncedVideoAngle: index must be ≥ 1, got ${index}`); return path.join(syncOutputDir(cwd), `synced-output-${index}.mp4`); } @@ -85,7 +100,7 @@ export function syncedVideoAngle(index: number, cwd: string = process.cwd()): st // Camera // --------------------------------------------------------------------------- -export function cameraProfilesDir(cwd: string = process.cwd()): string { +function cameraProfilesDir(cwd: string): string { return path.join(cwd, 'public', 'camera'); } @@ -97,27 +112,29 @@ export function cameraProfiles(cwd: string = process.cwd()): string { // Shorts pipeline // --------------------------------------------------------------------------- +/** Root shorts directory. Use for existence checks and readdir. */ export function shortsDir(cwd: string = process.cwd()): string { return path.join(cwd, 'public', 'shorts'); } -export function shortClipDir(clipId: string, cwd: string = process.cwd()): string { - return path.join(shortsDir(cwd), clipId); +export function shortClipDir(id: string, cwd: string = process.cwd()): string { + if (!id) throw new TypeError('shortClipDir: id must not be empty'); + return path.join(shortsDir(cwd), id); } -export function shortTranscript(clipId: string, cwd: string = process.cwd()): string { - return path.join(shortClipDir(clipId, cwd), 'transcript.json'); +export function shortTranscript(id: string, cwd: string = process.cwd()): string { + return path.join(shortClipDir(id, cwd), 'transcript.json'); } -export function shortDoc(clipId: string, cwd: string = process.cwd()): string { - return path.join(shortClipDir(clipId, cwd), 'transcript.doc.txt'); +export function shortDoc(id: string, cwd: string = process.cwd()): string { + return path.join(shortClipDir(id, cwd), 'transcript.doc.txt'); } export function shortsCameraProfiles(cwd: string = process.cwd()): string { return path.join(shortsDir(cwd), 'camera-profiles.json'); } -export function shortsTranscribeRawDir(cwd: string = process.cwd()): string { +function shortsTranscribeRawDir(cwd: string): string { return path.join(shortsDir(cwd), 'transcribe', 'output', 'raw'); } @@ -129,27 +146,28 @@ export function shortsTranscriptRaw(cwd: string = process.cwd()): string { // Carousel pipeline // --------------------------------------------------------------------------- -export function carouselDir(cwd: string = process.cwd()): string { +function carouselDir(cwd: string): string { return path.join(cwd, 'public', 'carousel'); } -export function carouselClipDir(carouselId: string, cwd: string = process.cwd()): string { - return path.join(carouselDir(cwd), carouselId); +export function carouselClipDir(id: string, cwd: string = process.cwd()): string { + if (!id) throw new TypeError('carouselClipDir: id must not be empty'); + return path.join(carouselDir(cwd), id); } -export function carouselTranscript(carouselId: string, cwd: string = process.cwd()): string { - return path.join(carouselClipDir(carouselId, cwd), 'transcript.json'); +export function carouselTranscript(id: string, cwd: string = process.cwd()): string { + return path.join(carouselClipDir(id, cwd), 'transcript.json'); } -export function carouselDoc(carouselId: string, cwd: string = process.cwd()): string { - return path.join(carouselClipDir(carouselId, cwd), 'transcript.doc.txt'); +export function carouselDoc(id: string, cwd: string = process.cwd()): string { + return path.join(carouselClipDir(id, cwd), 'transcript.doc.txt'); } // --------------------------------------------------------------------------- // Thumbnail pipeline // --------------------------------------------------------------------------- -export function thumbnailDir(cwd: string = process.cwd()): string { +function thumbnailDir(cwd: string): string { return path.join(cwd, 'public', 'thumbnail'); } From a0a75e2f043705c568cacab7dfcc698f8f1336cf Mon Sep 17 00:00:00 2001 From: Saloni Date: Tue, 26 May 2026 00:37:50 +0800 Subject: [PATCH 3/3] Fix dependency versions --- package-lock.json | 72 +++++++++++------------------------------------ package.json | 4 ++- 2 files changed, 20 insertions(+), 56 deletions(-) diff --git a/package-lock.json b/package-lock.json index 33e3440..ae2d6d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4655,27 +4655,6 @@ "node": ">= 8" } }, - "node_modules/@remotion/renderer/node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/@remotion/sfx": { "version": "4.0.451", "resolved": "https://registry.npmjs.org/@remotion/sfx/-/sfx-4.0.451.tgz", @@ -6060,27 +6039,6 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { - "version": "4.0.4", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "version": "10.2.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", @@ -6869,9 +6827,14 @@ } }, "node_modules/balanced-match": { - "version": "1.0.2", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } }, "node_modules/bare-events": { "version": "2.8.2", @@ -7021,14 +6984,16 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", - "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, "node_modules/braces": { @@ -7461,11 +7426,6 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "license": "MIT" }, - "node_modules/concat-map": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, "node_modules/convert-source-map": { "version": "2.0.0", "dev": true, @@ -16237,7 +16197,9 @@ } }, "node_modules/ws": { - "version": "8.19.0", + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", "license": "MIT", "engines": { "node": ">=10.0.0" diff --git a/package.json b/package.json index a4ed3ae..578293b 100644 --- a/package.json +++ b/package.json @@ -113,7 +113,9 @@ "lightningcss-linux-x64-gnu": "1.30.2" }, "overrides": { - "postcss": "^8.5.10" + "postcss": "^8.5.10", + "ws": ">=8.21.0", + "brace-expansion": ">=5.0.6" }, "lint-staged": { "*.{ts,tsx}": "eslint --max-warnings=0",