Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IOS] Seek to right after playback changed doesn't work #1359

Closed
GrimDev opened this issue Dec 30, 2021 · 12 comments
Closed

[IOS] Seek to right after playback changed doesn't work #1359

GrimDev opened this issue Dec 30, 2021 · 12 comments
Labels

Comments

@GrimDev
Copy link

GrimDev commented Dec 30, 2021

Describe the bug
Hi there 👋.

In the eventListener PlaybackTrackChanged, calling TrackPlayer.seekTo() on IOS does nothing while it works well on Android.
I tried some workarounds but failed.

Note that I have a slider component that use seekTo and works well, the issue only appears when I try to seek to right after adding the track (or playing) even if, of course, I use await.

NB: I noticed that iOS & Android track players doesn't do things (events) in the same order, the available events are also different. Having those infos inside the TrackPlayer documentation would be great.

Context
My app plays audio books. When a user pauses the audio or quits the app, I save the position of the current track in a database.
When he comes back later to the app, he is able to "continue" an audio book, restarting at the position he stops.
To make this possible, I need to seek to the last known position right after adding the track, ideally before it starts at the 0 position.

What I made works well on Android, but doesn't have any effect on iOS.

To Reproduce
Steps to reproduce the behavior:

  • Init a TrackPlayer
  • Add a track
  • Play the track
  • Seek to a position inside the PlaybackTrackChanged eventListener

I also tried :

  • Init a TrackPlayer
  • Add a track
  • Seek to a position
  • Play the track

And :

  • Init a TrackPlayer
  • Add a track
  • Play the track
  • Seek to a position

Environment

react-native info
System:
    OS: macOS 12.0.1
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    Memory: 54.09 MB / 16.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 14.18.1 - /usr/local/bin/node
    Yarn: 1.22.10 - /usr/local/bin/yarn
    npm: 8.0.0 - /usr/local/bin/npm
    Watchman: 2021.09.27.00 - /usr/local/bin/watchman
  Managers:
    CocoaPods: 1.11.2 - /usr/local/bin/pod
  SDKs:
    iOS SDK:
      Platforms: DriverKit 21.0.1, iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0
    Android SDK:
      API Levels: 29, 30
      Build Tools: 29.0.2, 30.0.2, 30.0.3
      System Images: android-24 | Google APIs Intel x86 Atom, android-27 | Google APIs Intel x86 Atom, android-29 | Google APIs Intel x86 Atom, android-30 | Google APIs Intel x86 Atom
      Android NDK: 21.4.7075529
  IDEs:
    Android Studio: 2020.3 AI-203.7717.56.2031.7678000
    Xcode: 13.1/13A1030d - /usr/bin/xcodebuild
  Languages:
    Java: 15.0.2 - /usr/bin/javac
  npmPackages:
    @react-native-community/cli: Not Found
    react: 17.0.2 => 17.0.2
    react-native: 0.66.4 => 0.66.4
    react-native-macos: Not Found
  npmGlobalPackages:
    *react-native*: Not Found

What react-native-track-player version are you using?
2.1.2

Are you testing on a real device or in the simulator? Which OS version are you running?
Real iPhone SE v15.1

Code

// Expecting initialized TrackPlayer
const track = {}; // Real track infos object

/* Experiment 1 */
TrackPlayer.addEventListener(Event.PlaybackTrackChanged, async (/* params */) => {
  await TrackPlayer.seekTo(/* any valid position */);
})
await TrackPlayer.add(track);
await TrackPlayer.play();

/* Experiment 2 */
await TrackPlayer.add(track);
await TrackPlayer.seekTo(/* any valid position */);
await TrackPlayer.play();

/* Experiment 3 */
await TrackPlayer.add(track);
await TrackPlayer.play();
await TrackPlayer.seekTo(/* any valid position */);
@praisedavid787
Copy link
Contributor

@GrimDev same issue here man. Works perfectly on android but not on iOS. I hope we can get a fix very soon.

@KochMario
Copy link

KochMario commented Jan 6, 2022

I have some weird position inconsistencies on iOS as well. On Android, everything works perfectly fine.
I think my issues might be related to the ones described here. For me seekTo does work, but seems that there's still some internal state left, which overwrites my changes.
E.g. I play a track and stop at 125s, then I reset the player, add the same track to the queue, seekTo the last known position of 125s and play the track, which results in the position from useProgress() being momentarily at 125s (the correct value), but immediately afterward it jumps to some other value in the past, e.g. sth like 119 and starts playing from there.

This is an example log dump:

 LOG  Updated position =>  472.434640026
 LOG  Updated position =>  473.426710043
 LOG  ⏯ TrackPlayer: stop
 LOG  PlaybackState . {"state": "paused", "type": "playback-state"}
 LOG  PlaybackState . {"state": "idle", "type": "playback-state"}
 LOG  Updated position =>  0
 LOG  ⏯ TrackPlayer.reset()
 LOG  ⏯ TrackPlayer.add()
 LOG  ⏯ TrackPlayer.seekTo last known position =>  473.426710043
 LOG  ⏯ TrackPlayer.play()
 LOG  PlaybackState . {"state": "loading", "type": "playback-state"}
 LOG  PlaybackState . {"state": "ready", "type": "playback-state"}
 LOG  PlaybackState . {"state": "buffering", "type": "playback-state"}
 LOG  PlaybackState . {"state": "playing", "type": "playback-state"}
 LOG  Updated position =>  465.637149167
 LOG  Updated position =>  465.898198667
 LOG  Updated position =>  466.206418292
 LOG  Updated position =>  466.447903001
 LOG  Updated position =>  467.842759342
 LOG  Updated position =>  468.851415458
 LOG  Updated position =>  469.910461718
 LOG  Updated position =>  470.914910175
 LOG  ⏯ TrackPlayer: stop
 LOG  PlaybackState . {"state": "paused", "type": "playback-state"}
 LOG  PlaybackState . {"state": "idle", "type": "playback-state"}
 LOG  Updated position =>  0
 LOG  ⏯ TrackPlayer.reset()
 LOG  ⏯ TrackPlayer.add()
 LOG  ⏯ TrackPlayer.seekTo last known position =>  470.914910175
 LOG  ⏯ TrackPlayer.play()
 LOG  PlaybackState . {"state": "loading", "type": "playback-state"}
 LOG  PlaybackState . {"state": "ready", "type": "playback-state"}
 LOG  PlaybackState . {"state": "buffering", "type": "playback-state"}
 LOG  PlaybackState . {"state": "playing", "type": "playback-state"}
 LOG  Updated position =>  466.018267625
 LOG  Updated position =>  466.275603584
 LOG  Updated position =>  466.676822668
 LOG  Updated position =>  467.931590205
 LOG  ⏯ TrackPlayer: stop

@GrimDev just like in your case - using seekTo with a slider component works absolutely fine.

@rajivtiwary-cm
Copy link

Facing the same issue @GrimDev. Did you find any solution?

@KochMario
Copy link

Btw I'd be happy to provide more information/logs if needed :)

@GrimDev
Copy link
Author

GrimDev commented Jan 23, 2022

Facing the same issue @GrimDev. Did you find any solution?

Nope @rajivtiwary-cm, not really my highest priority now but still waiting for a workaround

@martinmidtsund
Copy link
Contributor

I haven't tried this solution for iOS myself yet, but others are saying that it works: #387 (comment)

@KochMario
Copy link

@martinmidtsund I've tried the patch suggested in the referenced issue, unfortunately, this didn't change anything for me.

However, I can provide further information for this issue.

I've now verified that seekTo works perfectly fine when the audio file in question is downloaded and played from a local file.
The issue described above only occurs when playing an HLS stream. And it seems that the TrackPlayer then most often jumps to the position which was last manually sought to, i.e. moving the slider to a specific point and updating with TrackPlayer.seekTo()

@martinmidtsund
Copy link
Contributor

@KochMario Ok, I am trying to implement this functionality that @GrimDev is describing (starting on previously saved position) and indeed having troubles with seekTo right after playing a new track. I tried hacking it with setting volume to 0 and seeking in interval until new position is verified, which works, but is not optimal. But with the given patch, it seems to work fine on iOS. Have not tested and verified that seekTo works fine on Android.

I am not seeing any different behaviour on local files vs online files, and these are .mp3 files.

This is perhaps the same issue as #713 will fix?

@jspizziri
Copy link
Collaborator

jspizziri commented Feb 23, 2022

So it's looking like this issue is going to need to be solved in order to complete this PR.

With that said, I've been doing some investigation with @dcvz on what's causing the problem. It seems that it is related to the SwiftAudioEx project. Specifically, the loading of a new track is done asynchronously but seek is executed synchronously. If a seek is called after a skip but before the track loading is complete, then the resetting will occur.

Here's a PR that should address the issue.

@jspizziri
Copy link
Collaborator

The fix to SwiftAudioEx has been merged. I have the fix for this library in this commit packaged up with this PR.

So once SwiftAudioEx@0.14.7 gets published and the above PR is merged and released this issue should be resolved.

@martinmidtsund
Copy link
Contributor

Great work @jspizziri and @dcvz 🙏

jspizziri added a commit to 5-stones/react-native-track-player that referenced this issue Feb 24, 2022
@jspizziri jspizziri mentioned this issue Feb 24, 2022
dcvz pushed a commit that referenced this issue Feb 24, 2022
* chore(example): update the example project dependencies

* docs(example): add some general documentation on working with the example app

* chore(ios): upgrade the SwiftAudioEx library which fixes an issue with seek

#1359
@jspizziri jspizziri mentioned this issue Feb 24, 2022
@jspizziri
Copy link
Collaborator

The above MR containing this fix landed in https://github.com/DoubleSymmetry/react-native-track-player/releases/tag/v2.2.0-rc1

@dcvz I feel like this issue can be safely closed for now.

@dcvz dcvz closed this as completed Feb 24, 2022
hlieb53 added a commit to hlieb53/react-native-track-player that referenced this issue Nov 9, 2023
* chore(example): update the example project dependencies

* docs(example): add some general documentation on working with the example app

* chore(ios): upgrade the SwiftAudioEx library which fixes an issue with seek

doublesymmetry/react-native-track-player#1359
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants