UNPKG

youtube-data-mcp

Version:

MCP server for YouTube data extraction - transcripts, comments, and search

113 lines 4 kB
import { getSubtitles, getVideoDetails } from "youtube-caption-extractor"; export async function fetchBasicVideoInfo(videoId) { try { const details = await getVideoDetails({ videoID: videoId, lang: "en" }); return { title: details.title, channelName: undefined, publishedAt: undefined, viewCount: undefined, }; } catch { return fetchVideoInfoFromPage(videoId); } } async function fetchVideoInfoFromPage(videoId) { try { const response = await fetch(`https://www.youtube.com/watch?v=${videoId}`, { headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", "Accept-Language": "en-US,en;q=0.9", }, }); if (!response.ok) { return {}; } const html = await response.text(); const titleMatch = html.match(/<meta\s+name="title"\s+content="([^"]+)"/i); const channelMatch = html.match(/<meta\s+name="author"\s+content="([^"]+)"/i); const publishedAtMatch = html.match(/"publishDate":"([^"]+)"/); const viewCountMatch = html.match(/"viewCount":"([^"]+)"/); return { title: titleMatch?.[1], channelName: channelMatch?.[1], publishedAt: publishedAtMatch?.[1], viewCount: viewCountMatch?.[1], }; } catch { return {}; } } function formatSubtitles(subtitles) { return subtitles.map((s) => s.text).join(" "); } export async function getTranscript(videoId, lang = "en") { let subtitles = []; let videoTitle; let videoDescription; try { const details = await getVideoDetails({ videoID: videoId, lang }); subtitles = details.subtitles || []; videoTitle = details.title; videoDescription = details.description; } catch (primaryError) { try { subtitles = await getSubtitles({ videoID: videoId, lang }); } catch (fallbackError) { const errorMessage = primaryError instanceof Error ? primaryError.message : "Unknown error"; throw new Error(`Failed to fetch transcript: ${errorMessage}. Video may not have captions available in '${lang}' language.`); } } if (subtitles.length === 0) { throw new Error(`No transcript available for this video in '${lang}' language. Try a different language code.`); } const videoInfo = await fetchBasicVideoInfo(videoId); return { videoInfo: { id: videoId, title: videoTitle || videoInfo.title, channelName: videoInfo.channelName, publishedAt: videoInfo.publishedAt, viewCount: videoInfo.viewCount, }, fullText: formatSubtitles(subtitles), language: lang, }; } export async function getTranscriptWithTimestamps(videoId, lang = "en") { let subtitles = []; let videoTitle; try { const details = await getVideoDetails({ videoID: videoId, lang }); subtitles = details.subtitles || []; videoTitle = details.title; } catch { subtitles = await getSubtitles({ videoID: videoId, lang }); } if (subtitles.length === 0) { throw new Error(`No transcript available for this video in '${lang}' language.`); } const videoInfo = await fetchBasicVideoInfo(videoId); return { videoInfo: { id: videoId, title: videoTitle || videoInfo.title, channelName: videoInfo.channelName, publishedAt: videoInfo.publishedAt, viewCount: videoInfo.viewCount, }, fullText: formatSubtitles(subtitles), language: lang, segments: subtitles.map((s) => ({ start: s.start, duration: s.dur, text: s.text, })), }; } //# sourceMappingURL=youtube.js.map