mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-01-11 20:10:25 +00:00
seek fix
This commit is contained in:
parent
19438ff1d5
commit
9504d48607
7 changed files with 64 additions and 49 deletions
|
|
@ -145,7 +145,9 @@ class MPVView @JvmOverloads constructor(
|
|||
}
|
||||
|
||||
fun seekTo(positionSeconds: Double) {
|
||||
Log.d(TAG, "seekTo called: positionSeconds=$positionSeconds, isMpvInitialized=$isMpvInitialized")
|
||||
if (isMpvInitialized) {
|
||||
Log.d(TAG, "Executing MPV seek command: seek $positionSeconds absolute")
|
||||
MPVLib.command(arrayOf("seek", positionSeconds.toString(), "absolute"))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,9 +84,12 @@ class MpvPlayerViewManager(
|
|||
}
|
||||
|
||||
override fun receiveCommand(view: MPVView, commandId: String?, args: ReadableArray?) {
|
||||
android.util.Log.d("MpvPlayerViewManager", "receiveCommand: $commandId, args: $args")
|
||||
when (commandId) {
|
||||
"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" -> {
|
||||
args?.getInt(0)?.let { view.setAudioTrack(it) }
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import { ErrorModal } from './modals/ErrorModal';
|
|||
|
||||
// Android-specific components
|
||||
import { VideoSurface } from './android/components/VideoSurface';
|
||||
import { MpvPlayerRef } from './android/MpvPlayer';
|
||||
|
||||
// Utils
|
||||
import { logger } from '../../utils/logger';
|
||||
|
|
@ -75,6 +76,7 @@ const AndroidVideoPlayer: React.FC = () => {
|
|||
const useVLC = (Platform.OS === 'android' && forceVlc);
|
||||
|
||||
const videoRef = useRef<any>(null);
|
||||
const mpvPlayerRef = useRef<MpvPlayerRef>(null);
|
||||
const vlcHook = useVlcPlayer(useVLC, playerState.paused, playerState.currentTime);
|
||||
const tracksHook = usePlayerTracks(
|
||||
useVLC,
|
||||
|
|
@ -103,7 +105,7 @@ const AndroidVideoPlayer: React.FC = () => {
|
|||
const setupHook = usePlayerSetup(playerState.setScreenDimensions, setVolume, setBrightness, playerState.paused);
|
||||
|
||||
const controlsHook = usePlayerControls(
|
||||
videoRef,
|
||||
mpvPlayerRef, // Use mpvPlayerRef for MPV player
|
||||
vlcHook.vlcPlayerRef,
|
||||
useVLC,
|
||||
playerState.paused,
|
||||
|
|
@ -168,6 +170,13 @@ const AndroidVideoPlayer: React.FC = () => {
|
|||
if (!playerState.isMounted.current) return;
|
||||
|
||||
const videoDuration = data.duration;
|
||||
console.log('[AndroidVideoPlayer] handleLoad called:', {
|
||||
duration: videoDuration,
|
||||
initialPosition: watchProgress.initialPosition,
|
||||
showResumeOverlay: watchProgress.showResumeOverlay,
|
||||
initialSeekTarget: watchProgress.initialSeekTargetRef?.current
|
||||
});
|
||||
|
||||
if (videoDuration > 0) {
|
||||
playerState.setDuration(videoDuration);
|
||||
if (id && type) {
|
||||
|
|
@ -204,9 +213,17 @@ const AndroidVideoPlayer: React.FC = () => {
|
|||
playerState.setIsVideoLoaded(true);
|
||||
openingAnimation.completeOpeningAnimation();
|
||||
|
||||
// Handle Resume
|
||||
if (watchProgress.initialPosition && !watchProgress.showResumeOverlay) {
|
||||
controlsHook.seekToTime(watchProgress.initialPosition);
|
||||
// Handle Resume - check both initialPosition and initialSeekTargetRef
|
||||
const resumeTarget = watchProgress.initialPosition || watchProgress.initialSeekTargetRef?.current;
|
||||
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]);
|
||||
|
||||
|
|
@ -385,6 +402,7 @@ const AndroidVideoPlayer: React.FC = () => {
|
|||
onBuffer={(buf) => playerState.setIsBuffering(buf.isBuffering)}
|
||||
onTracksUpdate={vlcHook.handleVlcTracksUpdate}
|
||||
vlcPlayerRef={vlcHook.vlcPlayerRef}
|
||||
mpvPlayerRef={mpvPlayerRef}
|
||||
videoRef={videoRef}
|
||||
pinchRef={useRef(null)}
|
||||
onPinchGestureEvent={() => { }}
|
||||
|
|
|
|||
|
|
@ -59,12 +59,7 @@ const MpvPlayer = forwardRef<MpvPlayerRef, MpvPlayerProps>((props, ref) => {
|
|||
);
|
||||
}
|
||||
|
||||
console.log('[MpvPlayer] Rendering native component with:', {
|
||||
source: props.source?.substring(0, 50) + '...',
|
||||
paused: props.paused ?? true,
|
||||
volume: props.volume ?? 1.0,
|
||||
rate: props.rate ?? 1.0,
|
||||
});
|
||||
// Debug logging removed to prevent console spam
|
||||
|
||||
const handleLoad = (event: any) => {
|
||||
console.log('[MpvPlayer] Native onLoad event:', event?.nativeEvent);
|
||||
|
|
@ -72,11 +67,7 @@ const MpvPlayer = forwardRef<MpvPlayerRef, MpvPlayerProps>((props, ref) => {
|
|||
};
|
||||
|
||||
const handleProgress = (event: any) => {
|
||||
const data = event?.nativeEvent;
|
||||
if (data && Math.floor(data.currentTime) % 5 === 0) {
|
||||
console.log('[MpvPlayer] Native onProgress event:', data);
|
||||
}
|
||||
props.onProgress?.(data);
|
||||
props.onProgress?.(event?.nativeEvent);
|
||||
};
|
||||
|
||||
const handleEnd = (event: any) => {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import React from 'react';
|
||||
import React, { useCallback, memo } from 'react';
|
||||
import { View, TouchableWithoutFeedback, StyleSheet } from 'react-native';
|
||||
import { PinchGestureHandler } from 'react-native-gesture-handler';
|
||||
import MpvPlayer, { MpvPlayerRef } from '../MpvPlayer';
|
||||
import { styles } from '../../utils/playerStyles';
|
||||
import { ResizeModeType } from '../../utils/playerTypes';
|
||||
import { logger } from '../../../../utils/logger';
|
||||
|
||||
interface VideoSurfaceProps {
|
||||
processedStreamUrl: string;
|
||||
|
|
@ -77,13 +76,7 @@ export const VideoSurface: React.FC<VideoSurfaceProps> = ({
|
|||
// Use the actual stream URL
|
||||
const streamUrl = currentStreamUrl || processedStreamUrl;
|
||||
|
||||
console.log('[VideoSurface] Rendering with:', {
|
||||
streamUrl: streamUrl?.substring(0, 50) + '...',
|
||||
paused,
|
||||
volume,
|
||||
playbackSpeed,
|
||||
screenDimensions,
|
||||
});
|
||||
// Debug logging removed to prevent console spam
|
||||
|
||||
const handleLoad = (data: { duration: number; width: number; height: number }) => {
|
||||
console.log('[VideoSurface] onLoad received:', data);
|
||||
|
|
@ -97,10 +90,6 @@ export const VideoSurface: React.FC<VideoSurfaceProps> = ({
|
|||
};
|
||||
|
||||
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({
|
||||
currentTime: data.currentTime,
|
||||
playableDuration: data.currentTime,
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ import { useRef, useCallback } from 'react';
|
|||
import { Platform } from 'react-native';
|
||||
import { logger } from '../../../../utils/logger';
|
||||
|
||||
const DEBUG_MODE = false;
|
||||
const DEBUG_MODE = true; // Temporarily enable for debugging seek
|
||||
const END_EPSILON = 0.3;
|
||||
|
||||
export const usePlayerControls = (
|
||||
videoRef: any,
|
||||
mpvPlayerRef: any,
|
||||
vlcPlayerRef: any,
|
||||
useVLC: boolean,
|
||||
paused: boolean,
|
||||
|
|
@ -26,39 +26,46 @@ export const usePlayerControls = (
|
|||
const seekToTime = useCallback((rawSeconds: number) => {
|
||||
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 (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);
|
||||
}
|
||||
} else {
|
||||
if (videoRef.current && duration > 0 && !isSeeking.current) {
|
||||
if (DEBUG_MODE) logger.log(`[usePlayerControls] Seeking to ${timeInSeconds}`);
|
||||
// MPV Player
|
||||
if (mpvPlayerRef.current && duration > 0) {
|
||||
console.log(`[usePlayerControls][MPV] Seeking to ${timeInSeconds}`);
|
||||
|
||||
isSeeking.current = true;
|
||||
mpvPlayerRef.current.seek(timeInSeconds);
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
iosWasPausedDuringSeekRef.current = paused;
|
||||
if (!paused) setPaused(true);
|
||||
}
|
||||
|
||||
// Actually perform the seek
|
||||
videoRef.current.seek(timeInSeconds);
|
||||
|
||||
// Reset seeking flag after a delay
|
||||
setTimeout(() => {
|
||||
if (isMounted.current && isSeeking.current) {
|
||||
if (isMounted.current) {
|
||||
isSeeking.current = false;
|
||||
if (Platform.OS === 'ios' && iosWasPausedDuringSeekRef.current === false) {
|
||||
setPaused(false);
|
||||
iosWasPausedDuringSeekRef.current = null;
|
||||
}
|
||||
}
|
||||
}, 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) => {
|
||||
console.log('[usePlayerControls] skip called:', { seconds, currentTime, newTime: currentTime + seconds });
|
||||
seekToTime(currentTime + seconds);
|
||||
}, [currentTime, seekToTime]);
|
||||
|
||||
|
|
|
|||
|
|
@ -40,17 +40,22 @@ export const useWatchProgress = (
|
|||
if (id && type) {
|
||||
try {
|
||||
const savedProgress = await storageService.getWatchProgress(id, type, episodeId);
|
||||
console.log('[useWatchProgress] Loaded saved progress:', savedProgress);
|
||||
|
||||
if (savedProgress) {
|
||||
const progressPercent = (savedProgress.currentTime / savedProgress.duration) * 100;
|
||||
console.log('[useWatchProgress] Progress percent:', progressPercent);
|
||||
|
||||
if (progressPercent < 85) {
|
||||
setResumePosition(savedProgress.currentTime);
|
||||
setSavedDuration(savedProgress.duration);
|
||||
|
||||
if (appSettings.alwaysResume) {
|
||||
console.log('[useWatchProgress] Always resume enabled, setting initial position:', savedProgress.currentTime);
|
||||
setInitialPosition(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 {
|
||||
setShowResumeOverlay(true);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue