just_audio icon indicating copy to clipboard operation
just_audio copied to clipboard

player is not working appropriately in web when try to play an mp3 file from signed url generated by AWS

Open Abo-ghazalla opened this issue 2 years ago • 22 comments

Which API doesn't behave as documented, and how does it misbehave? The error is in play() after user setUrl().

the url is like: var url="https://d2oogf3dio531h.cloudfront.net/65577d97-9969-4043-8bc4-5f6bb973e3a9.mp3?Policy=eyAKICAgIlN0YXRlbWVudCI6IFt7IAogICAgICAiUmVzb3VyY2UiOiJodHRwczovL2Qyb29nZjNkaW81MzFoLmNsb3VkZ291cmNlSXAiOFRpbWUiOjgzNTc5ODN9CiAgICAgIH0gCiAgIH1dIAp9&Signature=Jc1d~yaNIW5C3StRtQe-EZtZhGvAK-JGh1cDF~CrVYBjbJSpz-hmiPjZwGJjKEGaLCaOeFJjIYGE~B7P0dm8PLfjb6eydfebNfdp5OMdrFio2HnGRsjqVcPuCDOKtjezYu3isWtt0AY-Tim6TBYvG9kuG3pPZa5L32zD4aFwPTmmahZko~byCc0ZBQJbKCyG4AcKnevCd2LaGjNGloprw__&Key-Pair-Id=K35S9ERGS425ZB"; Minimal reproduction project

To Reproduce (i.e. user steps, not code)

Error messages

Error: (4) Failed to load URL
    at Object.throw_ [as throw] (http://localhost:50415/dart_sdk.js:5391:11)
    at just_audio.AudioPlayer.new._load (http://localhost:50415/packages/just_audio/just_audio.dart.lib.js:828:25)
    at _load.throw (<anonymous>)
    at http://localhost:50415/dart_sdk.js:42999:38
    at _RootZone.runBinary (http://localhost:50415/dart_sdk.js:42854:58)
    at _FutureListener.thenAwait.handleError (http://localhost:50415/dart_sdk.js:37430:33)
    at handleError (http://localhost:50415/dart_sdk.js:38036:51)
    at Function._propagateToListeners (http://localhost:50415/dart_sdk.js:38062:17)
    at _Future.new.[_completeError] (http://localhost:50415/dart_sdk.js:37908:23)
    at async._AsyncCallbackEntry.new.callback (http://localhost:50415/dart_sdk.js:37947:31)
    at Object._microtaskLoop (http://localhost:50415/dart_sdk.js:43153:13)
    at _startMicrotaskLoop (http://localhost:50415/dart_sdk.js:43159:13)
    at http://localhost:50415/dart_sdk.js:38289:9

Expected behavior A clear and concise description of what you expected to happen.

Screenshots

Desktop (please complete the following information):

Smartphone (please complete the following information):

Flutter SDK version [✓] Flutter (Channel stable, 2.10.3, on macOS 12.0.1 21A559 darwin-x64, locale en-AE) [✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0) [✓] Xcode - develop for iOS and macOS (Xcode 13.1) [✓] Chrome - develop for the web [✓] Android Studio (version 2020.3) [✓] VS Code (version 1.65.2) [✓] Connected device (3 available) [✓] HTTP Host Availability Additional context Add any other context about the problem here.

Abo-ghazalla avatar Mar 22 '22 13:03 Abo-ghazalla

When I open that URL in my web browser it also gives an error, so I would not expect to work through this plugin either.

ryanheise avatar Mar 22 '22 13:03 ryanheise

the signed url remains valid for only few seconds to protect our mp3 files. this works fine in Android and IOS but the error is in the web

Abo-ghazalla avatar Mar 22 '22 14:03 Abo-ghazalla

I can't test it if I only have a few seconds to access it. Why don't you supply a test URL that has a longer expiration date?

ryanheise avatar Mar 22 '22 14:03 ryanheise

have you found solution?

paprikaparty33 avatar Dec 19 '22 07:12 paprikaparty33

no, I didn't complete this module in the web app

On Mon, Dec 19, 2022 at 9:45 AM paprikaparty33 @.***> wrote:

have you found solution?

— Reply to this email directly, view it on GitHub https://github.com/ryanheise/just_audio/issues/688#issuecomment-1357222887, or unsubscribe https://github.com/notifications/unsubscribe-auth/AK6CYRZTCTDKJID3NJKCEX3WOAHCJANCNFSM5RK66Y6Q . You are receiving this because you authored the thread.Message ID: @.***>

Abo-ghazalla avatar Dec 19 '22 08:12 Abo-ghazalla

This is the real problem. I have same with aws, but not only aws itself, but any S3-like storage.

what does code 4 means atleast? @ryanheise

BitBlueDevStudio avatar Apr 11 '23 21:04 BitBlueDevStudio

just_audio_web just passes on the error as is from the platform, in this case, from the browser, so you'll have to consult the browser documentation or Javascript documentation for what that error code means. The most popular cause of errors is incorrect server headers.

ryanheise avatar Apr 12 '23 02:04 ryanheise

@ryanheise is there any caching behind setUrl? I see this error not for the first time I download some file, but after a while, when I trying to download it again using same link (because my backend generates different presigned urls, but for app it always the same url for same file

BitBlueDevStudio avatar Apr 13 '23 11:04 BitBlueDevStudio

There shouldn't be any caching for setUrl, but if you create an audio source instance e.g. via AudioSource.uri() and you pass that same instance into setAudioSource again, then yes there will be a sort of caching going on because you are in fact using the same instance. Feel free to take a look through the source code to understand what happens in your scenario, as it's all pure Dart.

ryanheise avatar Apr 13 '23 11:04 ryanheise

The problem is that I always destroy player and always create new one

BitBlueDevStudio avatar Apr 13 '23 21:04 BitBlueDevStudio

Can you elaborate on what way that is the problem? Do you mean that it works without recreating the player?

ryanheise avatar Apr 13 '23 23:04 ryanheise

No, I mean that error described above occurs after some time, even if I create new AudioPlayer instance everytime. So its like: 1 get presigned url from server; 2 Create audioplayer; 3 use setUrl; 4 see it works fine; 5 destroy audioplayer; 6 repeat steps 1-5 after some time and few times; 7 get error on "setUrl" step, and after you get it once - you will get it all the time, even with other urls, which wasnt used before;

Oh, right now I noticed, that you mean AudioSource instance. But I do not use AudioSource, I simply use player.setUrl(urlString);

Also about reading code, when it came for web, I do not understand it very well, seems that load function (where error occurs) on web package, call some native code (js library?), and I do not know how to find this code, and I still do not understand what code 4 means in error.

BitBlueDevStudio avatar Apr 14 '23 01:04 BitBlueDevStudio

What is the expiry date for your signed URL? Does it expire during the timespan we're talking about here?

ryanheise avatar Apr 14 '23 01:04 ryanheise

@ryanheise Yes, it expires in 700 seconds.

For anyone who want to solve this problem - just add updating url argument. For example https://download.mp3?version=1

@Abo-ghazalla Just increment version before any request, and you will not have any problem with (4) Failed to load URL. At least it worked for me.

BitBlueDevStudio avatar Apr 20 '23 12:04 BitBlueDevStudio

If the URL expires in the span you're talking about, why would appending a version query parameter cause it to "un"-expire?

ryanheise avatar Apr 20 '23 12:04 ryanheise

In my case, setUrl uses my server url which looks like https://server.com/download?file=file

But inside server just create presigned url and return 301 redirect.

And there is no problem in expiration, because new presigned url generates every time for new request

BitBlueDevStudio avatar Apr 22 '23 16:04 BitBlueDevStudio

Anyone found any reliable way or workaround? I have tried using url argument update but that didn't work. And once this error happens, it just keeps on happening even for all valid and accessible urls. My .mp3 files are also on AWS.

saintjab avatar Sep 16 '23 15:09 saintjab

When you tried a URL argument update, I think there were other parts to that workaround besides just the argument, including a server redirect and so on.

ryanheise avatar Sep 17 '23 01:09 ryanheise

Hmm, sounds like I may have to find another solution/workaround. :(

saintjab avatar Sep 17 '23 21:09 saintjab

One other thing you can try is to download the file using http, and then play it in memory using a base64 URL. To avoid locking up the UI while encoding into base64, you could either do the encoding in a web worker or you could do it server side and just download the base64 encoded data to the web app.

ryanheise avatar Sep 18 '23 01:09 ryanheise

Awesome, thanks. That can work, can get the file as base64 directly. Do I need to do any more conversion to use? I am trying to learn more about StreamAudioSource so I can use that. Do I need base64 into other format/encode to use StreamAudioSource?

saintjab avatar Sep 18 '23 07:09 saintjab

It will be more efficient to bypass StreamAudioSource if you already have the base64 encoded data. You would do this by constructing a data URL:

https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs

ryanheise avatar Sep 18 '23 08:09 ryanheise