Linux: Delay in playback unless file is played immediately after setting the source
Checklist
- [X] I read the troubleshooting guide before raising this issue
- [X] I made sure that the issue I am raising doesn't already exist
Current bug behaviour
There's a significant and somewhat random delay that occurs when playing local files if time passes between setSource() and resume().
During the delay the player state reports playing, and multiple position events are fired with position at 0:00:0000.
Eventually the file plays, and the position events continue with accurate time info.
If the file is played very quickly after setting the source the file the sound plays immediately (similar to using the play() shortcut).
Expected behaviour
The file should play immediately when calling resume().
Steps to reproduce
Run the code sample:
- Click PREPARE
- Wait a second or two
- Click PLAY
Compare with INSTA-PLAY button.
Code sample
Full Code Sample
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
class SampleApp extends StatelessWidget {
AudioPlayer player = AudioPlayer();
final SampleAudioFile = '/home/jonathan/Documents/music/6538.mp3';
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Container(
color: Colors.black,
child: Column(children: [
DefaultTextStyle(
style: TextStyle(fontSize: 12, color: Colors.white),
child: Text(
'Click prepare, wait, then click play\nCompare to hitting insta-play',
textAlign: TextAlign.center,
)),
TextButton(onPressed: load, child: Text('PREPARE')),
TextButton(onPressed: play, child: Text('PLAY')),
TextButton(onPressed: insta, child: Text('INSTA-PLAY'))
]),
));
}
Future<void> load() async {
player = AudioPlayer();
await player.setSource(DeviceFileSource(SampleAudioFile));
}
Future<void> play() async {
await player.resume();
}
Future<void> insta() async {
player = AudioPlayer();
await player.play(DeviceFileSource(SampleAudioFile));
}
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(SampleApp());
}
Affected platforms
Linux
Platform details
Debian 12
AudioPlayers Version
5.2.1
Build mode
debug
Logs
• Debian clang version 14.0.6
• cmake version 3.25.1
• ninja version 1.11.1
• pkg-config version 1.8.1
Full Logs
Flutter doctor:
[✓] Flutter (Channel stable, 3.16.5, on Debian GNU/Linux 12 (bookworm) 6.6.6-surface-1, locale en_US.UTF-8)
• Flutter version 3.16.5 on channel stable at /home/jonathan/src/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 78666c8dc5 (5 weeks ago), 2023-12-19 16:14:14 -0800
• Engine revision 3f3e560236
• Dart version 3.2.3
• DevTools version 2.28.4
[✓] Linux toolchain - develop for Linux desktop
• Debian clang version 14.0.6
• cmake version 3.25.1
• ninja version 1.11.1
• pkg-config version 1.8.1
Related issues / more information
No response
Working on PR
no way
Thank you for the detailed report! Currently we have a lot going on. I try to fix it eventually. Feel free to post a merge request, if you can provide a fix :D
I found a workaround for this! (I'm on Ubuntu 22.04. can provide more details if needed) This is the controller class I'm using for the audioplayer.
class Controller{
AudioPlayer audioPlayer = AudioPlayer();
ValueNotifier<int> sliderNotifier = ValueNotifier<int>(0); //ValueNotifier so no need for setState
ValueNotifier<bool> playingNotifier = ValueNotifier<bool>(false); //ValueNotifier so no need for setState
Controller() {
audioPlayer.onPositionChanged.listen((Duration event){
sliderNotifier.value = event.inMilliseconds; //can be set to seconds, I like it to be set to as small of a unit as possible
});
audioPlayer.onPlayerStateChanged.listen((PlayerState state) {
playingNotifier.value = state == PlayerState.playing;
});
}
Future<void> playSong() async {
if (playingNotifier.value){
print("pause");
await audioPlayer.pause();
playingNotifier.value = false;
}
else{
print("resume");
//await audioPlayer.resume();
// CHANGE TO:
await audioPlayer.play(DeviceFileSource(...), position: Duration(milliseconds: sliderNotifier.value)); // this gives the same result as audioPlayer.resume()
playingNotifier.value = true;
}
}
}
I can provide further snippets of my code if necessary. I tried looking into the issue, but really can't find the thing that's causing the delay. This can be used as a workaround in the meantime.