Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Big performance issues on Android devices. #1799

Open
2 tasks done
ClemPalf opened this issue May 9, 2024 · 6 comments
Open
2 tasks done

Big performance issues on Android devices. #1799

ClemPalf opened this issue May 9, 2024 · 6 comments
Labels

Comments

@ClemPalf
Copy link

ClemPalf commented May 9, 2024

Checklist

  • I read the troubleshooting guide before raising this issue
  • I made sure that the issue I am raising doesn't already exist

Current bug behaviour

Hi,

First, a bit of context: In my app, I am using 2 audioplayers instances. One that plays a background music (from which I created a subscription with onPlayerComplete to loop over a few different songs), and one that is used to give the user some instructions based on its interaction with the app (the assets are generally 1–2 seconds long and are rarely called).

Problem: I received a lot of complaints from our android users that the app was "hard freezing" from time to time and at complete random moments. After a few trials, I managed to reproduce the issue, and indeed, I couldn't reproduce it consistently. It doesn't seem that the freezes are linked to any specific code or events (not even the one that triggers the "instructions").

I managed to catch those freeze in the CPU profiler and this is what I got:
First, when everything is working fine :
image
As we can see, the method AudioPlayer.getCurrentPosition accounts for only a fraction of the total CPU usage.

And this is the result when the app is freezing :
image
The AudioPlayer.getCurrentPosition suddenly account for half of the CPU usage.

Note that:

  • The freezes happen only on Android devices, whether they are weak or powerful (eg: Samsung S23 utlra).
  • The freezes are not related to the audioPlayer that gives instructions, I deleted it and could reproduce the problem. The issue comes from the one playing the background music.
  • No errors are thrown, just intense freezes, they last 20 seconds in average, and limit the UI to 1 frame every 2 seconds.

I am afraid I cannot provide a minimal reproducible example, especially as I struggle reproducing it myself.

Do you have some intuition as to what could make the AudioPlayer.getCurrentPosition so CPU greedy ?

I saw that the function was called on a crazy rate when an asset is being played, is there a way to maybe reduce it ?
(Although, it is the same on iPhones and there is no problem at all, so I guess that is not the problem … )

Should I try to play the music in an isolate ?

Kind regards,

Expected behaviour

No lags.

Steps to reproduce

  1. Execute flutter run on the code sample
  2. ...
  3. ...

Code sample

Code sample
void main() {
}

Affected platforms

Android

Platform details

The one I have reproduced the problem with:
One Plus 8,
Samsung S23,

From user complaints: many more.

AudioPlayers Version

main 6.0.0

Build mode

release

Audio Files/URLs/Sources

No response

Screenshots

No response

Logs

my relevant logs
Full Logs
my full logs or a link to a gist

Flutter doctor:

Output of: flutter doctor -v

Related issues / more information

No response

Working on PR

no way

@ClemPalf ClemPalf added the bug label May 9, 2024
@MyisCARRY
Copy link

Can you provide code how you are using the audio player that plays music?

@ClemPalf
Copy link
Author

Sure,
First, at the beginning of my app I set this audio context:

var conf = AudioContext(
      android: const AudioContextAndroid(
        isSpeakerphoneOn: false,
        stayAwake: true,
        contentType: AndroidContentType.music,
        usageType: AndroidUsageType.game,
        audioFocus: AndroidAudioFocus.gainTransientMayDuck,
      ),
      iOS: AudioContextIOS(
        category: AVAudioSessionCategory.playback,
        options: const {
          AVAudioSessionOptions.duckOthers,
        },
      ));

  AudioPlayer.global.setAudioContext(conf);

And create my audioplayer:

// Music player.
  AudioPlayer musicPlayer = AudioPlayer();

When the main feature/game of my app start, this code is run :
(My goal is to loop through a predefined playlist).

musicCompletionSubscription = musicPlayer.onPlayerComplete.listen(
    (event) {
      musicCheckPoint++;

      Sounds.playMusic(
        checkpoint: musicCheckPoint,
      );
   },
);

Sounds.playMusic(
    checkpoint: musicCheckPoint,
);

The Sounds class, looks something like this:

  class Sounds {
  static List<String> danceMusic = [
    "dance-sweat_and_shine",
    "dance-Energetic_Rythms",
    "dance-Pulse_in_Motion",
    "dance-Rhythmic_Rush_remix_v1",
    "dance-Rhythmic_Rush_remix_v2",
    //...
  ];
  
  ///...

  static Future<void> playMusic({
    required int checkpoint,
  }) async {
    final String music = danceMusic[checkpoint];
    musicPlayer.play(
      AssetSource('audio/musics/$music.mp3'),
      mode: PlayerMode.mediaPlayer,
    );
  }

  ///...
}

@MyisCARRY
Copy link

From what I have understood AndroidUsageType.game should be used for short sfx sounds. For music use AndroidUsageType.media.

Also I notice that you don't release previous asset before switching to new and you don't cancel previous listener.

@ClemPalf
Copy link
Author

I am going to try your recommendations, but I am not sure that I understand "you don't cancel previous listener".

Do you mean I should cancel and renew the onPlayerComplete every time a new music is played? Why?

@MyisCARRY
Copy link

Never mind the comment about listener, I understood it wrong

@Gustl22
Copy link
Collaborator

Gustl22 commented May 13, 2024

We currently work on Exoplayer for Android: #1691

If you want to work on a fix for the current media player, you're more than welcome to provide a Merge Request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants