I have like 10 – 15 audio, and I need to play them one after another or you can say merge them. They are dynamic(I get the urls from server). I’m using the just_audio
packege for playing audio. I’m using ConcatenatingAudioSource
to play one audio after another
This is how I initialize the player
late AudioPlayer _audioPlayer;
List<AudioPlayer> players = [];
ConcatenatingAudioSource concatenatingAudioSource =
ConcatenatingAudioSource(children: []);
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
final state = ref.watch(homeController);
state.ayahList.forEach((element) async {
final player = AudioPlayer();
await player.setUrl('https://example.com/$element.mp3');
players.add(player);
});
final audioSources = players
.map((player) => player.audioSource ?? AudioSource.uri(Uri()))
.toList();
concatenatingAudioSource =
ConcatenatingAudioSource(children: audioSources);
_audioPlayer = AudioPlayer()..setAudioSource(concatenatingAudioSource);
});
}
This is the UI, it’s very simple
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: audioPlayer.playerStateStream,
builder: (context, snapshot) {
final playerState = snapshot.data;
final processingState = playerState?.processingState;
final playing = playerState?.playing;
if (!(playing ?? false)) {
return IconButton(
onPressed: () => audioPlayer.play(),
icon: const Icon(Icons.play_arrow_rounded));
} else if (processingState != ProcessingState.completed) {
return IconButton(
onPressed: () => audioPlayer.pause(),
icon: const Icon(Icons.pause_rounded));
}
return const Icon(Icons.play_arrow_rounded);
});
}
Now when I click the play button, nothing happens, nothing on the log as well. Maybe I got the whole wrong idea about concatenatingAudioSource
, I don’t know. Please help me
2
Answers
I figured out another way to play one audio after another
It might be because
ref.watch
is used duringinitState
. This is not the place to put a watch as it will not be "watched".At this point, if you’re sure that
homeController
is well initialized and you don’t want to re-trigger the code block withinaddPostframeCallback
, you can useref.read
instead.Otherwise you should define a function like
handleHomeControllerChanged
, listen to yourhomeController
insidebuild
method (you should change yourstatefulWidget
toconsumerWidget
in order to be able to have access to ref.listen). This way, you can listen to changes onhomeController
and re-trigger the function each time the controller changes.