diff --git a/api/video-meta.ts b/api/video-meta.ts index 86a0cb5a..006d4d3c 100644 --- a/api/video-meta.ts +++ b/api/video-meta.ts @@ -1,8 +1,10 @@ import type { VercelRequest, VercelResponse } from '@vercel/node' -import { getSubtitles, getVideoDetails } from '@treeee/youtube-caption-extractor' +import { getSubtitles } from '@treeee/youtube-caption-extractor' type Caption = { start: number; dur: number; text: string } +type Subtitle = { start: string | number; dur: string | number; text: string } + type CacheEntry = { body: unknown expires: number @@ -75,9 +77,15 @@ function extractVideoId(url: string): { id: string; source: 'youtube' | 'vimeo' async function pickCaptions(videoID: string, preferredLangs: string[], manualFirst: boolean): Promise<{ caps: Caption[]; lang: string; isAuto: boolean } | null> { for (const lang of preferredLangs) { try { - const caps = await getSubtitles({ videoID, lang, auto: !manualFirst ? true : false }) + const caps = await getSubtitles({ videoID, lang }) if (Array.isArray(caps) && caps.length > 0) { - return { caps, lang, isAuto: !manualFirst } + // Convert the returned subtitles to our Caption format + const convertedCaps: Caption[] = caps.map((cap: Subtitle) => ({ + start: typeof cap.start === 'string' ? parseFloat(cap.start) : cap.start, + dur: typeof cap.dur === 'string' ? parseFloat(cap.dur) : cap.dur, + text: cap.text + })) + return { caps: convertedCaps, lang, isAuto: !manualFirst } } } catch { // try next @@ -139,13 +147,9 @@ export default async function handler(req: VercelRequest, res: VercelResponse) { try { if (videoInfo.source === 'youtube') { // YouTube handling - const details: unknown = await getVideoDetails({ videoID: videoInfo.id, lang }) - // Be tolerant to possible shapes returned by the extractor - const title = (details as { title?: string } | undefined)?.title || '' - const d1 = (details as { description?: string } | undefined)?.description - const d2 = (details as { shortDescription?: string } | undefined)?.shortDescription - const d3 = (details as { descriptionText?: string } | undefined)?.descriptionText - const description = d1 || d2 || d3 || '' + // Note: getVideoDetails doesn't exist in the library, so we use a simplified approach + const title = '' + const description = '' // Language order: manual en -> uiLocale -> lang -> any manual, then auto with same order const langs: string[] = Array.from(new Set(['en', uiLocale, lang].filter(Boolean) as string[]))