Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter countdown deadline audio

Tags:

flutter

dart

I am currently working on a Flutter project and utilizing the circular_countdown_timer package to display a countdown timer. However, I am facing a challenge in implementing a feature where I want to play a "Tic" audio during the last 5 seconds of the countdown. Specifically, I would like to play a "Tic" audio for each last second of the countdown, summing up to a total of 5 "Tic" sounds.

I am seeking guidance on how to achieve this functionality within my Flutter application. How can I trigger the audio playback during the last 5 seconds of the countdown, ensuring that the "Tic" audio is played for each last second that counts down?

Any insights, suggestions, or code samples related to integrating audio playback during the countdown using the circular_countdown_timer package would be highly appreciated.

Thank you in advance for your support and expertise in resolving this challenge.

Widget:

 /// Returns Body as per mode or mode conditions
  Widget returnSmQuizBodyWidget({required BuildContext context}) {
    if (_soloModeLogic.currentMode == 'Exclusive'{
      return const SMWinScreen();
    } else {
      return Column(
        children: [
          //-----------------------   Question Container
          Stack(
            clipBehavior: Clip.none,
            children: [
              //-----------------------   Question Frame
              returnQuestionFrame(context: context),

              //-----------------------   Timer
              Positioned(
                      right: 0,
                      left: 0,
                      bottom: -25,
                      child: CircularCountDownTimer(
                        duration: _soloModeLogic.quizTime,
                        initialDuration: 0,
                        controller: _soloModeLogic.countDownController,
                        width: 5.w,
                        height: 7.h,
                        ringColor: Colors.grey.shade400,
                        ringGradient: null,
                        fillColor: _soloModeLogic.isFreezeColor
                            ? Colors.lightBlueAccent
                            : Colors.red,
                        fillGradient: null,
                        backgroundColor: const Color(0xfff5f5f5),
                        backgroundGradient: null,
                        strokeWidth: 4.w,
                        strokeCap: StrokeCap.butt,
                        textStyle: TextStyle(
                          fontSize: 20.sp,
                          color: _soloModeLogic.isFreezeColor
                              ? Colors.lightBlueAccent
                              : Colors.red,
                          fontWeight: FontWeight.bold,
                        ),
                        textFormat: CountdownTextFormat.S,
                        isReverse: true,
                        isReverseAnimation: false,
                        isTimerTextShown: true,
                        autoStart: true,
                        onStart: () {},
                        onChange: (v) {},
                        onComplete: () =>
                            _soloModeLogic.onTimeOut(context: context),
                      ),
                    ),
            ],
          ),
        ],
      );
    }
  }
like image 306
Raj A Avatar asked Jun 08 '26 01:06

Raj A


1 Answers

I have created a demo app. based on your code. It does what you need.
One important thing I came to realize is that during the last five seconds, instead of playing/doing pause each second, which causes sync loss between counter and audio player, start playing audio from the last 5th second and stop at or before zero and select suitable audio file that takes appx 1 second to play a sound.
You can change the audio speed to adjust and you can also look out for alternate audio player library.
You can do anything with the code.(Fork/copy-pase,etc)
Thanks :)

Edit :
I realized that in future, I may delete the app from the repo, hence pasting important parts of the code here.
I have assets/tick.mp3 file in the root directory.
This is my pubspec.yaml file.

name: solution_76450197
description: A new Flutter project.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1

environment:
  sdk: '>=3.0.3 <4.0.0'
dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2
  circular_countdown_timer: ^0.2.3
  audioplayers: ^4.1.0

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^2.0.0
flutter:
  uses-material-design: true

  assets:
    - assets/

This is my main.dart file.

import 'package:audioplayers/audioplayers.dart';
import 'package:circular_countdown_timer/circular_countdown_timer.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class SoloModeLogic {
  String currentMode = "none";
  bool isFreezeColor = false;

  final audioPlayer = AudioPlayer()..setSource(AssetSource('tick.mp3'));
  int quizTime = 10;
  final CountDownController countDownController = CountDownController();


  // The length indicates threshold seconds (last five seconds)
  List<bool> threshold = [false, false ,false,false,false];

  onTimeOut({required BuildContext context}) {
    print("time out");
    audioPlayer.pause();
    //restartCountdown();
  }
  // Please not that it's not called at every second change but instead
  // called on more smaller unit of second second.
  // Hence it could be called multiple times per second
  void onCountdownChange(String v) {
    int vInt = int.parse(v);
    if (vInt > 0 && vInt < threshold.length + 1 && !threshold[vInt-1]) {
      audioPlayer.pause();
      threshold[vInt-1] = true;
      audioPlayer.seek(const Duration(milliseconds: 0));
      audioPlayer.resume();
    } else if (vInt == 0) {
      audioPlayer.pause();
    }
  }


  void restartCountdown() {
    audioPlayer.pause();
    threshold = threshold.map((e) => false).toList();
    countDownController.restart(duration: quizTime);
  }
}

final _soloModeLogic = SoloModeLogic();

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return returnSmQuizBodyWidget(context: context);
  }

  /// Returns Body as per mode or mode conditions
  Widget returnSmQuizBodyWidget({required BuildContext context}) {
    if (_soloModeLogic.currentMode == 'Exclusive') {
      return const Text("Exclusive Mode");
    } else {
      return Column(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          //-----------------------   Question Container
          Stack(
            clipBehavior: Clip.none,
            children: [
              //-----------------------   Question Frame
              const Text("My Question"),

              //-----------------------   Timer
              Positioned(
                right: 0,
                left: 0,
                top: (MediaQuery.of(context).size.height / 2),
                child: CircularCountDownTimer(
                  duration: _soloModeLogic.quizTime,
                  initialDuration: 0,
                  controller: _soloModeLogic.countDownController,
                  width: 50,
                  height: 70,
                  ringColor: Colors.grey.shade400,
                  ringGradient: null,
                  fillColor: _soloModeLogic.isFreezeColor
                      ? Colors.lightBlueAccent
                      : Colors.red,
                  fillGradient: null,
                  backgroundColor: const Color(0xfff5f5f5),
                  backgroundGradient: null,
                  strokeWidth: 4,
                  strokeCap: StrokeCap.butt,
                  textStyle: TextStyle(
                    fontSize: 20,
                    color: _soloModeLogic.isFreezeColor
                        ? Colors.lightBlueAccent
                        : Colors.red,
                    fontWeight: FontWeight.bold,
                  ),
                  textFormat: CountdownTextFormat.S,
                  isReverse: true,
                  isReverseAnimation: false,
                  isTimerTextShown: true,
                  autoStart: false,
                  onStart: () {},
                  onChange: _soloModeLogic.onCountdownChange,
                  onComplete: () => _soloModeLogic.onTimeOut(context: context),
                ),
              ),
            ],
          ),
          FloatingActionButton(
            onPressed: () {
              _soloModeLogic.restartCountdown();
            },
            child: Text("Start"),
          ),
          // This trailing comma makes auto-formatting nicer for build methods.
        ],
      );
    }
  }
}
like image 78
Mearaj Avatar answered Jun 10 '26 16:06

Mearaj



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!