流式传输音频时 MediaPlayer 缓冲时间问题

Issue with MediaPlayer buffering time when streaming audio

我正在使用 MediaPlayer 通过 HTTP 传输广播。在 Lollipop 上,我的流需要大约一分钟才能开始,这是不可接受的。在 Kitkat 上大概需要 20 秒,这本来就很痛苦,但现在变得无法使用了。

此组件有一个 well known problem 与缓冲相关:要缓冲的字节数已硬编码且无法更改。

我的代码真的很标准

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

我准备好了

player.start();

我听说过 GStreamer 的替代方案,但我无法在 Windows 上使用它。

我想知道是否有人有一个有效的解决方案来通过 HTTP 流式传输广播,并具有适当的启动延迟。

编辑

我测试了 ExoPlayer,但我得到的较低启动时间是 15 秒。播放器卡在 "preparing" 状态(没有缓冲,到目前为止我才看到)。

编辑

流的格式是 AAC

编辑

我测试了 https://code.google.com/p/aacdecoder-android/ 但这个库唯一的问题是不支持流暂停。我的应用程序要求支持在线流暂停。

我可以建议从 MediaPlayer 切换到 ExoPlayer。使用 ExoPlayer 可以设置缓冲参数如下:

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

minBufferMS 表示必须缓冲的最短数据持续时间,以便在用户操作(例如搜索)后开始或恢复播放。

minRebufferMs 表示播放器调用 rebuffer 后必须缓冲以恢复播放的最短数据持续时间(即由于缓冲区耗尽而不是由于用户操作(例如开始播放或搜索)而发生的重新缓冲) .

默认值分别为 500 和 5000。

如果您的用例与 GPL/LGPL 许可证兼容,那么 VLC 应该正是您所需要的。 VLC 能够在 3G 网络上从您的 URL 流式传输,延迟仅约 1 秒。

第 1 步: 下载 VLC 源代码并根据 instruction

编译

第 2 步: 最重要的 class 是 org.videolan.vlc.audio.AudioServiceController,它是从 org.videolan.vlc.gui.MRLPanelFragement.processUri() --> org.videolan.vlc.util.Util.openStream(Context, String) --> AudioServiceController.load(String, boolean) 调用的。您可以删除除 AudioServiceController 及其支持 class 之外的所有不必要的代码以缩小尺寸

您应该避免使用媒体播放器播放直播广播。

我使用了以下库并且效果很好:https://code.google.com/p/aacdecoder-android/

推流有2种延迟a。是缓冲延迟,它是启动延迟和 b。是广播延迟。

对于媒体播放器,流缓冲需要 1 分钟。所以我们首先需要看看如何减少填充缓冲区所花费的时间。我不确定 Android 的媒体播放器代码是否可以配置缓冲区大小。

然而,如果我们尝试为 android (https://code.google.com/p/aacdecoder-android/downloads/detail?name=aacdecoder- android-0.8.zip) 使用 AAC 解码器库,那么我们就可以填充输入缓冲区.

请问。参考下面的代码片段,你可以根据你的要求填充你的输入缓冲区容量,然后你就可以开始播放了。由于我们可以控制输入缓冲区容量,因此我们可以尝试减少开始播放的时间延迟。 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;
  }

我会 post 我是怎么做到的,并且会有所不同。它不是实时声音项目(它是来自在线 api 的 mp3,但大约 4-6mb)所以它可能会有所不同,但加载到我的 genimotion VM 上只需不到 3-5 秒。

我知道它和你的代码几乎一样。也许如果你可以分享 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 上测试,时间响应相似。

如果您愿意花一些钱买一个库,我推荐 Bass 它有一套完整的 API 可以集成的调用,还有可靠的文档。有一个共享软件版本,你可以测试。

如果你不愿意花$.我强烈推荐 @Kai 提到的 VLC,将来您也可以扩展您的应用程序以使用它流式传输视频。我之前与 API 合作,为我的水族馆进行现场直播。 @Kai 为您提供了必要的链接。

查看此 link 了解更多信息。