Lately I was trying out this waveform audio player (https://pub.dev/packages/audio_waveforms). Ill share the code below, The problem I am facing is that when the audio is done playing for the first time, The button and waveform resets automatically but pressing playing doesnt do anything. I wish there was a way to get it to replay the same track.
Can anyone help?
import 'package:audio_waveforms/audio_waveforms.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'dart:async'; // Import this for StreamSubscription
class AudioPlayerWidget extends StatefulWidget {
const AudioPlayerWidget({
super.key,
this.width,
this.height,
required this.audioUrl,
});
final double? width;
final double? height;
final String audioUrl;
@override
State<AudioPlayerWidget> createState() => _AudioPlayerWidgetState();
}
class _AudioPlayerWidgetState extends State<AudioPlayerWidget> {
late PlayerController _waveformController;
bool _isPlaying = false;
bool _isLoading = true;
bool _hasPlayed = false; // Track whether the audio has finished playing
late StreamSubscription<PlayerState> _playerStateSubscription;
String? _filePath; // Store the file path for re-initialization
@override
void initState() {
super.initState();
_waveformController = PlayerController();
_initializePlayer();
_playerStateSubscription =
_waveformController.onPlayerStateChanged.listen((state) {
setState(() {
_isPlaying = state.isPlaying;
});
});
}
Future<void> _initializePlayer() async {
try {
filePath = await downloadAudioFile(widget.audioUrl);
await _waveformController.preparePlayer(
path: _filePath!,
shouldExtractWaveform: true,
);
// Listen for completion event and reset both the player and waveform
waveformController.onCompletion.listen(() async {
setState(() {
_isPlaying = false;
_hasPlayed = true; // Track that the audio has finished
});
await _waveformController.seekTo(0); // Reset the waveform to start
await _waveformController.pausePlayer(); // Ensure the player is paused
});
setState(() {
_isLoading = false;
});
} catch (e) {
debugPrint("Error initializing player: $e");
setState(() {
_isLoading = false;
});
}
}
Future<String> _downloadAudioFile(String url) async {
final tempDir = await getTemporaryDirectory();
final file = File('${tempDir.path}/temp_audio.mp3');
final response = await http.get(Uri.parse(url));
await file.writeAsBytes(response.bodyBytes);
return file.path;
}
@override
void dispose() {
_playerStateSubscription.cancel();
_waveformController.dispose();
super.dispose();
}
void _togglePlayPause() async {
if (_isPlaying) {
await _waveformController.pausePlayer();
} else {
if (_hasPlayed) {
await _waveformController.seekTo(0); // Reset to the start
await _waveformController
.startPlayer(); // Start the player from the beginning
_hasPlayed = false;
} else {
await _waveformController.startPlayer();
}
}
}
@override
Widget build(BuildContext context) {
return Container(
width: widget.width ?? double.infinity,
height: widget.height ?? 150.0,
padding: const EdgeInsets.all(12.0),
decoration: BoxDecoration(
color: const Color(0xFF1A1A1A),
borderRadius: BorderRadius.circular(12.0),
),
child: _isLoading
? const Center(child: CircularProgressIndicator())
: Column(
children: [
GestureDetector(
onHorizontalDragUpdate: (details) {
final width =
widget.width ?? MediaQuery.of(context).size.width;
final position = (details.localPosition.dx / width) *
_waveformController.maxDuration;
_waveformController.seekTo(position.toInt());
},
child: AudioFileWaveforms(
size: Size(widget.width ?? double.infinity, 70),
playerController: _waveformController,
waveformType: WaveformType.long,
playerWaveStyle: const PlayerWaveStyle(
fixedWaveColor: Colors.grey,
liveWaveColor: Colors.blueAccent,
spacing: 6,
showSeekLine: true,
seekLineThickness: 2.0,
),
),
),
IconButton(
icon: Icon(
isPlaying ? Icons.pausecircle : Icons.play_circle,
size: 48.0,
color: Colors.white,
),
onPressed: _togglePlayPause,
),
],
),
);
}
}