"use client"; import { useState } from "react"; import { StreamActionLog } from "yt-dlp-transcript-common/components/StreamActionLog"; import { formatDuration } from "yt-dlp-transcript-common/lib/format"; import { QueueControl } from "../../../../../../components/QueueControl"; import { cancelJobAction } from "../../../../../../jobs/actions"; import { downloadVideoPipelineAction, } from "../../videoActions"; // The download completed but the audio was far shorter than the video — the // source served a truncated stream (e.g. a CDN-truncated HLS rung). The stub is // kept on disk; re-downloading with a different format (Original) fetches the // full audio. Offers a one-click re-download forcing the Original format. // `flagged` is the parent's condition, passed down rather than branched on for // the same reason as IncompleteTranscriptBanner (IncompleteTranscriptBanner.tsx): the re-download offered // here is what clears the flag, and unmounting this component on the refresh // that lands the new download outcome would take the run's log with it. export function ShortAudioBanner({ slug, videoId, flagged, shortAudio, defaultQueueKey, existingQueues, }: { slug: string; videoId: string; flagged: boolean; shortAudio?: { audioDurationSec: number; expectedDurationSec: number; coverage: number; }; defaultQueueKey: string; existingQueues: string[]; }) { const [queueKey, setQueueKey] = useState(defaultQueueKey); const [ranHere, setRanHere] = useState(false); if (!flagged && !ranHere) return null; const actionLabel = `Re-download ${videoId} as Original`; return (
{flagged ? (
Download was truncated at the source {shortAudio ? `The downloaded audio is only ${formatDuration(shortAudio.audioDurationSec)} of ${formatDuration(shortAudio.expectedDurationSec)} (${Math.round(shortAudio.coverage * 100)}%). ` : "The downloaded audio is far shorter than the video. "} The source served a truncated stream for the selected format, so it was flagged before transcription (the file is kept, not transcribed). Re-download with the Original format to fetch the full audio.
) : null} { setRanHere(true); return downloadVideoPipelineAction(slug, videoId, queueKey, "original"); }} cancelAction={cancelJobAction} buttonLabel="Re-download as Original" runningLabel="Re-downloading…" label={actionLabel} extraControls={ } />
); }