使用 InputStream 通过网络寻找流式音频的有效方法

Posted

技术标签:

【中文标题】使用 InputStream 通过网络寻找流式音频的有效方法【英文标题】:Efficient way to seek a streaming audio over network with InputStream 【发布时间】:2012-07-26 01:05:47 【问题描述】:

我正在使用jlGui 的 BasicPlayer(它基于 Javasound)播放音频文件。 该文件位于 Samba 共享中,我使用 Jcifs 访问它。它给了我一个InputStream

NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication( ... );

SmbFile f = new SmbFile( ... );
SmbFileInputStream audioIn = new SmbFileInputStream(f);

int bufSize = 8096;//should I use f.length() here?
audioBIS = new BufferedInputStream(audioIn, bufSize);

audioBIS.mark(f.length());

    //call BasicPlayer
play(audioBIS);

我需要能够将指针定位在文件中的任何位置,就像任何普通播放器一样。 我能想到的唯一解决方案是每次需要重新定位指针时使用BufferedInputStream 和标记/重置/跳过的组合。 一旦我打开文件并获取 Stream,我就会调用 mark() 方法,以便后续的 reset() 将在开始时重新定位我。然后有了skip(),我就可以去我想去的地方了。

audioBIS.reset();
audioBIS.skip(newBytePosition);

我的问题是,只有当我指定一个足够大的缓冲区来包含整个文件时,skip() 调用才能正常工作。

有没有更有效的方法来做到这一点?

【问题讨论】:

【参考方案1】:

我和你现在的路完全一样。案例是我们有一个服务器(和一个 SMB 共享)保存数千个音频文件。这些文件需要在应用程序中可播放。

我从 jCifs 开始,并修改了 BasicPlayer 的源代码来处理 SmbFile,就像处理 File 一样。它工作得很好,但是当涉及到寻找/跳过时,它并没有真正让你大吃一惊。只要您与服务器的连接良好,就应该没问题。

我最终放弃了那个解决方案,而是在服务器上安装了 tomcat6,并部署了一个小而简单的 servlet,它允许在给定位置对文件发出请求。然后,客户端机器会将响应作为 InputStream 并将其传递给 BasicPlayer。它工作得更好,并且播放是即时的。代码略多于此处粘贴的合理范围,但如果您有兴趣,我愿意与您分享。

【讨论】:

您的解决方案听起来很有趣,但我在服务器端没有足够的能力来安装 tomcat。无论如何,我可以想到一个 BasicPlayer 的包装器,它或多或少地做同样的事情,处理 seek 和 getTime 函数。就一个问题。如何根据给定的偏移量生成 Inputstream? here 给出的答案是鼓舞人心的,也暗示了缓存,但我担心我会引入复制巨大数组的开销。 当您说 InputStream 基于给定的偏移量时,您还在谈论 jCifs (SmbFile) 和以字节为单位的偏移量吗? 我指的是您说“客户端机器会将响应作为 InputStream”的部分。您不是说服务器会响应从所需位置开始的输入流吗? 是的,我的应用程序会调用,比如说,mediaserver/stream?fid=50&pos=1000,其中 fid 是文件 ID,pos 是以毫秒为单位的位置。然后 servlet 会接受这个请求,找到与提供的毫秒偏移量相对应的字节偏移量。基于字节偏移,我为文件创建了一个 RandomAccessFile 实例(对应于 fid)并使用 RandomAccessFile#seek 来获取字节位置。从那里我只需将 BufferedOutputStream 返回给客户端应用程序。它很快(几毫秒)并且运行良好一年。 你能给我们看看 servlet 代码吗,我对它是怎么做的很感兴趣。【参考方案2】:

作为替代。您始终可以关闭流并重新创建它。似乎走得很快,如果需要,你会回到位置 0。

因此,请跟踪您的位置。只要你向前移动,保持流并用skip()跳转。一旦您需要再次返回,请关闭该流并创建一个新的并 skip() 到想要的位置。

除非应用程序一直在回跳,否则你应该没问题。

将其封装在一个新的漂亮的自定义流中,您就有了一个支持来回切换的流。

【讨论】:

以上是关于使用 InputStream 通过网络寻找流式音频的有效方法的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 mediaRecorder 流式传输 android 的内部音频+屏幕?

如何使用来自网络套接字的网络音频 API 流式传输音频块?

从网络服务器流式传输音频

naudio 音频流到 html / 网页

将录制的音频从浏览器流式传输到服务器

将音频和视频从 Android 手机流式传输到 RTMP 服务器的最佳方式