web-dev-qa-db-fra.com

Problème lié à la durée de mise en mémoire tampon de MediaPlayer lors de la diffusion audio

J'utilise MediaPlayer pour diffuser une radio sur HTTP. Sur Lollipop, mon flux prend environ une minute à démarrer, ce qui est inacceptable. Cela prend environ 20 secondes sur KitKat, qui est déjà pénible mais qui est maintenant devenu inutilisable.

Il y a un problème connu avec ce composant lié à la mise en mémoire tampon: la quantité d'octets à mettre en mémoire tampon est codée et ne peut pas être modifiée.

Mon code est vraiment standard

player.reset();
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDataSource(streamUrl);
player.prepareAsync();

Et sur je prépare

player.start();

J'ai entendu parler d'alternatives comme GStreamer , mais je ne pouvais pas le faire fonctionner sous Windows.

Je me demande si quelqu'un a une solution efficace pour diffuser la radio sur HTTP avec un délai de démarrage décent.

EDIT

J'ai testé ExoPlayer mais le temps de démarrage le plus court que j'ai est de 15 secondes. Le joueur est bloqué sur l'état de "préparation" (pas de mise en mémoire tampon, c'est plus tard, je vois).

EDIT

Le format du flux est AAC

EDIT

J'ai testé https://code.google.com/p/aacdecoder-Android/ mais _ le seul problème de cette bibliothèque est le manque de support pour la pause du flux. Mon application a l'obligation de prendre en charge la pause sur le flux en ligne.

10
StackOverflower

Si votre cas d'utilisation est compatible avec les licences GPL/LGPL, VLC devrait être exactement ce dont vous avez besoin. VLC est capable de diffuser depuis votre URL sur un réseau 3G avec un délai d'environ 1 seconde.

Étape 1: Téléchargez le code source de VLC et compilez-le conformément à la instruction

Étape 2: La classe la plus importante est org.videolan.vlc.audio.AudioServiceController, appelée depuis org.videolan.vlc.gui.MRLPanelFragement.processUri() --> org.videolan.vlc.util.Util.openStream(Context, String) --> AudioServiceController.load(String, boolean). Vous pouvez supprimer tout le code inutile autre que AudioServiceController et ses classes de support pour réduire la taille.

8
Kai

Je peux suggérer de passer de MediaPlayer à ExoPlayer . Avec ExoPlayer, il est possible de configurer les paramètres de mise en mémoire tampon comme suit:

public static ExoPlayer newInstance(int rendererCount, int minBufferMs, int minRebufferMs) {
  return new ExoPlayerImpl(rendererCount, minBufferMs, minRebufferMs);
}

minBufferMS signifie une durée minimale de données qui doivent être mises en mémoire tampon pour que la lecture puisse démarrer ou reprendre à la suite d'une action de l'utilisateur telle qu'une recherche.

minRebufferMs signifie une durée minimale de données qui doivent être mises en mémoire tampon pour que la lecture reprenne après l’appel d’un rebuffeur (c’est-à-dire un rebuffeur dû à l’épuisement de la mémoire tampon et non à une action de l’utilisateur, telle que le démarrage de la lecture ou la recherche).

Les valeurs par défaut sont 500 et 5000, respectivement.

2
Dekra

Vous devez éviter le lecteur multimédia pour les flux de radio en direct.

J'ai utilisé la bibliothèque suivante et cela fonctionne très bien: https://code.google.com/p/aacdecoder-Android/

1
Bojan Kseneman

Il y a 2 types de retard dans le streaming a. est le délai de mise en mémoire tampon qui est le délai de démarrage et b. est le délai de diffusion. 

Dans le cas d'un lecteur multimédia, le flux met 1 minute pour se mettre en mémoire tampon. Il faut donc d’abord voir comment réduire le temps requis pour remplir le tampon. Je ne sais pas si cela est possible dans le code du lecteur multimédia d'Android pour configurer la taille de la mémoire tampon. 

Cependant, si nous essayons d'utiliser la bibliothèque de décodeurs AAC pour Android ( https://code.google.com/p/aacdecoder-Android/downloads/detail?name=aacdecoder- Android-0.8.Zip), nous avoir la disposition pour remplir le tampon d'entrée.

PL. reportez-vous à l'extrait de code ci-dessous, vous pouvez remplir la capacité de la mémoire tampon d'entrée en fonction de vos besoins, puis lancer la lecture. Puisque nous avons le contrôle sur la capacité du tampon d’entrée, nous pouvons essayer de réduire le délai de démarrage de la lecture. PL. vérifiez si cela peut vous aider. 

 /**
 * Sets the audio buffer (AudioTrack) capacity.
 * The capacity can be expressed in time of audio playing of such buffer.
 * For example 1 second buffer capacity is 88100 samples for 44kHz stereo.
 * By setting this the audio will start playing after the audio buffer 
   is    first filled.
 *
 * NOTE: this should be set BEFORE any of the play methods are called.
 *
 * @param audioBufferCapacityMs the capacity of the buffer in milliseconds
 */
  public void setAudioBufferCapacityMs( int audioBufferCapacityMs ) {
    this.audioBufferCapacityMs = audioBufferCapacityMs;
  }
0
shri

je vais poster comment je le fais et houe ça donne une différence. ce n'est pas un élément sonore en temps réel (c'est un mp3 d'une API en ligne, mais c'est environ 4-6mb), donc ça peut varier, mais cela prend moins de 3-5 secondes pour charger sur ma VM genimotion.

je sais que c'est presque le même que votre code. peut-être que si vous pouviez partager l'URL ou une adresse similaire donnant les mêmes problèmes, je pourrais le tester dans mon application.

runThread(url);//ran on the oncreate.


 private void runThread(final String url) {
    new Thread() {
        public void run() {
            mediaPlayer  = new MediaPlayer();//mediaplayer is a global variable.
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

                try{
                    mediaPlayer.setDataSource(url);

                    mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                        @Override
                        public void onCompletion(MediaPlayer mediaPlayer) {
                            //audio did finish.

                        }
                    });
                    mediaPlayer.prepare(); // might take long! (for buffering, etc)
                    duration = mediaPlayer.getDuration();
                    mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                        @Override
                        public void onPrepared(MediaPlayer mp) {
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {

                                    //here you should start playing it.
                                }
                            });
                        }
                    });
                }
                catch(Exception e)
                {

                }


            }
    }.start();
}

testé sur un lien 4 avec Jelly Bean, réponses temporelles similaires.

0
CptEric

Si vous êtes prêt à dépenser quelques dollars dans une bibliothèque, je vous recommande Bass Il contient un ensemble complet d’appels d’API que vous pouvez intégrer et une documentation solide. Il existe une version shareware que vous pouvez tester.

Si vous n'êtes pas disposé à dépenser $. Je recommande vivement VLC @Kai, car à l'avenir, vous pourrez étendre votre application pour diffuser de la vidéo en streaming. J'ai déjà travaillé avec l'API avant d'effectuer un flux en direct pour mon aquarium. Kai vous a fourni les liens nécessaires.

Découvrez ce link pour plus d'informations.

0