From bc4bf5a9637b7bcef39180a6aa5dc36d4783cfd8 Mon Sep 17 00:00:00 2001 From: tapframe Date: Thu, 11 Sep 2025 13:41:26 +0530 Subject: [PATCH] Fixed an issue with Container Parsing on AndroidVideoPlayer --- src/components/player/AndroidVideoPlayer.tsx | 38 ++++++++++++++++++- .../player/controls/PlayerControls.tsx | 3 +- src/screens/StreamsScreen.tsx | 23 ++++++++++- 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/components/player/AndroidVideoPlayer.tsx b/src/components/player/AndroidVideoPlayer.tsx index 66209a01..d0023374 100644 --- a/src/components/player/AndroidVideoPlayer.tsx +++ b/src/components/player/AndroidVideoPlayer.tsx @@ -74,6 +74,18 @@ const AndroidVideoPlayer: React.FC = () => { backdrop } = route.params; + // Optional hint not yet in typed navigator params + const videoType = (route.params as any).videoType as string | undefined; + + const defaultAndroidHeaders = () => { + if (Platform.OS !== 'android') return {} as any; + return { + 'User-Agent': 'ExoPlayerLib/2.19.1 (Linux;Android) Nuvio/1.0', + 'Accept': '*/*', + 'Connection': 'keep-alive', + } as any; + }; + // Initialize Trakt autosync const traktAutosync = useTraktAutosync({ id: id || '', @@ -177,6 +189,7 @@ const AndroidVideoPlayer: React.FC = () => { const [showSourcesModal, setShowSourcesModal] = useState(false); const [availableStreams, setAvailableStreams] = useState<{ [providerId: string]: { streams: any[]; addonName: string } }>(passedAvailableStreams || {}); const [currentStreamUrl, setCurrentStreamUrl] = useState(uri); + const [currentVideoType, setCurrentVideoType] = useState(videoType); // Track a single silent retry per source to avoid loops const retryAttemptRef = useRef(0); const [isChangingSource, setIsChangingSource] = useState(false); @@ -1020,6 +1033,29 @@ const AndroidVideoPlayer: React.FC = () => { return; // Do not proceed to show error UI } + // If format unrecognized, try flipping between HLS and MP4 once + const isUnrecognized = !!(error?.error?.errorString && String(error.error.errorString).includes('UnrecognizedInputFormatException')); + if (isUnrecognized && retryAttemptRef.current < 1) { + retryAttemptRef.current = 1; + const nextType = currentVideoType === 'm3u8' ? 'mp4' : 'm3u8'; + logger.warn(`[AndroidVideoPlayer] Format not recognized. Retrying with type='${nextType}'`); + if (errorTimeoutRef.current) { + clearTimeout(errorTimeoutRef.current); + errorTimeoutRef.current = null; + } + safeSetState(() => setShowErrorModal(false)); + setPaused(true); + setTimeout(() => { + if (!isMounted.current) return; + setCurrentVideoType(nextType); + // Force re-mount of source by tweaking URL param + const sep = currentStreamUrl.includes('?') ? '&' : '?'; + setCurrentStreamUrl(`${currentStreamUrl}${sep}rn_type_retry=${Date.now()}`); + setPaused(false); + }, 120); + return; + } + // Check for specific AVFoundation server configuration errors (iOS) const isServerConfigError = error?.error?.code === -11850 || error?.code === -11850 || @@ -2031,7 +2067,7 @@ const AndroidVideoPlayer: React.FC = () => {