D5: explicit VTT fallback branch when tryGetCaptions returns null for empty/unusable segments

- tryGetCaptions now returns null when transcriptEntriesToSegments produces
  empty array (all entries whitespace/filtered out), not a CaptionResult
  with zero segments
- downloadYouTube simplifies null check — null from tryGetCaptions always
  means 'no usable captions', triggers explicit VTT fallback to downloadAudio
- Add JSDoc explaining VTT fallback contract
This commit is contained in:
Giancarmine Salucci
2026-07-09 06:47:05 +02:00
parent 70253b64cd
commit f96d67b8d8
+10 -3
View File
@@ -48,11 +48,13 @@ export interface AudioResult {
export type DownloadResult = CaptionResult | AudioResult;
/** Try to get auto-generated captions from YouTube. Returns null if unavailable. */
/** Try to get auto-generated captions from YouTube. Returns null if unavailable
* (fetch error OR parsed segments are empty/unusable). */
async function tryGetCaptions(url: string, _outDir: string): Promise<CaptionResult | null> {
try {
const transcript = await fetchTranscript(url, { lang: 'en' });
const segments = transcriptEntriesToSegments(transcript);
if (segments.length === 0) return null;
const title = await getYouTubeTitle(url);
return { type: 'captions', segments, title };
} catch {
@@ -100,15 +102,20 @@ async function downloadAudio(url: string, outDir: string): Promise<{ audioPath:
return { audioPath: join(outDir, audioFile), title };
}
/** Download a YouTube URL: try captions first, fall back to audio. */
/** Download a YouTube URL: try captions first, fall back to audio.
*
* VTT fallback: when tryGetCaptions returns null (parse failure or
* empty/unusable segments) we fall through to downloadAudio instead
* of returning an empty CaptionResult. */
export async function downloadYouTube(url: string, jobId: string): Promise<DownloadResult> {
await ensureTmpDir();
const outDir = join(TMP_DIR, jobId);
await mkdir(outDir, { recursive: true });
const captions = await tryGetCaptions(url, outDir);
if (captions && captions.segments.length > 0) return captions;
if (captions) return captions;
/* VTT fallback: captions unavailable — download full audio for whisper transcription */
const { audioPath, title } = await downloadAudio(url, outDir);
return { type: 'audio', audioPath, title };
}