YT Fixes
This commit is contained in:
@@ -21,8 +21,9 @@ const YOUTUBE_URL_PATTERNS = [
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* YouTube embed URL base - fallback when yt-dlp is not available
|
* YouTube embed URL base - fallback when yt-dlp is not available
|
||||||
|
* Using youtube-nocookie.com to avoid Error 153 and embedding restrictions
|
||||||
*/
|
*/
|
||||||
const YOUTUBE_EMBED_BASE = 'https://www.youtube.com/embed';
|
const YOUTUBE_EMBED_BASE = 'https://www.youtube-nocookie.com/embed';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* YouTube oEmbed API base - used to fetch video metadata
|
* YouTube oEmbed API base - used to fetch video metadata
|
||||||
@@ -88,10 +89,15 @@ export function extractYouTubeVideoId(url: string): string | null {
|
|||||||
/**
|
/**
|
||||||
* Generates a YouTube embed URL for a video (fallback)
|
* Generates a YouTube embed URL for a video (fallback)
|
||||||
* @param videoId The YouTube video ID
|
* @param videoId The YouTube video ID
|
||||||
* @returns The embed URL
|
* @returns The embed URL with parameters to avoid Error 153
|
||||||
*/
|
*/
|
||||||
export function getYouTubeEmbedUrl(videoId: string): string {
|
export function getYouTubeEmbedUrl(videoId: string): string {
|
||||||
return `${YOUTUBE_EMBED_BASE}/${videoId}?autoplay=1`;
|
// Use youtube-nocookie.com and add parameters to help with embedding
|
||||||
|
// autoplay=1 - start playing when loaded
|
||||||
|
// rel=0 - only show related videos from same channel
|
||||||
|
// modestbranding=1 - minimize YouTube branding
|
||||||
|
// enablejsapi=1 - enable JavaScript API for better compatibility
|
||||||
|
return `${YOUTUBE_EMBED_BASE}/${videoId}?autoplay=1&rel=0&modestbranding=1&enablejsapi=1`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -255,8 +261,9 @@ export const YouTubeEmbed = as<'div', YouTubeEmbedProps>(({ url, ...props }, ref
|
|||||||
className={css.YouTubeEmbedIframe}
|
className={css.YouTubeEmbedIframe}
|
||||||
src={embedUrl}
|
src={embedUrl}
|
||||||
title="YouTube video player"
|
title="YouTube video player"
|
||||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||||
allowFullScreen
|
allowFullScreen
|
||||||
|
referrerPolicy="strict-origin-when-cross-origin"
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -66,11 +66,28 @@ export interface YouTubeStreamInfo {
|
|||||||
* @throws If yt-dlp is not installed or fails
|
* @throws If yt-dlp is not installed or fails
|
||||||
*/
|
*/
|
||||||
export const getYouTubeStream = async (url: string): Promise<YouTubeStreamInfo> => {
|
export const getYouTubeStream = async (url: string): Promise<YouTubeStreamInfo> => {
|
||||||
if (typeof window !== 'undefined' && (window as any).__TAURI__) {
|
if (typeof window === 'undefined') {
|
||||||
|
throw new Error('YouTube streaming requires desktop app with yt-dlp installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for Electron
|
||||||
|
const electron = (window as any).electron;
|
||||||
|
if (electron?.youtube?.getStream) {
|
||||||
|
const result = await electron.youtube.getStream(url);
|
||||||
|
// Electron returns { success: true, data: { video_url, title } } or { success: false, error }
|
||||||
|
if (result.success === false) {
|
||||||
|
throw new Error(result.error || 'Failed to get YouTube stream');
|
||||||
|
}
|
||||||
|
return result.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for Tauri
|
||||||
|
if ((window as any).__TAURI__) {
|
||||||
const { invoke } = await import('@tauri-apps/api/core');
|
const { invoke } = await import('@tauri-apps/api/core');
|
||||||
return invoke<YouTubeStreamInfo>('get_youtube_stream', { url });
|
return invoke<YouTubeStreamInfo>('get_youtube_stream', { url });
|
||||||
}
|
}
|
||||||
throw new Error('YouTube streaming requires Tauri desktop app with yt-dlp installed');
|
|
||||||
|
throw new Error('YouTube streaming requires desktop app with yt-dlp installed');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,7 +95,18 @@ export const getYouTubeStream = async (url: string): Promise<YouTubeStreamInfo>
|
|||||||
* @returns True if yt-dlp streaming is available
|
* @returns True if yt-dlp streaming is available
|
||||||
*/
|
*/
|
||||||
export const isYouTubeStreamingAvailable = (): boolean => {
|
export const isYouTubeStreamingAvailable = (): boolean => {
|
||||||
return typeof window !== 'undefined' && !!(window as any).__TAURI__;
|
if (typeof window === 'undefined') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for Electron
|
||||||
|
const electron = (window as any).electron;
|
||||||
|
if (electron?.youtube?.getStream) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for Tauri
|
||||||
|
return !!(window as any).__TAURI__;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user