react-native-track-player
react-native-track-player copied to clipboard
[Feature Request] Progress Updates Lag During Buffering
Hi there, I'm trying to implement an interface like Apple Podcasts (when you move the slider, the time changes in real time). When I change the position on the slider, TrackPlayer.seekTo(val) does not work instantly, because of this the slider twitches. I am using the @react-native-community/slider library. I tried adjusting the onSlidingStart and onSlidingComplete, and setting setTimeout, it improves the situation, but the twitching still remains. All examples available online also have this problem. Replacing the slider library doesn't solve the problem either. Could you please suggest how this problem is solved? Or maybe there is an example of a correct implementation with a slider? Thanks a lot!
Tested on physical iphone 13 pro max, ios 16.
<Slider value={progress.position} minimumValue={0} maximumValue={progress.duration} minimumTrackTintColor={palette.ACTION_PRIMARY} maximumTrackTintColor={palette.BORD} onSlidingComplete={async (val: number) => { await TrackPlayer.seekTo(value) }} />
Version: "react-native-track-player": "^2.1.3",
System: OS: macOS 12.4 CPU: (8) arm64 Apple M1 Memory: 115.11 MB / 16.00 GB Shell: 5.8.1 - /bin/zsh Binaries: Node: 18.0.0 - /opt/homebrew/bin/node Yarn: 1.22.17 - /opt/homebrew/bin/yarn npm: 8.6.0 - /opt/homebrew/bin/npm Watchman: 2022.03.21.00 - /opt/homebrew/bin/watchman Managers: CocoaPods: 1.11.3 - /usr/local/bin/pod SDKs: iOS SDK: Not Found Android SDK: Not Found IDEs: Android Studio: 2020.3 AI-203.7717.56.2031.7678000 Xcode: /undefined - /usr/bin/xcodebuild Languages: Java: 11.0.16 - /usr/bin/javac npmPackages: @react-native-community/cli: Not Found react: 17.0.2 => 17.0.2 react-native: 0.68.1 => 0.68.1 react-native-macos: Not Found npmGlobalPackages: react-native: Not Found
update -> Answer by gavrichards from the discord. But I didn't manage to solve the bug: "Hey, I have the same thing in my app. I have a boolean state isDragging, which I use to set the value of the slider, like this: const showPosition = isDragging ? draggingPosition : trackPosition;
So if it's dragging, the slider shows the dragging position, otherwise it shows the actual track position. onSlidingStart, I call setIsDragging(true) and set the dragging position. onSlidingComplete, I seek to the new position, and then set a 1 second timeout before calling setIsDragging(false). This is the trick. It keeps the slider position in the dragged position for 1 second until the library then reports the correct new track position."
@MrNapcae , I've not seen this issue before, and it doesn't seem to exist in the example project. When I run the example project on an iPhone SE Gen 2 with iOS 15.5 , the progress slider is very smooth.
@MrNapcae, я раньше не встречал эту проблему, и похоже, что ее нет в примере проекта. Когда я запускаю пример проекта на iPhone SE Gen 2 с iOS 15.5, ползунок прогресса работает очень плавно.
Try drag and drop with method TrackPlayer.seekTo(val). When moving quickly, a bug will be noticeable.
The guys in the discord faced this problem, but their solution did not help me. It is based on setTimeOut.
https://user-images.githubusercontent.com/1452066/186220652-990b2cbb-80dc-45d7-943c-e0573913bdf0.MOV
Here's a recording of me scrubbing quickly. I see no issues.
If you're able to send me a consistent reproduction of this based off of the example app, I'll take another look at it.
@jspizziri > If you're able to send me a consistent reproduction of this based off of the example app, I'll take another look at it.
the only change I made was to put in a longer video from the internet, duration: 1066 sec https://user-images.githubusercontent.com/42024544/186224425-de08d857-0568-44ef-ac48-9b4f979f441a.MP4
@MrNapcae what you're seeing looks like its the result of your audio file buffering. I don't think it has anything to do with the .seekTo
being slow like you initially thought. When you scrub to the desired position it takes a few MS to actually buffer the file at that position before playback begins. My recommendation would be to observe the playback state, and if it's loading/buffering pausing the update of your progress bar slider.
Because the progress events are asynchronous between the native code and JS we can't guarantee a progress event won't show up during buffering.
@dcvz it's possible we could solve something like this in the useProgress
hook?
@jspizziri Is it possible to download the full audio before playing it in order to avoid this?
@MrNapcae yes, you can download and play offline. I'm not 100% sure that will solve your problem, buffering the file from disk should be faster than buffering it from network, it just depends on the speed.
@jspizziri then maybe you can find out the status that buffering is in progress?
@MrNapcae I'm not sure what you mean by that.
@jspizziri Is there a way to receive a status that audio file is being loaded and it’s not available for playing yet?
@MrNapcae yes, this is what I was mentioning here. Please read the documentation for PlaybackState
and usePlaybackState
.
@jspizziri
Statuses other than none / ready / playing / paused do not come
export const PlayPauseButton: React.FC = () => { const state = usePlaybackState(); const isPlaying = state === State.Playing; const isLoading = state === State.Connecting || state === State.Buffering; console.log({state})
LOG Running "example" with {"rootTag":1,"initialProps":{}} LOG {"state": "none"} LOG {"state": "none"} LOG {"state": "connecting"} LOG {"state": "connecting"} LOG {"state": "connecting"} LOG {"state": "ready"} LOG {"state": "ready"} LOG {"state": "playing"} LOG {"state": "playing"} LOG {"state": "paused"} LOG {"state": "paused"} LOG {"state": "playing"} LOG {"state": "playing"} LOG {"state": "paused"} LOG {"state": "paused"} LOG {"state": "playing"} LOG {"state": "playing"} LOG {"state": "paused"} LOG {"state": "paused"} LOG {"state": "paused"} LOG {"state": "paused"}
@MrNapcae I don't want to be rude. But there's no way I'm going to read through that massive text dump and try and interpret what you're asking me.
@MrNapcae I don't want to be rude. But there's no way I'm going to read through that massive text dump and try and interpret what you're asking me.
sorry, updated
Hi @jspizziri I have the same problem when I go from pause to play the status of the player changes from loading/buffering playing/ready/paused
only on iOS on Android no problems and playing a stream
url: BASE_URL_STREAM,
title: 'Radio Gospel',
artist: 'Radio Gospel',
contentType: 'audio/mpeg',
isLiveStream: true,
```
Hi , i have the same issue, i never get State.Buffering, am i missing something? It works with TS v2.1.3 but with any higher versions than that it doesnt.
@mekaVR @MrNapcae @izyspania
Please try the nightly build which we believe resolves the buffering not being emitted issue.
See here for more detail
https://github.com/doublesymmetry/react-native-track-player/issues/1720#issuecomment-1246485024
To restate the ask in this issue:
With long content, or content that takes a long time buffering, progress updates can seem a bit jumpy. This is likely because after scrubbing but before the new position has been buffered, another progress event is emitted with an old position.
We might be able to check for a buffering state in the useProgess hook before we emit events
@jspizziri Sadly it does exactly the same , no Buffering state. "version": "3.1.0-7b247404c2b54df0550379277949a1cab5ddf47c",
@izyspania we'll deal with the bug on the dedicated bug ticket. Let's keep this discussion moving forward just to the feature request.