mirror of
https://github.com/JustAnimeCore/JustAnime.git
synced 2026-04-17 22:01:45 +00:00
url passing correctly
This commit is contained in:
@@ -178,8 +178,28 @@ export default function WatchPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set subtitles if available in the sources response
|
// Set subtitles if available in the sources response
|
||||||
if (data.subtitles && data.subtitles.length > 0) {
|
// Check both subtitles and tracks fields since API might return either
|
||||||
setSubtitles(data.subtitles);
|
const subtitleData = data.subtitles || data.tracks || [];
|
||||||
|
if (subtitleData.length > 0) {
|
||||||
|
// Filter out thumbnails from subtitles array
|
||||||
|
const filteredSubtitles = subtitleData.filter(sub =>
|
||||||
|
sub.lang && sub.lang.toLowerCase() !== 'thumbnails'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Look for thumbnails separately
|
||||||
|
const thumbnailTrack = subtitleData.find(sub =>
|
||||||
|
sub.lang && sub.lang.toLowerCase() === 'thumbnails'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (thumbnailTrack && thumbnailTrack.url) {
|
||||||
|
console.log('[Watch] Found thumbnails track:', thumbnailTrack.url);
|
||||||
|
setThumbnails(thumbnailTrack.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filteredSubtitles.length > 0) {
|
||||||
|
console.log('[Watch] Found subtitles:', filteredSubtitles.length);
|
||||||
|
setSubtitles(filteredSubtitles);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to find the best source in order of preference
|
// Try to find the best source in order of preference
|
||||||
@@ -421,8 +441,8 @@ export default function WatchPage() {
|
|||||||
subtitles={subtitles}
|
subtitles={subtitles}
|
||||||
thumbnails={thumbnails}
|
thumbnails={thumbnails}
|
||||||
category={isDub ? 'dub' : 'sub'}
|
category={isDub ? 'dub' : 'sub'}
|
||||||
intro={episodeData?.intro}
|
intro={episodeData?.intro || null}
|
||||||
outro={episodeData?.outro}
|
outro={episodeData?.outro || null}
|
||||||
autoSkipIntro={autoSkip}
|
autoSkipIntro={autoSkip}
|
||||||
autoSkipOutro={autoSkip}
|
autoSkipOutro={autoSkip}
|
||||||
episodeId={currentEpisodeId}
|
episodeId={currentEpisodeId}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import Hls from 'hls.js';
|
import Hls from 'hls.js';
|
||||||
import Image from 'next/image';
|
import NextImage from 'next/image';
|
||||||
|
|
||||||
// Get the M3U8 Proxy URL from environment variables
|
// Get the M3U8 Proxy URL from environment variables
|
||||||
const CORSPROXY_URL = process.env.NEXT_PUBLIC_CORSPROXY_URL;
|
const CORSPROXY_URL = process.env.NEXT_PUBLIC_CORSPROXY_URL;
|
||||||
@@ -99,11 +99,22 @@ export default function VideoPlayer({ src, poster, headers = {}, subtitles = [],
|
|||||||
const getProxiedUrl = (url) => {
|
const getProxiedUrl = (url) => {
|
||||||
if (!url) return url;
|
if (!url) return url;
|
||||||
|
|
||||||
|
// Log the original URL for debugging
|
||||||
|
console.log('[VideoPlayer] Original URL:', url);
|
||||||
|
|
||||||
// Check if the URL is an M3U8 URL
|
// Check if the URL is an M3U8 URL
|
||||||
if (url.includes('.m3u8') || url.includes('application/vnd.apple.mpegurl')) {
|
if (url.includes('.m3u8') || url.includes('application/vnd.apple.mpegurl')) {
|
||||||
|
// Check if we have a CORS proxy URL configured
|
||||||
|
if (!CORSPROXY_URL) {
|
||||||
|
console.warn('[VideoPlayer] No CORS proxy URL configured, using original URL');
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
// Route through the external M3U8 proxy server
|
// Route through the external M3U8 proxy server
|
||||||
const encodedUrl = encodeURIComponent(url);
|
const encodedUrl = encodeURIComponent(url);
|
||||||
return `${CORSPROXY_URL}/m3u8-proxy?url=${encodedUrl}`;
|
const proxiedUrl = `${CORSPROXY_URL}/m3u8-proxy?url=${encodedUrl}`;
|
||||||
|
console.log('[VideoPlayer] Using proxied URL:', proxiedUrl);
|
||||||
|
return proxiedUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return url;
|
return url;
|
||||||
@@ -259,7 +270,14 @@ export default function VideoPlayer({ src, poster, headers = {}, subtitles = [],
|
|||||||
maxMaxBufferLength: 60,
|
maxMaxBufferLength: 60,
|
||||||
startLevel: -1, // Auto level selection
|
startLevel: -1, // Auto level selection
|
||||||
capLevelToPlayerSize: true, // Limit quality based on player size
|
capLevelToPlayerSize: true, // Limit quality based on player size
|
||||||
debug: false
|
debug: false,
|
||||||
|
// Add more robust error recovery
|
||||||
|
fragLoadingMaxRetry: 5,
|
||||||
|
manifestLoadingMaxRetry: 5,
|
||||||
|
levelLoadingMaxRetry: 5,
|
||||||
|
fragLoadingRetryDelay: 1000,
|
||||||
|
manifestLoadingRetryDelay: 1000,
|
||||||
|
levelLoadingRetryDelay: 1000
|
||||||
});
|
});
|
||||||
|
|
||||||
window.hls = hls; // Save reference for debugging
|
window.hls = hls; // Save reference for debugging
|
||||||
@@ -294,26 +312,28 @@ export default function VideoPlayer({ src, poster, headers = {}, subtitles = [],
|
|||||||
});
|
});
|
||||||
|
|
||||||
hls.on(Hls.Events.ERROR, (event, data) => {
|
hls.on(Hls.Events.ERROR, (event, data) => {
|
||||||
|
console.error('[VideoPlayer] HLS error:', event, data);
|
||||||
|
|
||||||
if (data.fatal) {
|
if (data.fatal) {
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case Hls.ErrorTypes.NETWORK_ERROR:
|
case Hls.ErrorTypes.NETWORK_ERROR:
|
||||||
console.error('HLS network error');
|
console.error('[VideoPlayer] HLS network error, attempting recovery');
|
||||||
hls.startLoad();
|
hls.startLoad();
|
||||||
break;
|
break;
|
||||||
case Hls.ErrorTypes.MEDIA_ERROR:
|
case Hls.ErrorTypes.MEDIA_ERROR:
|
||||||
console.error('HLS media error');
|
console.error('[VideoPlayer] HLS media error, attempting recovery');
|
||||||
hls.recoverMediaError();
|
hls.recoverMediaError();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.error('HLS fatal error');
|
console.error('[VideoPlayer] HLS fatal error, cannot recover');
|
||||||
setError('Failed to load video');
|
setError('Failed to load video - please try another server');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// For non-HLS streams, use native video player
|
// For non-HLS streams, use native video player
|
||||||
video.src = src;
|
console.log('[VideoPlayer] Using native player for source:', src);
|
||||||
|
|
||||||
// Set headers for direct video requests
|
// Set headers for direct video requests
|
||||||
const fetchOptions = {
|
const fetchOptions = {
|
||||||
@@ -322,7 +342,10 @@ export default function VideoPlayer({ src, poster, headers = {}, subtitles = [],
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(src, fetchOptions);
|
const response = await fetch(src, fetchOptions);
|
||||||
if (!response.ok) throw new Error('Failed to load video');
|
if (!response.ok) {
|
||||||
|
console.error('[VideoPlayer] Failed to fetch video:', response.status, response.statusText);
|
||||||
|
throw new Error('Failed to load video');
|
||||||
|
}
|
||||||
|
|
||||||
const blob = await response.blob();
|
const blob = await response.blob();
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
@@ -330,18 +353,20 @@ export default function VideoPlayer({ src, poster, headers = {}, subtitles = [],
|
|||||||
|
|
||||||
// Auto-play when ready
|
// Auto-play when ready
|
||||||
if (isPlaying) {
|
if (isPlaying) {
|
||||||
video.play().catch(console.error);
|
video.play().catch(err => {
|
||||||
|
console.error('[VideoPlayer] Autoplay error:', err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading video:', error);
|
console.error('[VideoPlayer] Error loading video:', error);
|
||||||
setError('Failed to load video');
|
setError('Failed to load video - please try another server');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error setting up video:', error);
|
console.error('[VideoPlayer] Error setting up video:', error);
|
||||||
setError('Failed to load video');
|
setError('Failed to load video - please try another server');
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -562,18 +587,6 @@ export default function VideoPlayer({ src, poster, headers = {}, subtitles = [],
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Setup thumbnails for scrubbing preview
|
|
||||||
useEffect(() => {
|
|
||||||
if (thumbnails) {
|
|
||||||
console.log('Thumbnails URL available:', thumbnails);
|
|
||||||
const video = videoRef.current;
|
|
||||||
if (video) {
|
|
||||||
// Add data attribute for custom video player to use
|
|
||||||
video.setAttribute('data-thumbnails', thumbnails);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [thumbnails]);
|
|
||||||
|
|
||||||
// Toggle fullscreen
|
// Toggle fullscreen
|
||||||
const toggleFullscreen = () => {
|
const toggleFullscreen = () => {
|
||||||
const container = videoRef.current?.parentElement;
|
const container = videoRef.current?.parentElement;
|
||||||
@@ -1045,14 +1058,13 @@ export default function VideoPlayer({ src, poster, headers = {}, subtitles = [],
|
|||||||
// Load and verify thumbnails
|
// Load and verify thumbnails
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (thumbnails) {
|
if (thumbnails) {
|
||||||
const img = new Image();
|
const img = new window.Image();
|
||||||
img.onload = () => {
|
img.onload = () => {
|
||||||
setThumbnailsLoaded(true);
|
setThumbnailsLoaded(true);
|
||||||
console.log('Thumbnails loaded successfully');
|
console.log('Thumbnails loaded successfully');
|
||||||
};
|
};
|
||||||
img.onerror = () => {
|
img.onerror = (err) => {
|
||||||
console.error('Failed to load thumbnails');
|
console.error('Error loading thumbnails:', err);
|
||||||
setThumbnailsLoaded(false);
|
|
||||||
};
|
};
|
||||||
img.src = thumbnails;
|
img.src = thumbnails;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -586,33 +586,41 @@ export const fetchEpisodeSources = async (episodeId, dub = false, server = 'hd-2
|
|||||||
return { sources: [] };
|
return { sources: [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data.success) {
|
// Check if response is valid (status 200 or success flag)
|
||||||
console.error('[API Error] Response indicates failure - success flag is false');
|
// Some API responses use success flag, others use status code
|
||||||
|
const isValidResponse = (data.success === true) || (data.status === 200);
|
||||||
|
if (!isValidResponse) {
|
||||||
|
console.error('[API Error] Response indicates failure - invalid status or success flag');
|
||||||
return { sources: [] };
|
return { sources: [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data.data) {
|
// Get the data object from either data.data (new format) or data (old format)
|
||||||
|
const responseData = data.data || data;
|
||||||
|
|
||||||
|
if (!responseData) {
|
||||||
console.error('[API Error] Empty data object in response');
|
console.error('[API Error] Empty data object in response');
|
||||||
return { sources: [] };
|
return { sources: [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data.data.sources || data.data.sources.length === 0) {
|
if (!responseData.sources || responseData.sources.length === 0) {
|
||||||
console.error('[API Error] No sources found in response data');
|
console.error('[API Error] No sources found in response data');
|
||||||
return { sources: [] };
|
return { sources: [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[API Success] Found sources:', data.data.sources.map(s => ({
|
console.log('[API Success] Found sources:', responseData.sources.map(s => ({
|
||||||
url: s.url.substring(0, 50) + '...',
|
url: s.url.substring(0, 50) + '...',
|
||||||
quality: s.quality,
|
quality: s.quality,
|
||||||
isM3U8: s.isM3U8
|
isM3U8: s.isM3U8
|
||||||
})));
|
})));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sources: data.data.sources || [],
|
sources: responseData.sources || [],
|
||||||
headers: data.data.headers || { "Referer": "https://hianime.to/" },
|
headers: responseData.headers || { "Referer": "https://hianime.to/" },
|
||||||
subtitles: data.data.subtitles || [],
|
subtitles: responseData.tracks || responseData.subtitles || [],
|
||||||
anilistID: data.data.anilistID || null,
|
anilistID: responseData.anilistID || null,
|
||||||
malID: data.data.malID || null
|
malID: responseData.malID || null,
|
||||||
|
intro: responseData.intro || null,
|
||||||
|
outro: responseData.outro || null
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching episode sources:', error);
|
console.error('Error fetching episode sources:', error);
|
||||||
|
|||||||
Reference in New Issue
Block a user