flutteraudioaudio-player

How to handle multiple AudioPlayers in flutter


I am building a chat app and I need to build as many audio players as there are in the chat. I tried to use just_audio and audio_waveforms but neither of them helped me. With just_audio, I couldn't control multiple audio players, my approach was that for each audio message I would create an AudioPlayer with an id in a map. with this I could control each one of the audio players but there were some issues with the library itself so I quitted using it. audio_waveforms, it couldn't find my audio at all in assets/audio/1.wav. I also tried using path_provider like this:

final directory = await getApplicationDocumentsDirectory();
      await player.preparePlayer(
        path: '${directory.path}/$path',
        shouldExtractWaveform: true,
        noOfSamples: 100,
      );

but same issue. Can someone with experience in this field tell me what is the best approach for playing multiple audio players NOT simultaneously and what package or the code he used for this.

EDIT

I tried putting the folder in the same folder as the file and it didn't gave me an error but it didn't work, it just gave me a vertical line


Solution

  • Here's the sample code for playing multiple sounds from a ListView.

    Firstly, download my assets from here.

    This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

    dependencies:
      just_audio: ^0.9.35
    

    Also, in the pubspec.yaml file, do these configurations:

    flutter:
      uses-material-design: true
      assets:
        - assets/sound1.mp3
        - assets/sound2.mp3
        - assets/sound3.mp3
        - assets/sound4.mp3
        - assets/sound5.mp3
    

    Copy & paste these codes into the main.dart file:

    import "package:flutter/material.dart";
    import "package:just_audio/just_audio.dart";
    
    void main() {
      WidgetsFlutterBinding.ensureInitialized();
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return const MaterialApp(
          home: MyWidget(),
        );
      }
    }
    
    class MyWidget extends StatefulWidget {
      const MyWidget({super.key});
    
      @override
      State<MyWidget> createState() => _MyWidgetState();
    }
    
    class _MyWidgetState extends State<MyWidget> {
      int playIndex = -1;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: SafeArea(
            child: ListView.builder(
              itemCount: 5,
              itemBuilder: (BuildContext context, int index) {
                return ListTile(
                  dense: true,
                  leading: const Icon(Icons.music_note),
                  title: Text("Sound ${index + 1}"),
                  subtitle: Text("Tap to play sound ${index + 1}"),
                  trailing: Icon(
                    playIndex == index ? Icons.stop_circle : Icons.play_circle,
                  ),
                  onTap: () async {
                    if (playIndex == index) {
                      await MyAudioService.instance.stop();
                      playIndex = -1;
                      setState(() {});
                    } else {
                      final String soundPath = "assets/sound${index + 1}.mp3";
                      await MyAudioService.instance.play(
                        path: soundPath,
                        startedPlaying: () {
                          playIndex = index;
                          setState(() {});
                        },
                        stoppedPlaying: () {
                          playIndex = -1;
                          setState(() {});
                        },
                      );
                    }
                  },
                );
              },
            ),
          ),
        );
      }
    }
    
    class MyAudioService {
      MyAudioService._();
      static final MyAudioService instance = MyAudioService._();
    
      final AudioPlayer player = AudioPlayer();
    
      Future<void> play({
        required String path,
        required Function() startedPlaying,
        required Function() stoppedPlaying,
      }) async {
        await stop();
        await player.setAsset(path);
        startedPlaying();
        await player.play();
        await player.stop();
        stoppedPlaying();
        return Future<void>.value();
      }
    
      Future<void> stop() async {
        if (player.playing) {
          await player.stop();
        } else {}
        return Future<void>.value();
      }
    }