I have Audio Sink Error and Audio Playback Error after playing 30 audios on android just_audio

769 views Asked by At

After Playing 30 audios, I encounter these errors.Its an podcast app. Even I play same 30 audios the player fails after playing same audios 30 to 35 times. Although the audio files continue to play, but no there is no audible sound , and the notification widget of the player remains stuck on the previous audio. This problem is only on Android. I have tried playing on Ios it plays fine. How can I resolve this issue?

E/android.media.AudioTrack( 8248): Error code -20 when initializing AudioTrack.
E/MediaCodecAudioRenderer( 8248): Audio sink error
E/MediaCodecAudioRenderer( 8248):   com.google.android.exoplayer2.audio.AudioSink$InitializationException: AudioTrack init failed 0 Config(44100, 4, 28288) Format(null, null, null, audio/raw, null, -1, null, [-1, -1, -1.0], [1, 44100])
E/MediaCodecAudioRenderer( 8248):       at com.google.android.exoplayer2.audio.DefaultAudioSink$Configuration.buildAudioTrack(DefaultAudioSink.java:2136)
E/MediaCodecAudioRenderer( 8248):       at com.google.android.exoplayer2.audio.DefaultAudioSink.buildAudioTrack(DefaultAudioSink.java:1073)
E/MediaCodecAudioRenderer( 8248):       at com.google.android.exoplayer2.audio.DefaultAudioSink.buildAudioTrackWithRetry(DefaultAudioSink.java:1051)
E/MediaCodecAudioRenderer( 8248):       at com.google.android.exoplayer2.audio.DefaultAudioSink.initializeAudioTrack(DefaultAudioSink.java:843)
E/MediaCodecAudioRenderer( 8248):       at com.google.android.exoplayer2.audio.DefaultAudioSink.handleBuffer(DefaultAudioSink.java:929)
E/MediaCodecAudioRenderer( 8248):       at com.google.android.exoplayer2.audio.MediaCodecAudioRenderer.processOutputBuffer(MediaCodecAudioRenderer.java:709)
E/MediaCodecAudioRenderer( 8248):       at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.drainOutputBuffer(MediaCodecRenderer.java:1889)
E/MediaCodecAudioRenderer( 8248):       at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:782)
E/MediaCodecAudioRenderer( 8248):       at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:1007)
E/MediaCodecAudioRenderer( 8248):       at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:502)
E/MediaCodecAudioRenderer( 8248):       at android.os.Handler.dispatchMessage(Handler.java:102)
E/MediaCodecAudioRenderer( 8248):       at android.os.Looper.loopOnce(Looper.java:240)
E/MediaCodecAudioRenderer( 8248):       at android.os.Looper.loop(Looper.java:351)
E/MediaCodecAudioRenderer( 8248):       at android.os.HandlerThread.run(HandlerThread.java:67)
E/MediaCodecAudioRenderer( 8248):   Caused by: java.lang.UnsupportedOperationException: Cannot create AudioTrack
E/MediaCodecAudioRenderer( 8248):       at android.media.AudioTrack$Builder.build(AudioTrack.java:1390)
E/MediaCodecAudioRenderer( 8248):       at com.google.android.exoplayer2.audio.DefaultAudioSink$Configuration.createAudioTrackV29(DefaultAudioSink.java:2185)
E/MediaCodecAudioRenderer( 8248):       at com.google.android.exoplayer2.audio.DefaultAudioSink$Configuration.createAudioTrack(DefaultAudioSink.java:2163)
E/MediaCodecAudioRenderer( 8248):       at com.google.android.exoplayer2.audio.DefaultAudioSink$Configuration.buildAudioTrack(DefaultAudioSink.java:2128)
E/MediaCodecAudioRenderer( 8248):       ... 13 more
E/ExoPlayerImplInternal( 8248): Playback error
E/ExoPlayerImplInternal( 8248):   com.google.android.exoplayer2.ExoPlaybackException: MediaCodecAudioRenderer error, index=1, format=Format(null, null, null, audio/mpeg, null, -1, null, [-1, -1, -1.0], [1, 44100]), format_supported=YES
E/ExoPlayerImplInternal( 8248):       at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:578)
E/ExoPlayerImplInternal( 8248):       at android.os.Handler.dispatchMessage(Handler.java:102)
E/ExoPlayerImplInternal( 8248):       at android.os.Looper.loopOnce(Looper.java:240)
E/ExoPlayerImplInternal( 8248):       at android.os.Looper.loop(Looper.java:351)
E/ExoPlayerImplInternal( 8248):       at android.os.HandlerThread.run(HandlerThread.java:67)
E/ExoPlayerImplInternal( 8248):   Caused by: com.google.android.exoplayer2.audio.AudioSink$InitializationException: AudioTrack init failed 0 Config(44100, 4, 28288) Format(null, null, null, audio/raw, null, -1, null, [-1, -1, -1.0], [1, 44100])
E/ExoPlayerImplInternal( 8248):       at com.google.android.exoplayer2.audio.DefaultAudioSink$Configuration.buildAudioTrack(DefaultAudioSink.java:2136)
E/ExoPlayerImplInternal( 8248):       at com.google.android.exoplayer2.audio.DefaultAudioSink.buildAudioTrack(DefaultAudioSink.java:1073)
E/ExoPlayerImplInternal( 8248):       at com.google.android.exoplayer2.audio.DefaultAudioSink.buildAudioTrackWithRetry(DefaultAudioSink.java:1051)
E/ExoPlayerImplInternal( 8248):       at com.google.android.exoplayer2.audio.DefaultAudioSink.initializeAudioTrack(DefaultAudioSink.java:843)
E/ExoPlayerImplInternal( 8248):       at com.google.android.exoplayer2.audio.DefaultAudioSink.handleBuffer(DefaultAudioSink.java:929)
E/ExoPlayerImplInternal( 8248):       at com.google.android.exoplayer2.audio.MediaCodecAudioRenderer.processOutputBuffer(MediaCodecAudioRenderer.java:709)
E/ExoPlayerImplInternal( 8248):       at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.drainOutputBuffer(MediaCodecRenderer.java:1889)
E/ExoPlayerImplInternal( 8248):       at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:782)
E/ExoPlayerImplInternal( 8248):       at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:1007)
E/ExoPlayerImplInternal( 8248):       at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:502)
E/ExoPlayerImplInternal( 8248):       ... 4 more
E/ExoPlayerImplInternal( 8248):       Suppressed: com.google.android.exoplayer2.audio.AudioSink$InitializationException: AudioTrack init failed 0 Config(44100, 4, 28288) Format(null, null, null, audio/raw, null, -1, null, [-1, -1, -1.0], [1, 44100])
E/ExoPlayerImplInternal( 8248):           ... 14 more
E/ExoPlayerImplInternal( 8248):       Caused by: java.lang.UnsupportedOperationException: Cannot create AudioTrack
E/ExoPlayerImplInternal( 8248):           at android.media.AudioTrack$Builder.build(AudioTrack.java:1390)
E/ExoPlayerImplInternal( 8248):           at com.google.android.exoplayer2.audio.DefaultAudioSink$Configuration.createAudioTrackV29(DefaultAudioSink.java:2185)
E/ExoPlayerImplInternal( 8248):           at com.google.android.exoplayer2.audio.DefaultAudioSink$Configuration.createAudioTrack(DefaultAudioSink.java:2163)
E/ExoPlayerImplInternal( 8248):           at com.google.android.exoplayer2.audio.DefaultAudioSink$Configuration.buildAudioTrack(DefaultAudioSink.java:2128)
E/ExoPlayerImplInternal( 8248):           ... 13 more
E/ExoPlayerImplInternal( 8248):   Caused by: java.lang.UnsupportedOperationException: Cannot create AudioTrack
E/ExoPlayerImplInternal( 8248):       at android.media.AudioTrack$Builder.build(AudioTrack.java:1390)
E/ExoPlayerImplInternal( 8248):       at com.google.android.exoplayer2.audio.DefaultAudioSink$Configuration.createAudioTrackV29(DefaultAudioSink.java:2185)
E/ExoPlayerImplInternal( 8248):       at com.google.android.exoplayer2.audio.DefaultAudioSink$Configuration.createAudioTrack(DefaultAudioSink.java:2163)
E/ExoPlayerImplInternal( 8248):       at com.google.android.exoplayer2.audio.DefaultAudioSink$Configuration.buildAudioTrack(DefaultAudioSink.java:2128)
E/ExoPlayerImplInternal( 8248):       ... 13 more
D/MediaCodec( 8248): [0xb4000075ee75b000] setState: 7

audioHandler.dart

class AudioPlayerHandlerMain extends BaseAudioHandler
    with SeekHandler, ChangeNotifier {
   AudioPlayer _player = AudioPlayer();
  static var current_audio_file_id = '';
  static var current_audio_file_type = 'suhbas';

  Future<void> dispose() async {

    _player.dispose();
    print("Disposedddd");

  }


  Stream<Duration>? _positionStream;
  var currentSecond = 0;
  late StreamSubscription<Duration> _positionSubscription;

  AudioPlayerHandlerMain(PlayingMediaItem _item, BuildContext context) {
    _player.playbackEventStream.map(_transformEvent).pipe(playbackState);


    mediaItem.add(_item);

    _player.setAudioSource(AudioSource.uri(Uri.parse(_item.id)));
    notifyListeners();
  }

  AudioPlayer getPlayer() {

    return _player;
  }

  static isMediaPlayable(String? url, int id) async {
    print("Audio file id: $id");
    try {
      if(Platform.isIOS){
        AudioPlayer().setFilePath(url ?? "");
      }else{
        await AudioPlayer().setUrl(url ?? "");
       }

      Timer.periodic(Duration(seconds: 10), (Timer t) {
        getIt<AudioPulseDaoRepository>()
            .getAudioPulseItem(current_audio_file_id)
            .then((value) {
         });
      });

      return true;
    } catch (e) {
      return false;
    }
  }

  static getDuration(String url) async {
    try {
      return await AudioPlayer().setUrl(url ?? "");
    } catch (e) {
      return Duration();
    }
  }

  AudioPlayerHandlerMain? _audioHandler;

  void initAudioHandler(AudioPlayerHandlerMain audioHandler) {


    _audioHandler = audioHandler;
   

    notifyListeners();


  }

  AudioPlayerHandlerMain? audioHandler() => _audioHandler;
  @override
  Future<void> play() async {
    
    _player.play();
    notifyListeners();
  }


  @override
  Future<void> pause() async{
    _player.pause();
    notifyListeners();
  }

  @override
  Future<void> seek(Duration position) => _player.seek(position);

  @override
  Future<void> stop() async {
    _player.stop();
    await playbackState.firstWhere((state) => state.processingState == AudioProcessingState.idle);
    super.stop();
  }

  PlaybackState _transformEvent(PlaybackEvent event) {
    if (current_audio_file_id.isNotEmpty) {
      Stream.periodic(const Duration(seconds: 4), (_) => _player.position)
          .listen((event) {
        if (event.inSeconds != 0) {
          currentSecond = event.inSeconds;
          if(currentSecond%5==0){
            getIt<AudioPulseDaoRepository>().insertAudioPulseItem(
                AudioPulseModel(
                    current_audio_file_id, currentSecond.toString(), current_audio_file_type));
          }
        }
      });
    }

    return PlaybackState(
      controls: [
        MediaControl.rewind,
        if (_player.playing) MediaControl.pause else MediaControl.play,
        MediaControl.stop,
        MediaControl.fastForward,
      ],
      systemActions: const {
        MediaAction.seek,
        MediaAction.seekForward,
        MediaAction.seekBackward,
      },
      androidCompactActionIndices: const [0, 1, 3],
      processingState: const {
        ProcessingState.idle: AudioProcessingState.idle,
        ProcessingState.loading: AudioProcessingState.loading,
        ProcessingState.buffering: AudioProcessingState.buffering,
        ProcessingState.ready: AudioProcessingState.ready,
        ProcessingState.completed: AudioProcessingState.completed,
      }[_player.processingState]!,
      playing: _player.playing,
      updatePosition: _player.position,
      bufferedPosition: _player.bufferedPosition,
      speed: _player.speed,
      queueIndex: event.currentIndex,
       );

  }

  Duration lastFileDuration = Duration.zero;
  void setLastFileDuration(Duration fileDuration) {
    //TODO: maybe required in future.
    lastFileDuration = fileDuration;
    notifyListeners();
  }
}

Init Audio Handler In main.dart

Future<void> initAudioHandler(BuildContext context) async {

    var handler = await AudioService.init(
      builder: () => AudioPlayerHandlerMain(
         PlayingMediaItem.getDummyModel()
             ,context
      ),
      config: const AudioServiceConfig(
        androidNotificationChannelId: 'com.platform.untotheones',
        androidNotificationChannelName: 'Unto The One',
        androidNotificationOngoing: false,
        androidStopForegroundOnPause: true,

      ),
    );

    Provider.of<AudioPlayerHandlerMain>(context, listen: false).initAudioHandler(handler);

  }

}

I have tried different solutions but still no success. I have tried playing audios on IOS it plays fine this error is just on android. I have tried playing audios from downloads and from server both have same issue. My audios are in mp3 format. If I have a list of 15 audios and I play the list 2 3 times. After some time there is no sound for the same audios. When this happens then the audio_service widget in notification is still playing the last audio. And even I kill my app the audio_service then will be still playing previous audios but don't have any sound

1

There are 1 answers

0
Ryan Heise On BEST ANSWER

You are creating too many AudioPlayer instances and running out of memory. You should not need to create more than one AudioPlayer() unless you wish to play these different players at the same time. Assuming you don't want to play two files at the same time, the only player instance you need is this one at the top of your audio handler:

   AudioPlayer _player = AudioPlayer();

The other 3 places where you repeatedly create new instances, like here:

      if(Platform.isIOS){
        AudioPlayer().setFilePath(url ?? "");
      }else{
        await AudioPlayer().setUrl(url ?? "");
       }

and here:

  static getDuration(String url) async {
    try {
      return await AudioPlayer().setUrl(url ?? "");
    } catch (e) {
      return Duration();
    }
  }

should be fixed by replacing the AudioPlayers() constructor with a reference to your existing player _player.