This commit is contained in:
tapframe 2025-12-22 21:40:11 +05:30
parent 19438ff1d5
commit 9504d48607
7 changed files with 64 additions and 49 deletions

View file

@ -145,7 +145,9 @@ class MPVView @JvmOverloads constructor(
} }
fun seekTo(positionSeconds: Double) { fun seekTo(positionSeconds: Double) {
Log.d(TAG, "seekTo called: positionSeconds=$positionSeconds, isMpvInitialized=$isMpvInitialized")
if (isMpvInitialized) { if (isMpvInitialized) {
Log.d(TAG, "Executing MPV seek command: seek $positionSeconds absolute")
MPVLib.command(arrayOf("seek", positionSeconds.toString(), "absolute")) MPVLib.command(arrayOf("seek", positionSeconds.toString(), "absolute"))
} }
} }

View file

@ -84,9 +84,12 @@ class MpvPlayerViewManager(
} }
override fun receiveCommand(view: MPVView, commandId: String?, args: ReadableArray?) { override fun receiveCommand(view: MPVView, commandId: String?, args: ReadableArray?) {
android.util.Log.d("MpvPlayerViewManager", "receiveCommand: $commandId, args: $args")
when (commandId) { when (commandId) {
"seek" -> { "seek" -> {
args?.getDouble(0)?.let { view.seekTo(it) } val position = args?.getDouble(0)
android.util.Log.d("MpvPlayerViewManager", "Seek command received: position=$position")
position?.let { view.seekTo(it) }
} }
"setAudioTrack" -> { "setAudioTrack" -> {
args?.getInt(0)?.let { view.setAudioTrack(it) } args?.getInt(0)?.let { view.setAudioTrack(it) }

View file

@ -40,6 +40,7 @@ import { ErrorModal } from './modals/ErrorModal';
// Android-specific components // Android-specific components
import { VideoSurface } from './android/components/VideoSurface'; import { VideoSurface } from './android/components/VideoSurface';
import { MpvPlayerRef } from './android/MpvPlayer';
// Utils // Utils
import { logger } from '../../utils/logger'; import { logger } from '../../utils/logger';
@ -75,6 +76,7 @@ const AndroidVideoPlayer: React.FC = () => {
const useVLC = (Platform.OS === 'android' && forceVlc); const useVLC = (Platform.OS === 'android' && forceVlc);
const videoRef = useRef<any>(null); const videoRef = useRef<any>(null);
const mpvPlayerRef = useRef<MpvPlayerRef>(null);
const vlcHook = useVlcPlayer(useVLC, playerState.paused, playerState.currentTime); const vlcHook = useVlcPlayer(useVLC, playerState.paused, playerState.currentTime);
const tracksHook = usePlayerTracks( const tracksHook = usePlayerTracks(
useVLC, useVLC,
@ -103,7 +105,7 @@ const AndroidVideoPlayer: React.FC = () => {
const setupHook = usePlayerSetup(playerState.setScreenDimensions, setVolume, setBrightness, playerState.paused); const setupHook = usePlayerSetup(playerState.setScreenDimensions, setVolume, setBrightness, playerState.paused);
const controlsHook = usePlayerControls( const controlsHook = usePlayerControls(
videoRef, mpvPlayerRef, // Use mpvPlayerRef for MPV player
vlcHook.vlcPlayerRef, vlcHook.vlcPlayerRef,
useVLC, useVLC,
playerState.paused, playerState.paused,
@ -168,6 +170,13 @@ const AndroidVideoPlayer: React.FC = () => {
if (!playerState.isMounted.current) return; if (!playerState.isMounted.current) return;
const videoDuration = data.duration; const videoDuration = data.duration;
console.log('[AndroidVideoPlayer] handleLoad called:', {
duration: videoDuration,
initialPosition: watchProgress.initialPosition,
showResumeOverlay: watchProgress.showResumeOverlay,
initialSeekTarget: watchProgress.initialSeekTargetRef?.current
});
if (videoDuration > 0) { if (videoDuration > 0) {
playerState.setDuration(videoDuration); playerState.setDuration(videoDuration);
if (id && type) { if (id && type) {
@ -204,9 +213,17 @@ const AndroidVideoPlayer: React.FC = () => {
playerState.setIsVideoLoaded(true); playerState.setIsVideoLoaded(true);
openingAnimation.completeOpeningAnimation(); openingAnimation.completeOpeningAnimation();
// Handle Resume // Handle Resume - check both initialPosition and initialSeekTargetRef
if (watchProgress.initialPosition && !watchProgress.showResumeOverlay) { const resumeTarget = watchProgress.initialPosition || watchProgress.initialSeekTargetRef?.current;
controlsHook.seekToTime(watchProgress.initialPosition); if (resumeTarget && resumeTarget > 0 && !watchProgress.showResumeOverlay && videoDuration > 0) {
console.log('[AndroidVideoPlayer] Seeking to resume position:', resumeTarget, 'duration:', videoDuration);
// Use a small delay to ensure the player is ready, then seek directly
setTimeout(() => {
if (mpvPlayerRef.current) {
console.log('[AndroidVideoPlayer] Calling mpvPlayerRef.current.seek directly');
mpvPlayerRef.current.seek(Math.min(resumeTarget, videoDuration - 0.5));
}
}, 200);
} }
}, [id, type, episodeId, useVLC, playerState.isMounted, watchProgress.initialPosition]); }, [id, type, episodeId, useVLC, playerState.isMounted, watchProgress.initialPosition]);
@ -385,6 +402,7 @@ const AndroidVideoPlayer: React.FC = () => {
onBuffer={(buf) => playerState.setIsBuffering(buf.isBuffering)} onBuffer={(buf) => playerState.setIsBuffering(buf.isBuffering)}
onTracksUpdate={vlcHook.handleVlcTracksUpdate} onTracksUpdate={vlcHook.handleVlcTracksUpdate}
vlcPlayerRef={vlcHook.vlcPlayerRef} vlcPlayerRef={vlcHook.vlcPlayerRef}
mpvPlayerRef={mpvPlayerRef}
videoRef={videoRef} videoRef={videoRef}
pinchRef={useRef(null)} pinchRef={useRef(null)}
onPinchGestureEvent={() => { }} onPinchGestureEvent={() => { }}

View file

@ -59,12 +59,7 @@ const MpvPlayer = forwardRef<MpvPlayerRef, MpvPlayerProps>((props, ref) => {
); );
} }
console.log('[MpvPlayer] Rendering native component with:', { // Debug logging removed to prevent console spam
source: props.source?.substring(0, 50) + '...',
paused: props.paused ?? true,
volume: props.volume ?? 1.0,
rate: props.rate ?? 1.0,
});
const handleLoad = (event: any) => { const handleLoad = (event: any) => {
console.log('[MpvPlayer] Native onLoad event:', event?.nativeEvent); console.log('[MpvPlayer] Native onLoad event:', event?.nativeEvent);
@ -72,11 +67,7 @@ const MpvPlayer = forwardRef<MpvPlayerRef, MpvPlayerProps>((props, ref) => {
}; };
const handleProgress = (event: any) => { const handleProgress = (event: any) => {
const data = event?.nativeEvent; props.onProgress?.(event?.nativeEvent);
if (data && Math.floor(data.currentTime) % 5 === 0) {
console.log('[MpvPlayer] Native onProgress event:', data);
}
props.onProgress?.(data);
}; };
const handleEnd = (event: any) => { const handleEnd = (event: any) => {

View file

@ -1,10 +1,9 @@
import React from 'react'; import React, { useCallback, memo } from 'react';
import { View, TouchableWithoutFeedback, StyleSheet } from 'react-native'; import { View, TouchableWithoutFeedback, StyleSheet } from 'react-native';
import { PinchGestureHandler } from 'react-native-gesture-handler'; import { PinchGestureHandler } from 'react-native-gesture-handler';
import MpvPlayer, { MpvPlayerRef } from '../MpvPlayer'; import MpvPlayer, { MpvPlayerRef } from '../MpvPlayer';
import { styles } from '../../utils/playerStyles'; import { styles } from '../../utils/playerStyles';
import { ResizeModeType } from '../../utils/playerTypes'; import { ResizeModeType } from '../../utils/playerTypes';
import { logger } from '../../../../utils/logger';
interface VideoSurfaceProps { interface VideoSurfaceProps {
processedStreamUrl: string; processedStreamUrl: string;
@ -77,13 +76,7 @@ export const VideoSurface: React.FC<VideoSurfaceProps> = ({
// Use the actual stream URL // Use the actual stream URL
const streamUrl = currentStreamUrl || processedStreamUrl; const streamUrl = currentStreamUrl || processedStreamUrl;
console.log('[VideoSurface] Rendering with:', { // Debug logging removed to prevent console spam
streamUrl: streamUrl?.substring(0, 50) + '...',
paused,
volume,
playbackSpeed,
screenDimensions,
});
const handleLoad = (data: { duration: number; width: number; height: number }) => { const handleLoad = (data: { duration: number; width: number; height: number }) => {
console.log('[VideoSurface] onLoad received:', data); console.log('[VideoSurface] onLoad received:', data);
@ -97,10 +90,6 @@ export const VideoSurface: React.FC<VideoSurfaceProps> = ({
}; };
const handleProgress = (data: { currentTime: number; duration: number }) => { const handleProgress = (data: { currentTime: number; duration: number }) => {
// Log every 5 seconds to avoid spam
if (Math.floor(data.currentTime) % 5 === 0) {
console.log('[VideoSurface] onProgress:', data);
}
onProgress({ onProgress({
currentTime: data.currentTime, currentTime: data.currentTime,
playableDuration: data.currentTime, playableDuration: data.currentTime,

View file

@ -2,11 +2,11 @@ import { useRef, useCallback } from 'react';
import { Platform } from 'react-native'; import { Platform } from 'react-native';
import { logger } from '../../../../utils/logger'; import { logger } from '../../../../utils/logger';
const DEBUG_MODE = false; const DEBUG_MODE = true; // Temporarily enable for debugging seek
const END_EPSILON = 0.3; const END_EPSILON = 0.3;
export const usePlayerControls = ( export const usePlayerControls = (
videoRef: any, mpvPlayerRef: any,
vlcPlayerRef: any, vlcPlayerRef: any,
useVLC: boolean, useVLC: boolean,
paused: boolean, paused: boolean,
@ -26,39 +26,46 @@ export const usePlayerControls = (
const seekToTime = useCallback((rawSeconds: number) => { const seekToTime = useCallback((rawSeconds: number) => {
const timeInSeconds = Math.max(0, Math.min(rawSeconds, duration > 0 ? duration - END_EPSILON : rawSeconds)); const timeInSeconds = Math.max(0, Math.min(rawSeconds, duration > 0 ? duration - END_EPSILON : rawSeconds));
console.log('[usePlayerControls] seekToTime called:', {
rawSeconds,
timeInSeconds,
useVLC,
hasMpvRef: !!mpvPlayerRef?.current,
hasVlcRef: !!vlcPlayerRef?.current,
duration,
isSeeking: isSeeking.current
});
if (useVLC) { if (useVLC) {
if (vlcPlayerRef.current && duration > 0) { if (vlcPlayerRef.current && duration > 0) {
if (DEBUG_MODE) logger.log(`[usePlayerControls][VLC] Seeking to ${timeInSeconds}`); logger.log(`[usePlayerControls][VLC] Seeking to ${timeInSeconds}`);
vlcPlayerRef.current.seek(timeInSeconds); vlcPlayerRef.current.seek(timeInSeconds);
} }
} else { } else {
if (videoRef.current && duration > 0 && !isSeeking.current) { // MPV Player
if (DEBUG_MODE) logger.log(`[usePlayerControls] Seeking to ${timeInSeconds}`); if (mpvPlayerRef.current && duration > 0) {
console.log(`[usePlayerControls][MPV] Seeking to ${timeInSeconds}`);
isSeeking.current = true; isSeeking.current = true;
mpvPlayerRef.current.seek(timeInSeconds);
if (Platform.OS === 'ios') { // Reset seeking flag after a delay
iosWasPausedDuringSeekRef.current = paused;
if (!paused) setPaused(true);
}
// Actually perform the seek
videoRef.current.seek(timeInSeconds);
setTimeout(() => { setTimeout(() => {
if (isMounted.current && isSeeking.current) { if (isMounted.current) {
isSeeking.current = false; isSeeking.current = false;
if (Platform.OS === 'ios' && iosWasPausedDuringSeekRef.current === false) {
setPaused(false);
iosWasPausedDuringSeekRef.current = null;
}
} }
}, 500); }, 500);
} else {
console.log('[usePlayerControls][MPV] Cannot seek - ref or duration invalid:', {
hasRef: !!mpvPlayerRef?.current,
duration
});
} }
} }
}, [useVLC, duration, paused, setPaused, videoRef, vlcPlayerRef, isSeeking, isMounted]); }, [useVLC, duration, paused, setPaused, mpvPlayerRef, vlcPlayerRef, isSeeking, isMounted]);
const skip = useCallback((seconds: number) => { const skip = useCallback((seconds: number) => {
console.log('[usePlayerControls] skip called:', { seconds, currentTime, newTime: currentTime + seconds });
seekToTime(currentTime + seconds); seekToTime(currentTime + seconds);
}, [currentTime, seekToTime]); }, [currentTime, seekToTime]);

View file

@ -40,17 +40,22 @@ export const useWatchProgress = (
if (id && type) { if (id && type) {
try { try {
const savedProgress = await storageService.getWatchProgress(id, type, episodeId); const savedProgress = await storageService.getWatchProgress(id, type, episodeId);
console.log('[useWatchProgress] Loaded saved progress:', savedProgress);
if (savedProgress) { if (savedProgress) {
const progressPercent = (savedProgress.currentTime / savedProgress.duration) * 100; const progressPercent = (savedProgress.currentTime / savedProgress.duration) * 100;
console.log('[useWatchProgress] Progress percent:', progressPercent);
if (progressPercent < 85) { if (progressPercent < 85) {
setResumePosition(savedProgress.currentTime); setResumePosition(savedProgress.currentTime);
setSavedDuration(savedProgress.duration); setSavedDuration(savedProgress.duration);
if (appSettings.alwaysResume) { if (appSettings.alwaysResume) {
console.log('[useWatchProgress] Always resume enabled, setting initial position:', savedProgress.currentTime);
setInitialPosition(savedProgress.currentTime); setInitialPosition(savedProgress.currentTime);
initialSeekTargetRef.current = savedProgress.currentTime; initialSeekTargetRef.current = savedProgress.currentTime;
seekToTime(savedProgress.currentTime); // Don't call seekToTime here - duration is 0
// The seek will be handled in handleLoad callback
} else { } else {
setShowResumeOverlay(true); setShowResumeOverlay(true);
} }