【发布时间】:2017-03-30 08:01:38
【问题描述】:
我正在创建一个应用程序,其中多个设备可以在 LAN 中相互连接并播放来自彼此设备的歌曲。
现在,当设备 A 向设备 B 请求歌曲时,B 通过套接字将歌曲文件发送回 A。歌曲下载完成后,A 开始使用MediaPlayer 播放它。
现在的问题是,即使在高速 LAN 上,也可能需要几秒钟才能完成歌曲的提取,因此在选择歌曲和实际开始播放之间存在明显的延迟。
我想找到一种在歌曲仍在下载时播放歌曲的方法。以下是我找到的一些可能的解决方案,但由于某些原因无法探索:
-
在
MediaPlayer文档中,我注意到一个构造函数采用MediaDataSource实现,允许我在 MediaPlayer 需要时手动返回部分媒体文件,因此我可以推迟返回一个字节,直到它完成下载(如果它还没有完成下载),实际上就像一个“缓冲”动作。这似乎是一个解决方案,但不幸的是,我的应用程序的 minSdk 设置为 16,MediaDataSource仅适用于 23 及以上,所以我无法尝试。 -
一种选择是使用
MediaPlayer的setDataSource(FileDescriptor fd, long offset, long length)方法。这将允许我告诉 MediaPlayer 只播放歌曲的某个字节。这样,我可以等待文件的更多部分(或整个文件)可用,然后使用setNextMediaPlayer()并传入一个新的 MediaPlayer 对象,该对象准备整首歌曲并一直寻找到之前的媒体播放器对象将停止播放,以便进行无缝过渡。 但这还有另一个问题。我需要能够计算在第一个不完整的媒体播放器对象的最后一个指定字节处将达到的毫秒位置。否则我不知道要寻找下一个媒体播放器对象的位置以获得无缝过渡。对于有损格式,这种计算似乎是不可能的。 -
我真的不知道这个选项是否有效,我只是在做假设。我注意到
setDataSource()需要一个 Uri。如果该 Uri 指向手机上的文件,则媒体播放器只会加载整个文件。但是,如果 Uri 指向 Internet 上需要流式传输的音频文件,它会自行计算出来并处理下载和缓冲的所有细节。所以我想知道的是,是否可以将设备 B 上的歌曲作为 Uri 暴露给设备 A,以便媒体播放器将其视为互联网上的歌曲?一直以来,我都在使用套接字并手动将文件从一台设备复制到另一台设备,所以我不知道这将如何工作。谁能解释一下这是否可行?实际上,我一直没有探索将歌曲从一台设备“流式传输”到另一台设备的方法,这实际上是有原因的。那是因为我想将歌曲缓存在设备 B 上,这样以后如果我切换到另一首歌曲,然后从设备 A 返回之前播放的歌曲,它就不必再次流式传输。它应该只播放缓存的副本。
-
最后,我遇到了
ExoPlayer。它似乎提供了大量的定制。似乎我可以对其类进行自定义实现来处理所有缓冲。但是文档和示例很少,对我来说太复杂了。我不知道如何把它拉下来。对于我想要实现的目标,这个解决方案是否过于复杂?
希望有人可以在这里为我指明正确的方向。
【问题讨论】:
标签: java android streaming android-mediaplayer exoplayer