From 26305c2983582ba2d053a6427c0c43b0100946af Mon Sep 17 00:00:00 2001 From: Alex Kim Date: Sun, 8 Dec 2024 02:48:23 +1100 Subject: [PATCH] Used debouncing for trick play and stop rendering trickplay, while not sliding --- components/video-player/controls/Controls.tsx | 177 +++++++++--------- modules/vlc-player/ios/VlcPlayerView.swift | 96 ++++------ 2 files changed, 131 insertions(+), 142 deletions(-) diff --git a/components/video-player/controls/Controls.tsx b/components/video-player/controls/Controls.tsx index ec4e68e8..c74c9c09 100644 --- a/components/video-player/controls/Controls.tsx +++ b/components/video-player/controls/Controls.tsx @@ -52,6 +52,7 @@ import DropdownViewDirect from "./dropdown/DropdownViewDirect"; import DropdownViewTranscoding from "./dropdown/DropdownViewTranscoding"; import BrightnessSlider from "./BrightnessSlider"; import SkipButton from "./SkipButton"; +import { debounce } from "lodash"; interface Props { item: BaseItemDto; @@ -245,13 +246,25 @@ export const Controls: React.FC = ({ useEffect(() => { prefetchAllTrickplayImages(); }, []); - const toggleControls = () => setShowControls(!showControls); + const handleSliderStart = useCallback(() => { + if (showControls === false) return; + + setIsSliding(true); + wasPlayingRef.current = isPlaying; + lastProgressRef.current = progress.value; + + pause(); + isSeeking.value = true; + }, [showControls, isPlaying]); + + const [isSliding, setIsSliding] = useState(false); const handleSliderComplete = useCallback( async (value: number) => { isSeeking.value = false; progress.value = value; + setIsSliding(false); await seek( Math.max(0, Math.floor(isVlc ? value : ticksToSeconds(value))) @@ -262,27 +275,20 @@ export const Controls: React.FC = ({ ); const [time, setTime] = useState({ hours: 0, minutes: 0, seconds: 0 }); + const handleSliderChange = useCallback( + debounce((value: number) => { + const progressInTicks = msToTicks(value); + console.log("Progress in ticks", progressInTicks); + calculateTrickplayUrl(progressInTicks); - const handleSliderChange = (value: number) => { - const progressInTicks = isVlc ? msToTicks(value) : value; - calculateTrickplayUrl(progressInTicks); - - const progressInSeconds = Math.floor(ticksToSeconds(progressInTicks)); - const hours = Math.floor(progressInSeconds / 3600); - const minutes = Math.floor((progressInSeconds % 3600) / 60); - const seconds = progressInSeconds % 60; - setTime({ hours, minutes, seconds }); - }; - - const handleSliderStart = useCallback(() => { - if (showControls === false) return; - - wasPlayingRef.current = isPlaying; - lastProgressRef.current = progress.value; - - pause(); - isSeeking.value = true; - }, [showControls, isPlaying]); + const progressInSeconds = Math.floor(ticksToSeconds(progressInTicks)); + const hours = Math.floor(progressInSeconds / 3600); + const minutes = Math.floor((progressInSeconds % 3600) / 60); + const seconds = progressInSeconds % 60; + setTime({ hours, minutes, seconds }); + }, 20), // 100ms debounce delay + [] + ); const handleSkipBackward = useCallback(async () => { if (!settings?.rewindSkipTime) return; @@ -326,6 +332,71 @@ export const Controls: React.FC = ({ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light); }, []); + const memoizedRenderBubble = useCallback(() => { + if (!trickPlayUrl || !trickplayInfo) { + return null; + } + const { x, y, url } = trickPlayUrl; + const tileWidth = 150; + const tileHeight = 150 / trickplayInfo.aspectRatio!; + + console.log("time, ", time); + + return ( + + + + + + {`${time.hours > 0 ? `${time.hours}:` : ""}${ + time.minutes < 10 ? `0${time.minutes}` : time.minutes + }:${time.seconds < 10 ? `0${time.seconds}` : time.seconds}`} + + + ); + }, [trickPlayUrl, trickplayInfo, time]); + return ( = ({ containerStyle={{ borderRadius: 100, }} - renderBubble={() => { - if (!trickPlayUrl || !trickplayInfo) { - return null; - } - const { x, y, url } = trickPlayUrl; - const tileWidth = 150; - const tileHeight = 150 / trickplayInfo.aspectRatio!; - return ( - - - - - - {`${time.hours > 0 ? `${time.hours}:` : ""}${ - time.minutes < 10 ? `0${time.minutes}` : time.minutes - }:${ - time.seconds < 10 ? `0${time.seconds}` : time.seconds - }`} - - - ); - }} + renderBubble={() => isSliding && memoizedRenderBubble()} sliderHeight={10} thumbWidth={0} progress={progress} diff --git a/modules/vlc-player/ios/VlcPlayerView.swift b/modules/vlc-player/ios/VlcPlayerView.swift index a5a0835d..f63aff44 100644 --- a/modules/vlc-player/ios/VlcPlayerView.swift +++ b/modules/vlc-player/ios/VlcPlayerView.swift @@ -59,46 +59,37 @@ class VlcPlayerView: ExpoView { // MARK: - Public Methods @objc func play() { - DispatchQueue.main.async { [weak self] in - self?.mediaPlayer?.play() - self?.isPaused = false - print("Play") - } + self.mediaPlayer?.play() + self.isPaused = false + print("Play") } @objc func pause() { - DispatchQueue.main.async { [weak self] in - self?.mediaPlayer?.pause() - self?.isPaused = true - } + self.mediaPlayer?.pause() + self.isPaused = true } @objc func seekTo(_ time: Int32) { - DispatchQueue.main.async { [weak self] in - guard let self = self, let player = self.mediaPlayer else { return } + guard let player = self.mediaPlayer else { return } + + let wasPlaying = player.isPlaying + if wasPlaying { + self.pause() + } + + if let duration = player.media?.length.intValue { + print("Seeking to time: \(time) Video Duration \(duration)") + + // If the specified time is greater than the duration, seek to the end + let seekTime = time > duration ? duration - 1000 : time + player.time = VLCTime(int: seekTime) - let wasPlaying = player.isPlaying if wasPlaying { - self.pause() - } - - if let duration = player.media?.length.intValue { - print("Seeking to time: \(time) Video Duration \(duration)") - - // If the specified time is greater than the duration, seek to the end - let seekTime = time > duration ? duration - 1000 : time - player.time = VLCTime(int: seekTime) - - // Wait for a short moment to ensure the seek has been processed - DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { - if wasPlaying { - self.play() - } - self.updatePlayerState() - } - } else { - print("Error: Unable to retrieve video duration") + self.play() } + self.updatePlayerState() + } else { + print("Error: Unable to retrieve video duration") } } @@ -146,11 +137,6 @@ class VlcPlayerView: ExpoView { print("Debug: Media options: \(mediaOptions)") media.addOptions(mediaOptions) - // Apply subtitle options - let subtitleTrackIndex = source["subtitleTrackIndex"] as? Int ?? -1 - print("Debug: Subtitle track index from source: \(subtitleTrackIndex)") - self.setSubtitleTrack(subtitleTrackIndex) - self.mediaPlayer?.media = media self.hasSource = true @@ -162,9 +148,7 @@ class VlcPlayerView: ExpoView { } @objc func setAudioTrack(_ trackIndex: Int) { - DispatchQueue.main.async { - self.mediaPlayer?.currentAudioTrackIndex = Int32(trackIndex) - } + self.mediaPlayer?.currentAudioTrackIndex = Int32(trackIndex) } @objc func getAudioTracks() -> [[String: Any]]? { @@ -181,29 +165,25 @@ class VlcPlayerView: ExpoView { @objc func setSubtitleTrack(_ trackIndex: Int) { print("Debug: Attempting to set subtitle track to index: \(trackIndex)") - DispatchQueue.main.async { - self.mediaPlayer?.currentVideoSubTitleIndex = Int32(trackIndex) - print( - "Debug: Current subtitle track index after setting: \(self.mediaPlayer?.currentVideoSubTitleIndex ?? -1)" - ) - } + self.mediaPlayer?.currentVideoSubTitleIndex = Int32(trackIndex) + print( + "Debug: Current subtitle track index after setting: \(self.mediaPlayer?.currentVideoSubTitleIndex ?? -1)" + ) } @objc func setSubtitleURL(_ subtitleURL: String, name: String) { - DispatchQueue.main.async { [weak self] in - guard let self = self, let url = URL(string: subtitleURL) else { - print("Error: Invalid subtitle URL") - return - } + guard let url = URL(string: subtitleURL) else { + print("Error: Invalid subtitle URL") + return + } - let result = self.mediaPlayer?.addPlaybackSlave(url, type: .subtitle, enforce: true) - if let result = result { - let internalName = "Track \(self.customSubtitles.count + 1)" - print("Subtitle added with result: \(result) \(internalName)") - self.customSubtitles.append((internalName: internalName, originalName: name)) - } else { - print("Failed to add subtitle") - } + let result = self.mediaPlayer?.addPlaybackSlave(url, type: .subtitle, enforce: true) + if let result = result { + let internalName = "Track \(self.customSubtitles.count + 1)" + print("Subtitle added with result: \(result) \(internalName)") + self.customSubtitles.append((internalName: internalName, originalName: name)) + } else { + print("Failed to add subtitle") } }