bluefireteam / audioplayers

A Flutter package to play multiple audio files simultaneously (Android/iOS/web/Linux/Windows/macOS)
https://pub.dartlang.org/packages/audioplayers
MIT License
2.01k stars 845 forks source link

[web] Errors on setSource and resume when playing audio stream #1249

Closed masus04 closed 2 years ago

masus04 commented 2 years ago

Checklist

Errors are thrown when playing, pausing or resuming audio playback on Flutter web application.

Current bug behaviour

When loading an audio stream source either using audioplayer.setSource(source) or audioplayer.play(source), the following error is thrown:

Error: Unsupported operation: Infinity
    at Object.throw_ [as throw] (http://localhost:8080/dart_sdk.js:5080:11)
    at [dartx.round] (http://localhost:8080/dart_sdk.js:17915:17)
    at toDuration (http://localhost:8080/packages/audioplayers_web/wrapped_player.dart.lib.js:149:112)
    at http://localhost:8080/packages/audioplayers_web/wrapped_player.dart.lib.js:157:59
    at Object._checkAndCall (http://localhost:8080/dart_sdk.js:5279:16)
    at Object.dcall (http://localhost:8080/dart_sdk.js:5284:17)
    at Audio.<anonymous> (http://localhost:8080/dart_sdk.js:109003:100)

The audio is played correctly to the end however.

When pausing or stopping and then resuming the audioplayer however, the following error is thrown and the component falls into an unrecoverable state:

Error: NotSupportedError: Failed to load because no supported source was found.

    at Object.createErrorWithStack (http://localhost:8080/dart_sdk.js:5093:12)
    at Error._throw (http://localhost:8080/dart_sdk.js:20399:18)
    at Error.throwWithStackTrace (http://localhost:8080/dart_sdk.js:20396:18)
    at async._AsyncCallbackEntry.new.callback (http://localhost:8080/dart_sdk.js:40921:18)
    at Object._microtaskLoop (http://localhost:8080/dart_sdk.js:40778:13)
    at _startMicrotaskLoop (http://localhost:8080/dart_sdk.js:40784:13)
    at http://localhost:8080/dart_sdk.js:36261:9

Even adding a new source does not return the player to a working state after this.

Expected behaviour

Steps to reproduce

Code sample **Dart code:** Performs the steps described ```dart void main() { final fileType = "audio/mpeg"; FilePickerResult? result = await FilePicker.platform.pickFiles(type: fileType); final response = await apiClient.postMedia( path: mediaPath, field: "file", fileType: fileType, mediaFile: file, ); final audioPlayer = AudioPlayer(); final audioSource = UrlSource("http://localhost:5000/api/audio"); audioPlayer.setSource(audioSource); audioPlayer.resume(); audioPlayer.pause(); audioPlayer.resume(); } ``` **Backend code:** Provides API that stores an audio file in memory and returns it on a GET request. ```python from http import HTTPStatus from typing import Dict import uvicorn from fastapi import FastAPI, UploadFile from pydantic import BaseModel from starlette.responses import StreamingResponse app = FastAPI() file_db: Dict[str, UploadFile] = {} audio_route = "/api/audio" class ExampleMedia(BaseModel): filename: str content_type: str @app.post( path=audio_route, status_code=HTTPStatus.ACCEPTED, response_model=ExampleMedia, ) async def post_media_file_async(file: UploadFile) -> ExampleMedia: """ Receives a media file and stores it in the backend in order to make it available using a GET request. This example showcases how a long-running background task can be handled asynchronously. It is also required to display audio and video files from a web source. :returns: HttpStatus.Accepted = 202 if the task was accepted correctly """ # TODO: Verify that file type &/ codec are compatible with your application file_db[file.filename] = file print(f"Processing file named {file.filename}") # TODO: Perform async processing here return ExampleMedia(filename=file.filename, content_type=file.content_type) @app.get( path=f"{audio_route}/{{file_name}}", ) async def get_media_file_async(file_name: str): file = file_db[file_name] def file_iterator(): yield from file.file # Make sure the media_type is set correctly, or else the browser will not be able to handle the response correctly return StreamingResponse(content=file_iterator(), media_type=file.content_type) if __name__ == '__main__': uvicorn.run(app, host="0.0.0.0", port=5000) ```

Flutter doctor:

[✓] Flutter (Channel stable, 3.0.5, on Ubuntu 22.04.1 LTS 5.15.0-46-generic, locale en_US.UTF-8)
    • Flutter version 3.0.5 at /home/masus/snap/flutter/common/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision f1875d570e (6 weeks ago), 2022-07-13 11:24:16 -0700
    • Engine revision e85ea0e79c
    • Dart version 2.17.6
    • DevTools version 2.12.2

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0-rc1)
    • Android SDK at /home/masus/Android/Sdk
    • Platform android-33, build-tools 33.0.0-rc1
    • Java binary at: /snap/android-studio/123/android-studio/jre/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
    • All Android licenses accepted.

[✓] Chrome - develop for the web
    • Chrome at google-chrome

[✓] Linux toolchain - develop for Linux desktop
    • clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
    • cmake version 3.10.2
    • ninja version 1.8.2
    • pkg-config version 0.29.1

[✓] Android Studio (version 2021.2)
    • Android Studio at /snap/android-studio/123/android-studio
    • Flutter plugin version 69.0.2
    • Dart plugin version 212.5744
    • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)

[✓] VS Code
    • VS Code at /snap/code/current
    • Flutter extension can be installed from:
      🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[✓] Connected device (2 available)
    • Linux (desktop) • linux  • linux-x64      • Ubuntu 22.04.1 LTS 5.15.0-46-generic
    • Chrome (web)    • chrome • web-javascript • Google Chrome 104.0.5112.79

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!

Audio Files/URLs/Sources

The library's sample file can be downloaded and used for this example:

Environment information

Platform 1:

Gustl22 commented 2 years ago

@masus04 can you test with current main in pubspec.yaml?

dependencies:
  audioplayers:
    git: 
      url: https://github.com/bluefireteam/audioplayers.git
      path: 'packages/audioplayers'

This could be solved by #1192

masus04 commented 2 years ago

It definitely seems to be related to the same issue but it does not seem to fix it..

masus04 commented 2 years ago

When I rebuild using the pubspec.yaml snippet you provided above, the code fix is still not present in my Dart Packges dir. Is it possible the change has not yet been fully merged to the parent repository?

masus04 commented 2 years ago

If I manually add the changed line to the dependency files, the Unsupported operation: Infinity error is no longer thrown, but I still can't pause and resume the audio playback.

Gustl22 commented 2 years ago

Which source do you play? Is it a live stream? I think the link for the sample was not updated in the issue description.

I'm pretty sure it was merged in the main branch. Maybe you should do a flutter clean before flutter pub get to get the according version.

masus04 commented 2 years ago

I cleaned the dependencies multiple times and the same thing happens on a full docker build, so that can't be the reason.

The source is a FastApi StreamSource

Gustl22 commented 2 years ago

Oh I forgot, you also have to override the web implementation of course, because it references the released ones in audioplayers:

dependency_overrides: 
  audioplayers_web:
    git: 
      url: https://github.com/bluefireteam/audioplayers.git
      path: 'packages/audioplayers_web'

The source is a FastApi StreamSource

Ok, but which codec? .mp3, .m3u8, etc...

masus04 commented 2 years ago

Alright, overriding the web dependency did the trick for the Infinity issue :+1:

As for the source: I upload the source dynamically in my example, so I tried both mp3 and the example coin.wav file from the docs.

It seems the two issues were not directly related as the following error still appears when pausing and resuming an audio playback:

Error: NotSupportedError: Failed to load because no supported source was found.

    at Object.createErrorWithStack (http://localhost:8080/dart_sdk.js:5093:12)
    at Error._throw (http://localhost:8080/dart_sdk.js:20399:18)
    at Error.throwWithStackTrace (http://localhost:8080/dart_sdk.js:20396:18)
    at async._AsyncCallbackEntry.new.callback (http://localhost:8080/dart_sdk.js:40921:18)
    at Object._microtaskLoop (http://localhost:8080/dart_sdk.js:40778:13)
    at _startMicrotaskLoop (http://localhost:8080/dart_sdk.js:40784:13)
    at http://localhost:8080/dart_sdk.js:36261:9

Should I close this issue and open a new one to make it more clear?

Gustl22 commented 2 years ago

Should I close this issue and open a new one to make it more clear?

Yes, that would be nice. Also it would help a lot to have a project as example, so we can reproduce the behavior. The best thing would be to clone and modify the example, so that it reproduces your behavior. Or just simply create a quick project via flutter create my_issue_project

masus04 commented 2 years ago

I tried that but had some issues recreating it.. I'll give it another try :+1:

masus04 commented 2 years ago

Opened separate issue for follow up: https://github.com/bluefireteam/audioplayers/pull/1247