48 votes

Pourquoi le MediaPlayer d'Android met-il si longtemps à préparer certains flux en direct pour la lecture ?

Je constate de grandes différences dans le temps que prend le MediaPlayer Android pour se préparer à la lecture d'un flux en direct avec différents flux.

Les données concrètes

J'ai ajouté la journalisation entre prepareAsync() et le rappel onPrepared(MediaPlayer mp) et testé plusieurs flux plusieurs fois chacun. Les temps pour chaque flux étaient très cohérents (+/- une seconde), et voici les résultats :

  1. Flux de nouvelles MPR : 27 secondes (http://newsstream1.publicradio.org:80/)
  2. Flux de musique classique MPR : 15 secondes (http://classicalstream1.publicradio.org:80/)
  3. MPR The Current stream : 7 secondes (http://currentstream1.publicradio.org:80/)
  4. Flux PRI : 52 secondes (http://pri-ice.streamguys.biz/pri1)

Les tests ont été effectués sur un Nexus S avec Android 2.3.4 sur une connexion 3G (~1100 Kbps).

La lecture de fichiers audio MP3 non diffusés en continu ne pose pas de problème.

Voici des extraits de la façon dont je joue les flux :

Préparez MediaPlayer :

...
mediaPlayer.setDataSource(playUrl);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.prepareAsync();
...

Puis dans onPrepared(MediaPlayer mp) :

mediaPlayer.start();

Pourquoi la préparation de certains cours d'eau prend-elle autant de temps que celle d'autres ? Les données ci-dessus semblent suggérer que pourrait se fonder sur le montant de données qui ont été mises en mémoire tampon et non pas la durée du contenu audio mis en mémoire tampon. Est-ce vraiment possible ?

Mise à jour : J'ai testé le streaming en direct sur des appareils physiques avec Android 1.6, 2.2 et 2.3.4 et des émulateurs avec 1.6, 2.1, 2.2, 2.3.1 et 2.3.3. Je ne vois le long délai que sur 2.3.3 et 2.3.4. Les versions plus anciennes commencent la lecture dans les 5 secondes.

0voto

LiTTle Points 943

Lorsque j'ai eu ce problème, j'ai décidé de tester si le flux est disponible avant d'ouvrir le lecteur. Si vous faites attendre l'utilisateur pendant un long moment et que la musique démarre, c'est ok (ça ne l'est pas, mais disons que c'est ok). Le pire scénario est de le faire attendre longtemps et la musique ne démarrera jamais ! Donc, nous avons 2 situations :

  • Le scénario de diffusion en direct, comme une station de radio.
  • Le fichier mp3 enregistré qui est disponible en ligne.

Au scénario radio nous pourrions vérifier si le port accepte les connexions (état ouvert/fermé). S'il est ouvert, préparez le lecteur pour la musique, sinon ne le préparez pas du tout.

public static boolean isLiveStreamingAvailable() {
        SocketAddress sockaddr = new InetSocketAddress(STREAMING_HOST, STREAMING_PORT);
        // Create your socket
        Socket socket = new Socket();
        boolean online = true;
        // Connect with 10 s timeout
        try {
            socket.connect(sockaddr, 10000);
        } catch (SocketTimeoutException stex) {
            // treating timeout errors separately from other io exceptions
            // may make sense
            return false;
        } catch (IOException iOException) {
            return false;
        } finally {
            // As the close() operation can also throw an IOException
            // it must caught here
            try {
                socket.close();
            } catch (IOException ex) {
                // feel free to do something moderately useful here, eg log the event
            }

        }
        return true;
    }

Au scénario de fichier mp3 les choses sont un peu différentes. Vous devez vérifier le code de réponse qui suit la requête http.

public static boolean isRecordedStreamingAvailable() {
        try {
            HttpURLConnection.setFollowRedirects(false);
            // note : you may also need
            //        HttpURLConnection.setInstanceFollowRedirects(false)
            HttpURLConnection con =
                    (HttpURLConnection) new URL(RECORDED_URL).openConnection();
            con.setRequestMethod("HEAD");
            return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
        }
        catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X