Search code examples
flutterdartjust-audio

How can I fade in and fade out audio in just_audio?


I have a ConcatenatingAudioSource for which I want to fade each item in and out. What is the best way to fade in and fade out in just_audio?


Solution

  • As per @Intellect's comment, I achieved a fade out effect by just controlling the volume with a CountdownTimer. Here is an example in an AudioManager class I set up that does the trick, FYI.

    import 'package:just_audio/just_audio.dart';
    import 'package:quiver/async.dart';
    
    class AudioManager {
    
    /// Relevant code snippets ....
    
      final AudioPlayer _player = AudioPlayer();
      CountdownTimer? _timer;
    
      Future<void> play({required String audio, required volume}) async {
        _player
            .setAsset('assets/audio/$audio.mp3')
            .then((value) async {
           
    
          /// Stop the [_player] and important to cancel the [_timer].
          /// If audio is switched, and the [_timer] is not cancelled, it will continue to run and 
          /// may cancel the new clip.
          if (_player.playing) {
            _timer?.cancel();
            await _player.stop();
          }
              
              /// Make sure to reset the volume when play another clip.
    
          await _player.seek(Duration.zero);
          await _player.setVolume(volume);
          await _player.play();
        });
      }
    
      Future<void> fadeOutAndStop(
          {required double startVolume}) async {
        /// Will fade out over 3 seconds
        Duration duration = const Duration(seconds: 3);
    
        /// Using a [CountdownTimer] to decrement the volume every 50 milliseconds, then stop [AudioPlayer] when done.
        _timer = CountdownTimer(duration, const Duration(milliseconds: 50))..listen((event) {
          final percent = event.remaining.inMilliseconds / duration.inMilliseconds;
          setVolume(percent * startVolume);
        }).onDone(() async {
          await _player.stop();
        });
      }
    
      Future<void> setVolume(double volume) async =>
          await _player.setVolume(volume);
      ///
    }