8

I tried reading through the project readme and issues on Github to see if it was a possibility to play two or more audio files simultaneously using the just_audio and audio_service plugins for Flutter. Has anyone achieved something similar using these plugins or similar ones? I currently use these plugins in production so it'd be preferable to stick with them to add the desired functionality to the app.

Any help would be greatly appreciated, thanks!

Ryan Heise
  • 2,273
  • 5
  • 14

1 Answers1

9

In just_audio, you can create two instances of AudioPlayer and set them to play different audio sources. e.g.

final player1 = AudioPlayer();
final player2 = AudioPlayer();

await player1.setUrl(url1);
await player2.setUrl(url2);
...
player1.play(); // don't await
player2.play(); // don't await

If you await each play request, it would not start playing the second one until after waiting for the first one to finish playing. So by not awaiting, the second play request should be triggered within milliseconds after the first one, and both will play in parallel.

If for any reason you need to wait until both players have finished playing, you can use Future.wait:

await Future.wait([
  player1.play(),
  player2.play(),
]);
print('done'); // this will print after both players are finished.

(Extra example based on your comment) To loop player2 until player1 completes:

await player2.setLoopMode(LoopMode.one);
player2.play(); // don't await
await player1.play(); // wait for player1 to complete
await player1.pause(); // or stop or dispose
await player2.pause(); // or stop or dispose

Note that each player uses up native resources, which means two things:

  1. You may hit a resource limit if you create too many parallel instances.
  2. You should call dispose on each player once you're finished using it since this will free up those resources for use by other apps.

On the audio_service side, you are basically implementing callbacks for what you want to happen when the user presses the play button, etc, and you can stick the above code into your callback. For example, if you want to play both players simultaneously when the user clicks "play", you would implement your callback like this:

Future<void> play() async {
  player1.play();
  player2.play();
}

You could also implement the pause callback similarly:

Future<void> pause() async {
  player1.pause();
  player2.pause();
}
Ryan Heise
  • 2,273
  • 5
  • 14
  • I'm not sure if this is out of the scope of my original question and if I'd need to ask a new question, but is there a way to repeatedly loop `player2` until `player1` has finished playing? – Robert Hinckley Dec 29 '20 at 01:56
  • @RyanHeise, Could you please tell me what the limits for parallel instances count? Is it 5 playing sounds at time for most devices or 50 parallel sounds? – JavaRunner Feb 26 '21 at 02:01
  • You would have to find that through your own testing, but it may actually vary depending on the resources of the particular device. I'm not sure what those numbers are I'm afraid. – Ryan Heise Feb 26 '21 at 02:49
  • I've tried this but it can play 2 files in one player instance. Just a comment. It can play up to many files in one instance even if i apply player.stop() before playing again. It seems audio player creates duplicate stream in the background. Maybe player.dispose() should clear the data but im not sure if i used it well – Ishmael Mavor Raines Feb 17 '23 at 15:57
  • A single player instance can't play two files simultaneously. If it does, it is worth reporting the bug. – Ryan Heise Feb 18 '23 at 06:23