audioplayers
audioplayers copied to clipboard
AVPlayerItem.Status.failed on setSourceUrl, null)
Checklist
- [X] I read the troubleshooting guide before raising this issue
- [X] I made sure that the issue I am raising doesn't already exist
Current bug behaviour
UrlSource(url: https://thonn.mthana.shop/static/91a3c69bef6a9383e01df5e38e7db720.mp3), PlatformException(DarwinAudioError, Failed to set source. For troubleshooting, see https://github.com/bluefireteam/audioplayers/blob/main/troubleshooting.md, AVPlayerItem.Status.failed on setSourceUrl, null)<…> [VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(DarwinAudioError, Failed to set source. For troubleshooting, see https://github.com/bluefireteam/audioplayers/blob/main/troubleshooting.md, AVPlayerItem.Status.failed on setSourceUrl, null) [VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(DarwinAudioError, Failed to set source. For troubleshooting, see https://github.com/bluefireteam/audioplayers/blob/main/troubleshooting.md, AVPlayerItem.Status.failed on setSourceUrl, null) [VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(DarwinAudioError, Failed to set source. For troubleshooting, see https://github.com/bluefireteam/audioplayers/blob/main/troubleshooting.md, AVPlayerItem.Status.failed on setSourceUrl, null)
Expected behaviour
ios 17.0 iPhone 15 xcode 14.0 Flutter 3.1.5
AudioPlayers Version audioplayers: ^5.2.0
Steps to reproduce
- Execute
flutter run
on the code sample - ...
- ...
Code sample
Code sample
void main() {
}
Affected platforms
iOS
Platform details
IOS 17.0
AudioPlayers Version
5.2.0
Build mode
No response
Audio Files/URLs/Sources
No response
Screenshots
No response
Logs
my relevant logs
Full Logs
my full logs or a link to a gist
Flutter doctor:
Output of: flutter doctor -v
Related issues / more information
No response
Working on PR
no way
Fixed it by encoding the url before passing it to the player
final encodedURL = Uri.encodeFull(url);
await player.play(UrlSource(encodedURL));
Maybe the encoding in https://github.com/bluefireteam/audioplayers/blob/audioplayers-v5.2.0/packages/audioplayers/lib/src/uri_ext.dart has to be fixed. Thanks to @cice for debugging this
Fixed it by encoding the url before passing it to the player
final encodedURL = Uri.encodeFull(url); await player.play(UrlSource(encodedURL));
Maybe the encoding in
audioplayers-v5.2.0
/packages/audioplayers/lib/src/uri_ext.dart has to be fixed. Thanks to @cice for debugging this
to give some context:
it took us quite a bit of debugging to figure this out. first of all we had to dig deep into the swift/ios part of the player to get some more details on the error (imho the completeError call back should pass on some more details to flutter about the underlying error). inspecting the playerItem on this level revealed an Error containing ultimately the hint "400 Bad Request". Which was strange, because the URL itself worked fine (in any browser/curl/whatever).
Upon inspecting the URL down there, we could see that this was not the same URL as we passed in. The thing is, we use Google Storage with signed URLs. The signature is URL-encoded Base64 as a query param. This param gets mangled by audioplayers
encodeOnce
thingy (see https://github.com/bluefireteam/audioplayers/blob/01193785508abd717b060875cd79eba044910d86/packages/audioplayers/lib/src/uri_ext.dart#L2).
I am not sure what was intended to solve here, but the net effect is, that this de- and re-encoding messes up URLs that have encoded query params.
Thus our workaround to encode the entire URL once more, so that decodeFull
withing encodeOnce
effectively does the exact reverse, and the player gets a proper and working URL.
So as a workaround for anyone experiencing something similar is pretty straightforward, but imho the encodeOnce
method should be fixed.
@tiloman, see https://github.com/bluefireteam/audioplayers/issues/1669. Reading from the issue description and url, this problem has nothing to do with encoding.
me to.
The error seen in sentry background is on ios
I had to switch from
player.setSourceUrl()
--> player.setSourceDeviceFile()
Seeing as I am playing from a recorded file.