【问题标题】:Issue with MediaPlayer buffering time when streaming audio流式传输音频时 MediaPlayer 缓冲时间问题
【发布时间】:2015-06-08 13:53:42
【问题描述】:

我正在使用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 秒。播放器卡在“准备”状态(不是缓冲,到目前为止我看到了)。

编辑

流的格式是AAC

编辑

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

【问题讨论】:

  • 您的流使用什么比特率?例如32 kbps 64 kbps 等
  • @Simas:它使用 32 kbps。我知道这会随着比特率的提高而改善,但似乎不是一个真正的解决方案
  • 你在播放什么格式的音频,AAC?
  • @BojanKseneman:是的,AAC。
  • 可以选择 Web api 吗?

标签: android android-mediaplayer


【解决方案1】:

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

第 1 步: 下载VLC源代码并按照instruction进行编译

第 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 及其支持类之外的所有不必要的代码以缩小尺寸

【讨论】:

  • 我从未听说过这个,我将测试这个解决方案。谢谢
  • kai 在 VLC 播放器中,我们可以选择在直播时暂停。你能请吗?澄清
  • @Kai:你知道是否有使用 android studio 的工作示例吗?我不确定我是否有时间在赏金迫使我选择获胜者之前测试这个解决方案。正如 shri 所说,必须有一个支持暂停的解决方案。
  • @StackOverflower 你能澄清一下你希望暂停直播的行为是什么样的吗?你的意思是我可以暂停直播 x 秒,播放器应该缓冲它并在我再次点击播放时播放它?
  • @StackOverflower 刚刚对其进行了测试,它确实支持上述暂停,有点惊讶。我不知道这个缓冲区的长度是否可以调整。
【解决方案2】:

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

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

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

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

默认值分别为 500 和 5000。

【讨论】:

  • 您有显示缓冲设置的完整示例吗?我记得几个月前我测试了 ExoPlayer,但我找不到在这个主题上取得任何进展的方法。不过我可能看不到它。
  • 这是一个ExoPlayer的demo app,你可以轻松测试缓冲状态github.com/google/ExoPlayer/tree/master/demo
  • 谢谢,我会测试一下。无论如何,我希望您有任何权威来源说明 ExoPlayer 解决了这个问题。我在 google play 上关注了这个问题,没有人提到过 ExoPlayer。不过我会找到的:)
  • 您的示例代码似乎适用于Exoplayer 1。我在Exoplayer 2 中找不到ExoPlayerImpl
  • 在 Android 6.0.1 上使用 ExoPlayer 2 (r2.1.3),使用来自radio.abc.net.au/help/streams 的 mp3、96kbps 流进行测试,我发现延迟最小(
【解决方案3】:

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

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

【讨论】:

  • “您应该避免使用媒体播放器进行直播广播”。 - 只是出于好奇:为什么?是否有任何关于此的文档/文章/任何内容?
  • 我们注意到很多设备上的媒体播放器存在问题。棘手的问题可能与编解码器有关,但使用上述库似乎可以在这些设备上运行。
  • Bojan 有没有办法在acc解码器中配置输入缓冲区大小
  • 当然。有两个方法 aacPlayer.setAudioBufferCapacityMs(343); aacPlayer.setDecodeBufferCapacityMs(3242);注意我刚刚输入了一些愚蠢的值
  • 感谢您的回答。几个月前我测试了这个库,它是完美的,除了一件事:它不允许暂停流,只允许停止。不幸的是,这对我的应用程序产生了影响
【解决方案4】:

流式传输有 2 种延迟是缓冲延迟,即启动延迟和 b。是广播延迟。

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

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

Pl。参考下面的代码sn-p,您可以根据您的要求填充您的输入缓冲区容量,然后您就可以开始播放了。由于我们可以控制输入缓冲区的容量,我们可以尝试减少开始播放的时间延迟。 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】:

我会发布我是如何做到的,并且会有所作为。它不是实时声音项目(它是来自在线 api 的 mp3,但大小约为 4-6mb),因此它可能会有所不同,但在我的 genimotion VM 上加载不到 3-5 秒。

我知道它与您的代码几乎相同。也许如果你可以分享 url 或类似的 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 上进行了测试,类似的时间响应。

【讨论】:

    【解决方案6】:

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

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

    查看此link 了解更多信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-20
      • 1970-01-01
      • 1970-01-01
      • 2012-04-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多