extract_transcript
Extracts text transcripts from YouTube videos to create LinkedIn post drafts, converting video content into editable written material.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| youtubeUrl | Yes | YouTube video URL |
Implementation Reference
- Core handler function implementing the transcript extraction logic from YouTube videos using the 'youtube-transcript' library with API fallback.export async function extractTranscript(youtubeUrl, youtubeApiKey = null) { try { console.log(`Extracting transcript from: ${youtubeUrl}`); // Extract video ID from URL const videoId = extractVideoId(youtubeUrl); if (!videoId) { throw new Error("Invalid YouTube URL. Could not extract video ID."); } // Try to get transcript using youtube-transcript package try { const transcriptItems = await YoutubeTranscript.fetchTranscript(videoId); if (!transcriptItems || transcriptItems.length === 0) { throw new Error("No transcript available"); } // Combine transcript segments into a single text const fullTranscript = transcriptItems .map(item => item.text) .join(' ') .replace(/\s+/g, ' '); // Clean up extra spaces return fullTranscript; } catch (error) { console.error("Error with primary transcript method:", error); // Fallback to YouTube API if available if (youtubeApiKey) { return await fetchTranscriptWithYouTubeAPI(videoId, youtubeApiKey); } else { throw new Error("Failed to extract transcript: " + error.message); } } } catch (error) { console.error("Transcript extraction error:", error); throw new Error(`Failed to extract transcript: ${error.message}`); } }
- src/server.js:74-110 (registration)MCP server tool registration for 'extract_transcript', including input schema, execution handler wrapper, and description.server.tool( "extract_transcript", { youtubeUrl: z.string().url().describe("YouTube video URL") }, async ({ youtubeUrl }) => { try { // Check if YouTube API key is set (if needed) if (!apiKeyManager.hasYouTubeKey()) { console.log("No YouTube API key set, will try without it"); } const transcript = await extractTranscript(youtubeUrl, apiKeyManager.getYouTubeKey()); return { content: [{ type: "text", text: JSON.stringify({ success: true, transcript }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: JSON.stringify({ success: false, error: error.message }, null, 2) }], isError: true }; } }, { description: "Extract transcript from a YouTube video" } );
- src/server.js:76-78 (schema)Zod schema defining the input parameter 'youtubeUrl' as a required URL string.{ youtubeUrl: z.string().url().describe("YouTube video URL") },
- Helper function to parse YouTube video ID from various URL formats.*/ function extractVideoId(url) { try { const urlObj = new URL(url); // Standard YouTube URL (youtube.com/watch?v=VIDEO_ID) if (urlObj.hostname.includes('youtube.com')) { return urlObj.searchParams.get('v'); } // Short YouTube URL (youtu.be/VIDEO_ID) if (urlObj.hostname === 'youtu.be') { return urlObj.pathname.substring(1); } return null; } catch (error) { console.error("Error extracting video ID:", error); return null; } }
- Fallback helper for fetching transcript via YouTube Data API v3 (incomplete, notes OAuth2 needed).*/ async function fetchTranscriptWithYouTubeAPI(videoId, apiKey) { if (!apiKey) { throw new Error("YouTube API key not provided"); } // First, get the caption track const captionUrl = `https://www.googleapis.com/youtube/v3/captions?part=snippet&videoId=${videoId}&key=${apiKey}`; const response = await fetch(captionUrl); if (!response.ok) { throw new Error(`YouTube API error: ${response.statusText}`); } const data = await response.json(); if (!data.items || data.items.length === 0) { throw new Error("No captions available for this video"); } // Note: Actually downloading the caption track requires OAuth2 authentication // which is beyond the scope of this example throw new Error("YouTube API fallback requires OAuth2 authentication"); }