Reading list Switch to dark mode

    Audio Video Progress Bar  In Flutter

    Updated 22 December 2023

    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.

    Start your headless eCommerce
    now.
    Find out More

    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.

    Thank you for taking the time to read this blog post🙂.

    References:-

    https://pub.dev/packages/audio_video_progress_bar.

    . . .

    Leave a Comment

    Your email address will not be published. Required fields are marked*


    Be the first to comment.

    Back to Top

    Message Sent!

    If you have more details or questions, you can reply to the received confirmation email.

    Back to Home