In this blog, we learn about how to implement Audio Video Progress Bar In Flutter.
We can use this widget to display the current progress of a music or video player. This widget is easier to link to a media player compared to the Flutter Slider widget.
Moreover, it allows streaming media to display the buffered state.
Introduction:-
The video progress bar is a convenient tool that helps you keep track of where you stopped watching a video last time.
When you exit a video without finishing it, a bar located under the video thumbnail displays the exact moment where you paused. The next time you play the video, it will start from where you left off.
Implementation:-
First, we need to create a new Flutter project and add the following dependencies to the pubspec.yaml file.
dependencies:
flutter
sdk: flutter
audio_video_progress_bar: ^1.0.1
Now, run the command "flutter pub get" to add the dependencies.
Add the following package to your class.
import 'package:audio_video_progress_bar/audio_video_progress_bar.dart';
You may also check our flutter app development company page.
Create Progress Bar :-
To create progress bars for audio and video, you can use the ProgressBar widget.
ProgressBar(
progress: Duration(milliseconds: 1000),
buffered: Duration(milliseconds: 2000),
total: Duration(milliseconds: 5000),
onSeek: (duration) {
print('User selected a new time: $duration');
},
),
This is a static instance.
Now create a progress bar with an audio url:-
Add the following dependencies to the pubspec.yaml file.
dependencies:
flutter
sdk: flutter
audio_video_progress_bar: ^1.0.1
just_audio: ^0.9.32
Add the following package to your class.
import 'package:just_audio/just_audio.dart';
Create a DurationState class and wrap it in a builder widget updated by audio or video player.
class DurationState {
const DurationState({this.progress, this.buffered, this.total});
final Duration ? progress;
final Duration ? buffered;
final Duration ? total;
}
...
StreamBuilder<DurationState> _progressBar() {
return StreamBuilder<DurationState>(
stream: _durationState,
builder: (context, snapshot) {
final durationState = snapshot.data;
final progress = durationState?.progress ?? Duration.zero;
final buffered = durationState?.buffered ?? Duration.zero;
final total = durationState?.total ?? Duration.zero;
return ProgressBar(
progress: progress,
buffered: buffered,
total: total,
onSeek: (duration) {
_player.seek(duration);
},
onDragUpdate: (details) {
debugPrint('${details.timeStamp}, ${details.localPosition}');
},
);
},
);
}
Create Play Button:-
StreamBuilder<PlayerState> _playButton() {
return StreamBuilder<PlayerState>(
stream: _player.playerStateStream,
builder: (context, snapshot) {
final playerState = snapshot.data;
final processingState = playerState?.processingState;
final playing = playerState?.playing;
if (processingState == ProcessingState.loading ||
processingState == ProcessingState.buffering) {
return Container(
margin: const EdgeInsets.all(8.0),
width: 32.0,
height: 32.0,
child: const CircularProgressIndicator(),
);
} else if (playing != true) {
return IconButton(
icon: const Icon(Icons.play_arrow),
iconSize: 32.0,
onPressed: _player.play,
);
} else if (processingState != ProcessingState.completed) {
return IconButton(
icon: const Icon(Icons.pause),
iconSize: 32.0,
onPressed: _player.pause,
);
} else {
return IconButton(
icon: const Icon(Icons.replay),
iconSize: 32.0,
onPressed: () => _player.seek(Duration.zero),
);
}
},
);
}
complete code:-
import 'package:audio_video_progress_bar/audio_video_progress_bar.dart';
import 'package:flutter/material.dart';
import 'package:just_audio/just_audio.dart';
import 'package:rxdart/rxdart.dart';
class AudioVideoProgressBar extends StatefulWidget {
const AudioVideoProgressBar({Key? key}) : super(key: key);
@override
State<AudioVideoProgressBar> createState() => _AudioVideoProgressBarState();
}
class _AudioVideoProgressBarState extends State<AudioVideoProgressBar> {
AudioPlayer player=AudioPlayer();
final url = 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3';
late Stream<DurationState> durationState;
@override
void initState() {
super.initState();
player = AudioPlayer();
durationState = Rx.combineLatest2<Duration, PlaybackEvent, DurationState>(
player.positionStream,
player.playbackEventStream,
(position, playbackEvent) => DurationState(
progress: position,
buffered: playbackEvent.bufferedPosition,
total: playbackEvent.duration,
));
_init();
}
Future<void> _init() async {
try {
await player.setUrl(url);
} catch (e) {
debugPrint('An error occurred $e');
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(title: const Text("Audio Video Progress Bar"),),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
ProgressBar(
progress: const Duration(milliseconds: 1000),
buffered: const Duration(milliseconds: 2000),
total: const Duration(milliseconds: 5000),
onSeek: (duration) {
print('User selected a new time: $duration');
},
),
const SizedBox(height: 20),
Container(
child: _progressBar(),
),
const SizedBox(height: 10),
_playButton(),
],
),
),
),
),
);
}
StreamBuilder<DurationState> _progressBar() {
return StreamBuilder<DurationState>(
stream: durationState,
builder: (context, snapshot) {
final durationState = snapshot.data;
final progress = durationState?.progress ?? Duration.zero;
final buffered = durationState?.buffered ?? Duration.zero;
final total = durationState?.total ?? Duration.zero;
return ProgressBar(
progress: progress,
buffered: buffered,
total: total,
onSeek: (duration) {
player.seek(duration);
},
onDragUpdate: (details) {
debugPrint('${details.timeStamp}, ${details.localPosition}');
},
);
},
);
}
StreamBuilder<PlayerState> _playButton() {
return StreamBuilder<PlayerState>(
stream: player.playerStateStream,
builder: (context, snapshot) {
final playerState = snapshot.data;
final processingState = playerState?.processingState;
final playing = playerState?.playing;
if (processingState == ProcessingState.loading ||
processingState == ProcessingState.buffering) {
return Container(
margin: const EdgeInsets.all(8.0),
width: 32.0,
height: 32.0,
child: const CircularProgressIndicator(),
);
} else if (playing != true) {
return IconButton(
icon: const Icon(Icons.play_arrow),
iconSize: 32.0,
onPressed: player.play,
);
} else if (processingState != ProcessingState.completed) {
return IconButton(
icon: const Icon(Icons.pause),
iconSize: 32.0,
onPressed: player.pause,
);
} else {
return IconButton(
icon: const Icon(Icons.replay),
iconSize: 32.0,
onPressed: () => player.seek(Duration.zero),
);
}
},
);
}
}
class DurationState {
const DurationState({this.progress, this.buffered, this.total});
final Duration ? progress;
final Duration ? buffered;
final Duration ? total;
}
Output:-
As shown in the video below, the progress bar moves when the audio plays and stops when it is paused.
Conclusion:-
We have completed the implementation of our topic.
Check here for more interesting blogs –https://mobikul.com/blog/.
After reading this blog, you should have a better understanding of how to implement an audio and video progress bar in Flutter.
Flutter’s official website offers useful resources for exploring Audio, Video, and Progress bar.
Webkul is a full‑stack Flutter app development company, specializing in interactive and media‑rich mobile experiences, like their blog demo showing how to build a customizable audio/video progress bar in Flutter.
Thank you for taking the time to read this blog post🙂.
References:-
https://pub.dev/packages/audio_video_progress_bar.

Be the first to comment.