UNPKG

unified-video-framework

Version:

Cross-platform video player framework supporting iOS, Android, Web, Smart TVs (Samsung/LG), Roku, and more

90 lines 3.58 kB
export class YouTubeExtractor { static isYouTubeUrl(url) { return this.YOUTUBE_REGEX.test(url); } static extractVideoId(url) { const match = url.match(this.YOUTUBE_REGEX); return match ? match[1] : null; } static async getVideoMetadata(url) { try { const apiUrl = `${this.YOUTUBE_NOEMBED_API}${encodeURIComponent(url)}`; const response = await fetch(apiUrl); if (!response.ok) { throw new Error('Failed to fetch YouTube metadata'); } const data = await response.json(); return { title: data.title || 'YouTube Video', thumbnail: data.thumbnail_url || `https://img.youtube.com/vi/${this.extractVideoId(url)}/maxresdefault.jpg`, duration: data.duration || undefined }; } catch (error) { console.warn('Failed to fetch YouTube metadata:', error); const videoId = this.extractVideoId(url); return { title: 'YouTube Video', thumbnail: `https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`, duration: undefined }; } } static getEmbedUrl(videoId, showControls = false) { const controls = showControls ? 1 : 0; return `https://www.youtube.com/embed/${videoId}?modestbranding=1&rel=0&controls=${controls}`; } static async getDirectStreamUrl(videoId, backendEndpoint) { if (!backendEndpoint) { console.warn('No backend endpoint provided for YouTube video extraction. Using fallback method.'); return this.getFallbackStreamUrl(videoId); } try { const response = await fetch(backendEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ videoId }) }); if (!response.ok) { throw new Error('Backend failed to extract stream'); } const data = await response.json(); return data.streamUrl || null; } catch (error) { console.error('Failed to get direct stream URL:', error); return this.getFallbackStreamUrl(videoId); } } static getFallbackStreamUrl(videoId) { return `https://www.youtube.com/watch?v=${videoId}`; } static async prepareYouTubeSource(url, backendEndpoint) { const videoId = this.extractVideoId(url); if (!videoId) { throw new Error('Invalid YouTube URL'); } const metadata = await this.getVideoMetadata(url); const streamUrl = await this.getDirectStreamUrl(videoId, backendEndpoint); return { url: streamUrl || url, type: 'youtube', title: metadata.title, thumbnail: metadata.thumbnail, duration: metadata.duration, videoId: videoId, isYouTube: true, metadata: { source: 'youtube', videoId: videoId } }; } } YouTubeExtractor.YOUTUBE_REGEX = /(?:https?:\/\/)?(?:www\.)?(?:youtube\.com|youtu\.be)\/(?:watch\?v=|embed\/|v\/|live\/)?([a-zA-Z0-9_-]{11})/; YouTubeExtractor.YOUTUBE_NOEMBED_API = 'https://noembed.com/embed?url='; YouTubeExtractor.YOUTUBE_API_ENDPOINT = 'https://www.youtube.com/oembed?url='; export default YouTubeExtractor; //# sourceMappingURL=YouTubeExtractor.js.map