Android媒体播放器需要很长时间来准备和缓冲。

27

我的应用程序在准备和缓冲音频流时需要很长时间。我看过这个问题Why does it take so long for Android's MediaPlayer to prepare some live streams for playback?,但它只是说人们遇到了这个问题,没有说明如何解决这个问题。

我在所有版本的Android上都遇到了这个问题,从2.2测试到4.1.2。

该流以适合移动和3G连接的比特率传输。相同的流在等效的iOS应用程序中仅需不到一秒钟即可开始缓冲。

有没有办法指定应该缓冲多长时间?我知道“Tune In”收音机应用程序提供了这个功能(https://play.google.com/store/apps/details?id=tunein.player)。

谢谢。

编辑:我再次测试并发现这只发生在运行Gingerbread及以上版本(≥2.3)的设备上。我知道Android将底层框架从OpenCore更改为StageFright。那么我该如何优化媒体框架呢?似乎老旧的HTC Wildfire可以准备、流和播放,速度比全新的HTC One X和Nexus 7快10倍,这似乎是不对的。


我没有一个确切的答案,但这会帮助你的应用程序让用户感到更少的沮丧。 (https://dev59.com/emw15IYBdhLWcg3weLwF#42042218) - LiTTle
3个回答

16

我已经苦苦思考这个问题数月。最终我找到了解决方案。

真正的问题在于MediaPlayer类的实现方式。特别是MediaPlayer缓冲数据的方式。这就是为什么解决方案是创建自己的缓冲区,将其保存到临时文件中并将其提供给MediaPlayer。

本教程和源代码详细说明如何操作。 http://androidstreamingtut.blogspot.nl/2012/08/custom-progressive-audio-streaming-with.html

通过适应此代码,可以轻松创建更好的流媒体播放器。

Google开发者们确实搞砸了。

编辑:该答案相对较旧。现在我建议不要使用 MediaPlayer ,而应改用 ExoPlayer 。它具有可扩展性、稳定性,并可以播放多种不同类型的媒体。您可以在此处找到它:https://github.com/google/ExoPlayer/


1
请注意:这种解决方案并不适用于所有情况,因为有时MediaPlayer在暂停、加载新缓冲区和重新启动时会出现“卡顿”的情况。MediaPlayer只是一个编写不良的类。 - Juan Carlos Ospina Gonzalez
谢谢,这听起来可能是一个合适的替代方案,不过,我现在已经开始在我的应用中使用FFMpeg了。 - SteveEdson
嗨 SteveEdson,你正在使用来自William Seemann的ServeStream代码吗?为什么你没有选择流代理解决方案呢? - burakk
是的,我的应用程序需要能够播放多种不同的编解码器和格式,并且需要能够高效地进行流媒体传输,因此Williams的示例似乎是一个明智的方法。 - SteveEdson

9

由于Android MediaPlayer类不提供对缓冲区大小等更低级别设置的访问权限,因此实际上并没有太多可以做的。唯一的替代方案是使用AudioTrack和像FFmpeg这样的库制作自己的播放器以进行解码。


谢谢!自从我提出这个问题以来,我得出了结论,我需要使用FFMpeg库。我没有听说过AudioTrack,所以我会研究一下这个。我正在努力弄清楚如何在我的应用程序中实现FFMpeg,但我想这是另一个问题了。 - SteveEdson
2
Steve,我开发了一个开源的Android应用程序,很可能可以实现你想要的功能。我还刚刚添加了FFmpeg支持,因此我可以流传输像mms://这样的协议。在这里查看代码:http://sourceforge.net/projects/servestream/ 。如果您有任何问题,可以随时通过SourceForge与我联系。希望这可以帮到你。 - William Seemann
1
需要注意的一点是,如果您使用FFMPEG,您可能需要开源您的项目(取决于您使用的编解码器是GPL还是LGPL许可证)。请阅读此处以获取更多信息:http://ffmpeg.org/legal.html - ajacian81
1
嗨,William,我在我的Note 3(Android版本4.3)上尝试了你的媒体播放器,仍然出现相同的问题,播放音乐约一秒钟,然后等待7*8秒并恢复...这与普通MediaPlayer实现相同。我该如何修复它,通过修改缓冲区大小?在DownloadTask类(DownloadPlayer.java)中。 - burakk
我和burakk得到了完全相同的结果。我使用Android的次数越多,就越失望。 - Jameson

0

我建议的一件事是尝试编码。例如,对于MP4文件,请确保MOOV原子位于文件开头(在S/O上有足够多的关于如何使用ffmpeg等工具实现此操作的问题)。对于MP3文件,您可以尝试不同的编解码器或比特率。

例如,您可以尝试在线找到的许多音频文件,如果发现其中一个不需要很长时间缓冲,那么可以尝试以相同的方式对您的文件进行编码。


2
感谢您的建议,但很遗憾在这种情况下,它不是一个合适的选项,因为流是由提供方控制的,超出了我的控制范围。如果我能够控制这些流,这个方法可能会奏效。 - SteveEdson
是的,我正在尝试按照NDK食谱作为指南完成这项任务。如果您有任何好的教程可以帮助我完成设置,请提供链接。我无法相信Android平台在看似微不足道的任务上如此不足,以至于你必须费尽心思地从不同的平台移植代码。 - Juan Carlos Ospina Gonzalez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接