mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-03-24 03:27:43 +00:00
double encoded url fix
This commit is contained in:
parent
2bf7dcd635
commit
f111514090
2 changed files with 65 additions and 19 deletions
|
|
@ -47,8 +47,26 @@ const VideoPlayer: React.FC = () => {
|
|||
const route = useRoute<RouteProp<RootStackParamList, 'Player'>>();
|
||||
const { streamProvider, uri, headers, forceVlc } = route.params as any;
|
||||
|
||||
// Check if the stream is from Xprime
|
||||
const isXprimeStream = streamProvider === 'xprime' || streamProvider === 'Xprime';
|
||||
// Check if the stream is from Xprime (by provider name or URL pattern)
|
||||
const isXprimeStream = streamProvider === 'xprime' || streamProvider === 'Xprime' ||
|
||||
(uri && /flutch.*\.workers\.dev|fsl\.fastcloud\.casa|xprime/i.test(uri));
|
||||
|
||||
// Xprime-specific headers for better compatibility (from local-scrapers-repo)
|
||||
const getXprimeHeaders = () => {
|
||||
if (!isXprimeStream) return {};
|
||||
return {
|
||||
'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': 'video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5',
|
||||
'Accept-Language': 'en-US,en;q=0.9',
|
||||
'Accept-Encoding': 'identity',
|
||||
'Origin': 'https://xprime.tv',
|
||||
'Referer': 'https://xprime.tv/',
|
||||
'Sec-Fetch-Dest': 'video',
|
||||
'Sec-Fetch-Mode': 'no-cors',
|
||||
'Sec-Fetch-Site': 'cross-site',
|
||||
'DNT': '1'
|
||||
} as any;
|
||||
};
|
||||
|
||||
// Check if the file format is MKV
|
||||
const lowerUri = (uri || '').toLowerCase();
|
||||
|
|
@ -61,6 +79,8 @@ const VideoPlayer: React.FC = () => {
|
|||
// - Android devices
|
||||
// - Xprime streams on any platform
|
||||
// - Non-MKV files on iOS (unless forceVlc is set)
|
||||
// Use VideoPlayer (VLC) for:
|
||||
// - MKV files on iOS (unless forceVlc is set)
|
||||
const shouldUseAndroidPlayer = Platform.OS === 'android' || isXprimeStream || (Platform.OS === 'ios' && !isMkvFile && !forceVlc);
|
||||
if (__DEV__) {
|
||||
logger.log('[VideoPlayer] Player selection:', {
|
||||
|
|
@ -203,7 +223,20 @@ const VideoPlayer: React.FC = () => {
|
|||
const [isLoadingSubtitleList, setIsLoadingSubtitleList] = useState<boolean>(false);
|
||||
const [showSourcesModal, setShowSourcesModal] = useState<boolean>(false);
|
||||
const [availableStreams, setAvailableStreams] = useState<{ [providerId: string]: { streams: any[]; addonName: string } }>(passedAvailableStreams || {});
|
||||
const [currentStreamUrl, setCurrentStreamUrl] = useState<string>(uri);
|
||||
// Decode URLs for VLC compatibility - VLC has issues with encoded URLs
|
||||
const decodeUrlForVlc = (url: string): string => {
|
||||
try {
|
||||
// Always decode URLs for VLC as it has trouble with encoded characters
|
||||
const decoded = decodeURIComponent(url);
|
||||
logger.log('[VideoPlayer] Decoded URL for VLC:', { original: url, decoded });
|
||||
return decoded;
|
||||
} catch (e) {
|
||||
logger.warn('[VideoPlayer] URL decoding failed, using original:', e);
|
||||
return url;
|
||||
}
|
||||
};
|
||||
|
||||
const [currentStreamUrl, setCurrentStreamUrl] = useState<string>(decodeUrlForVlc(uri));
|
||||
const [isChangingSource, setIsChangingSource] = useState<boolean>(false);
|
||||
const [showErrorModal, setShowErrorModal] = useState(false);
|
||||
const [errorDetails, setErrorDetails] = useState<string>('');
|
||||
|
|
@ -1913,8 +1946,8 @@ const VideoPlayer: React.FC = () => {
|
|||
// Set pending seek state
|
||||
setPendingSeek({ position: savedPosition, shouldPlay: wasPlaying });
|
||||
|
||||
// Update the stream URL and details immediately
|
||||
setCurrentStreamUrl(newStream.url);
|
||||
// Update the stream URL and details immediately (decode URL for VLC)
|
||||
setCurrentStreamUrl(decodeUrlForVlc(newStream.url));
|
||||
setCurrentQuality(newQuality);
|
||||
setCurrentStreamProvider(newProvider);
|
||||
setCurrentStreamName(newStreamName);
|
||||
|
|
|
|||
|
|
@ -926,16 +926,24 @@ export const StreamsScreen = () => {
|
|||
const streamName = stream.name || stream.title || 'Unnamed Stream';
|
||||
const streamProvider = stream.addonId || stream.addonName || stream.name;
|
||||
|
||||
// Determine if we should force VLC on iOS based on provider-declared formats (e.g., MKV)
|
||||
// Determine if we should force VLC on iOS based on actual stream format (not provider capability)
|
||||
let forceVlc = !!options?.forceVlc;
|
||||
try {
|
||||
const providerId = stream.addonId || (stream as any).addon;
|
||||
if (Platform.OS === 'ios' && providerId && !forceVlc) {
|
||||
forceVlc = await localScraperService.supportsFormat(providerId, 'mkv');
|
||||
logger.log(`[StreamsScreen] Provider '${providerId}' MKV support -> ${forceVlc}`);
|
||||
if (Platform.OS === 'ios' && !forceVlc) {
|
||||
// Check if the actual stream is an MKV file
|
||||
const lowerUri = (stream.url || '').toLowerCase();
|
||||
const contentType = (stream.headers && ((stream.headers as any)['Content-Type'] || (stream.headers as any)['content-type'])) || '';
|
||||
const isMkvByHeader = typeof contentType === 'string' && contentType.includes('matroska');
|
||||
const isMkvByPath = lowerUri.includes('.mkv') || /[?&]ext=mkv\b/.test(lowerUri) || /format=mkv\b/.test(lowerUri) || /container=mkv\b/.test(lowerUri);
|
||||
const isMkvFile = Boolean(isMkvByHeader || isMkvByPath);
|
||||
|
||||
if (isMkvFile) {
|
||||
forceVlc = true;
|
||||
logger.log(`[StreamsScreen] Stream is MKV format -> forcing VLC`);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
logger.warn('[StreamsScreen] MKV support detection failed:', e);
|
||||
logger.warn('[StreamsScreen] Stream format detection failed:', e);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -997,19 +1005,24 @@ export const StreamsScreen = () => {
|
|||
} catch (_e) {}
|
||||
return;
|
||||
}
|
||||
// If provider declares MKV support, force the in-app VLC-based player on iOS
|
||||
// If stream is actually MKV format, force the in-app VLC-based player on iOS
|
||||
try {
|
||||
const providerId = stream.addonId || (stream as any).addon;
|
||||
if (Platform.OS === 'ios' && providerId) {
|
||||
const providerRequiresVlc = await localScraperService.supportsFormat(providerId, 'mkv');
|
||||
if (providerRequiresVlc) {
|
||||
logger.log(`[StreamsScreen] Forcing in-app VLC for provider '${providerId}' on iOS due to MKV support`);
|
||||
navigateToPlayer(stream);
|
||||
if (Platform.OS === 'ios') {
|
||||
// Check if the actual stream is an MKV file
|
||||
const lowerUri = (stream.url || '').toLowerCase();
|
||||
const contentType = (stream.headers && ((stream.headers as any)['Content-Type'] || (stream.headers as any)['content-type'])) || '';
|
||||
const isMkvByHeader = typeof contentType === 'string' && contentType.includes('matroska');
|
||||
const isMkvByPath = lowerUri.includes('.mkv') || /[?&]ext=mkv\b/.test(lowerUri) || /format=mkv\b/.test(lowerUri) || /container=mkv\b/.test(lowerUri);
|
||||
const isMkvFile = Boolean(isMkvByHeader || isMkvByPath);
|
||||
|
||||
if (isMkvFile) {
|
||||
logger.log(`[StreamsScreen] Stream is MKV format -> forcing VLC on iOS`);
|
||||
navigateToPlayer(stream, { forceVlc: true });
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.warn('[StreamsScreen] MKV pre-check failed:', err);
|
||||
logger.warn('[StreamsScreen] Stream format pre-check failed:', err);
|
||||
}
|
||||
|
||||
// iOS: very short MKV detection race; never block longer than MKV_HEAD_TIMEOUT_MS
|
||||
|
|
|
|||
Loading…
Reference in a new issue