doublesymmetry / react-native-track-player

A fully fledged audio module created for music apps. Provides audio playback, external media controls, background mode and more!
https://rntp.dev/
Apache License 2.0
3.31k stars 1.02k forks source link

Audio quality is stuck in mono/low bitrate after iOS recording is triggered at any point during app lifecycle #2016

Closed jamfromouterspace closed 1 year ago

jamfromouterspace commented 1 year ago

Describe the Bug If any other package uses the recording functionality in iOS, it breaks the playback quality of Track Player until restart.

Steps To Reproduce Record something in your app (using expo-av or react-native-audio-recorder-player or react-native-audio-record). Once any recording functionality is triggered, for the rest of the lifecycle of the app the playback quality from track-player is very bad

Code To Reproduce

// normal playback
await TrackPlayer.play(someHighQualityTrack)
await TrackPlayer.pause()
// trigger recording (also works with expo-av )
const recorder = new AudioRecorderPlayer()
await recorder.startRecorder()
await recorder.stopRecorder()
// low quality playback
await TrackPlayer.play(someHighQualityTrack)

Replicable on Example App? Yes

Environment Info: Expo SDK 48 using development client React Native 0.71.8 Track Player version: 2.x, 3.2.0, and 4.0.0-rc04 Real device iOS 16.4.1 / macOS 11.4

How I can Help Note that audio playback from expo-av doesn't have this problem, I wonder if it's just a matter of being able to reset the audio playback settings in iOS programmatically.

I've tried running TrackPlayer.reset() and TrackPlayer.setupPlayer() to reset the playback in some way, but it does nothing.

jamfromouterspace commented 1 year ago

Ok so if I downgrade to 2.1 and call destroy() and setupPlayer() again with iosCategory: IOSCategory.Playback it fixes it.

The problem seems to be that when you start recording in iOS (again, using any package), the iOS Category gets set to PlaybackRecord which causes the low quality playback.

All we actually need is to be able to set the iOS Category after the player is already set up. Then, we wouldnt need to destroy() it because we're only doing that in order to reset the iOS Category.

jamfromouterspace commented 1 year ago

Ok we found a better solution. We installed react-native-sound which exposes Sound.setCategory("Playback"). We can set this anytime – works like a charm.

Still, I think Track Player should allow us to set the AVAudioSessionCategory just like react-native-sound so that we dont need to install another package, and it shouldn't be hard to implement (correct me if I'm wrong – I'm a total noob in swift)

jspizziri commented 1 year ago

This sounds like a feature request to add iosCategory and the like to the updateOptions interface. I'd be open to reviewing a PR if you wanted to submit one.

puckey commented 1 year ago

I think the way to go would be to set the category again every time the app is asked to play a track

puckey commented 1 year ago

@closetothe the following pr will configure the audio session whenever play() is called: https://github.com/doublesymmetry/react-native-track-player/issues/2016 – could you check if this fixes your issues?

puckey commented 1 year ago

Just noticed I forgot to create the actual pr for this – see https://github.com/doublesymmetry/react-native-track-player/pull/2091