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
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();
}
}