Ошибка при буферизации MediaPlayer при потоковой передаче аудио

Я использую MediaPlayer для потоковой передачи по протоколу HTTP. На Lollipop мой поток занимает около минуты, чтобы начать, что неприемлемо. Это займет около 20 секунд на Киткате, что уже больно, но теперь стало непригодным.

Существует хорошо известная проблема с этим компонентом, связанным с буферизацией: количество байтов в буфер закодировано и не может быть изменено.

Мой код действительно стандартный

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

И на подготовленный я делаю

player.start();

Я слышал об альтернативах как GStreamer, но я не мог заставить его работать в Windows.

Интересно, есть ли у кого-нибудь рабочее решение для потоковой передачи по протоколу HTTP с приемлемой задержкой запуска.

ИЗМЕНИТЬ

Я тестировал ExoPlayer, но более низкое начальное время, которое я получаю, составляет 15 секунд. Игрок застревает в состоянии "подготовки" (не буферизации, которое позже пока я вижу).

ИЗМЕНИТЬ

Формат потока AAC

ИЗМЕНИТЬ

Я тестировал https://code.google.com/p/aacdecoder-android/, но единственной проблемой, с которой связана эта библиотека, является отсутствие поддержки для потоковой паузы. Это требование моего приложения поддерживать паузу в онлайн-потоке.

Ответ 1

Если ваш вариант использования совместим с лицензиями GPL/LGPL, тогда VLC должен быть именно тем, что вам нужно. VLC может передавать ваш URL-адрес в сети 3G с задержкой ~ 1 с.

Шаг 1: Загрузите исходный код VLC и выполните компиляцию в инструкция

Шаг 2: Самый важный класс - org.videolan.vlc.audio.AudioServiceController, который был вызван из org.videolan.vlc.gui.MRLPanelFragement.processUri() --> org.videolan.vlc.util.Util.openStream(Context, String) --> AudioServiceController.load(String, boolean). Вы можете удалить весь ненужный код, отличный от AudioServiceController, и его классы поддержки, чтобы уменьшить размер

Ответ 2

Я могу предложить переключиться с MediaPlayer на ExoPlayer. С ExoPlayer можно настроить параметры буферизации следующим образом:

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

minBufferMS означает минимальную продолжительность данных, которые должны быть буферизованы для воспроизведения, чтобы начать или возобновить действие пользователя, например поиск.

minRebufferMs означает минимальную продолжительность данных, которые должны быть буферизованы для воспроизведения, чтобы возобновить после того, как игрок вызвал повторителя (т.е. отбойщик, который возникает из-за истощения буфера, а не из-за действия пользователя, такого как начало воспроизведения или поиск).

Значения по умолчанию - 500 и 5000 соответственно.

Ответ 3

Вам следует избегать медиаплеера для прямых радиопотоков.

Я использовал следующую библиотеку, и она отлично работает: https://code.google.com/p/aacdecoder-android/

Ответ 4

В потоке a есть 2 вида задержки. является задержка буферизации, которая является задержкой запуска и b. является задержкой вещания.

В случае медиаплеера поток берет 1 минуту для буфера. Поэтому нам сначала нужно посмотреть, как сократить время, необходимое для заполнения буфера. Я не уверен, что это возможно в коде Media Player для Android, чтобы настроить размер буфера.

Однако, если мы попытаемся использовать библиотеку декодера AAC для android (https://code.google.com/p/aacdecoder-android/downloads/detail?name=aacdecoder- android-0.8.zip), то у нас есть условие для заполнения входной буфер.

Pl. обратитесь к фрагменту кода ниже, вы можете заполнить емкость входного буфера, исходя из вашего требования, а затем вы можете начать воспроизведение. Поскольку мы контролируем емкость входного буфера, мы можем попытаться уменьшить временную задержку, чтобы начать воспроизведение. Pl. проверьте, поможет ли это вам.

 /**
 * 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;
  }

Ответ 5

Я опубликую, как я это делаю, и мотыга это дает разницу. это не звуковой элемент в реальном времени (это mp3 из онлайн-апи, но он около 4-6 мб), поэтому он может меняться, но занимает менее 3-5 секунд, чтобы загрузить на моем genimotion VM.

Я знаю это почти так же, как ваш код. возможно, если бы вы могли поделиться URL-адресом или похожим с теми же проблемами, я мог бы проверить его в своем приложении.

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();
}

, протестированный на nexus 4 с желе bean, аналогичные ответы времени.

Ответ 6

Если вы готовы потратить немного $на библиотеку, я рекомендую Bass. Он имеет полный набор вызовов API, которые вы можете интегрировать и также прочная документация. Существует условно-бесплатная версия, которую вы можете проверить.

Если вы не хотите тратить $. Я настоятельно рекомендую VLC @Kai, а также в будущем вы можете расширить свое приложение для потокового видео с ним. Я работал с API раньше, чтобы выполнить живой поток для моего аквариума. @Kai предоставил вам необходимые ссылки.

Обратитесь к этой ссылке для получения дополнительной информации.