如何使用 Servlet 流式传输 MP3、MP4、AVI 等音频/视频文件

Posted

技术标签:

【中文标题】如何使用 Servlet 流式传输 MP3、MP4、AVI 等音频/视频文件【英文标题】:How to stream audio/video files such as MP3, MP4, AVI, etc using a Servlet 【发布时间】:2012-11-15 07:19:28 【问题描述】:

我想使用 servlet 将我的音频/视频文件流式传输到网络。

我尝试使用以下 servlet:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
    File file = new File("/Users/myfolder/Documents/workspace/love.mp3");
    response.setContentType(getServletContext().getMimeType(file.getName()));
    response.setContentLength((int) file.length());
    Files.copy(file.toPath(), response.getOutputStream());

还有以下 html

<a href="/media" data-format="mp3 ogg">Click Here!</a>

然而,播放器只是在加载……加载……加载……

这是怎么引起的,我该如何解决?

【问题讨论】:

【参考方案1】:

很多媒体播放器要求服务器支持所谓的 HTTP 范围请求。 IE。它必须能够根据请求返回带有Range 标头的媒体文件的特定部分。例如,在 10MB 长的文件中,只有索引 1000 处的字节直到 2000 为止。这对于许多媒体播放器来说是强制性的,以便能够足够快地跳过特定范围的媒体流和/或通过创建多个连接来提高缓冲速度,每个连接都请求文件的不同部分。

然而,这是 servlet 中的大量附加代码,需要充分了解 HTTP Range 规范。通常 servlet 容器(Tomcat、JBoss AS、Glassfish 等)自己的默认 servlet 已经支持这个。因此,如果有一种方法可以通过标准方式将媒体文件夹发布到网络上,这样您就不需要为此自行开发一个 servlet,那么我会走这条路。

不清楚您使用的是哪个 servletcontainer,因此我将在此示例中假设 Tomcat:

    只需将 love.mp3 文件放到 web 项目的公共 web 内容中,这样它就可以被 &lt;a href="love.mp3"&gt; 使用,而不需要整个 servlet。

    或者,将love.mp3 文件放在Tomcat/webapps 文件夹的新子文件夹中,例如Tomcat/webapps/media/love.mp3。这样就可以通过&lt;a href="/media/love.mp3"&gt; 获得。

    或者,将love.mp3 文件放在磁盘上的其他位置,例如/path/to/media/love.mp3 并将 /media 文件夹添加为新上下文,方法是将以下行添加到 Tomcat 的 /conf/server.xml

     <Context docBase="/path/to/media" path="/media" />
    

    这样&lt;a href="/media/love.mp3"&gt; 也可以使用。

无论哪种方式,Tomcat 自己的DefaultServletRange 请求都有适当的支持,将用于流式传输内容。

但是如果绝对没有办法使用 servletcontainer 自己的默认 servlet,那么您需要重写您的 servlet 代码,使其正确支持Range 请求。您可以从 Tomcat DefaultServlet 和 OmniFaces FileServlet 等开源示例中获得灵感。

另见:

Video Using HTML 5 and servlet

【讨论】:

对不起。我错过了重要信息。这不是路径问题......因为当我在没有 HTML5 音频播放器(可访问音频播放器)的情况下运行服务器时它完全可以工作。我想要的是使用 servlet 流式传输到 html5 播放器。 是的,我知道。您阅读理解我的回答了吗?您的 servlet 必须支持 Range 请求。然而,servletcontainer 的默认服务已经支持它,因此最好通过将文件直接发布到网络来使用它。 好的.. 感谢您的回答,但似乎需要时间来理解。我会试试的。 有没有办法为 DefaultServlet 提供的静态内容实现请求过滤器? @jwi 您可以编写一个过滤器,对DefaultServlet 执行forward,然后调用chain.doFilter(request, response) 失败。

以上是关于如何使用 Servlet 流式传输 MP3、MP4、AVI 等音频/视频文件的主要内容,如果未能解决你的问题,请参考以下文章

如何将 .MP4 文件等本地文件流式传输到 Chrome Cast?

用于 chrome 中 html5 视频的 Servlet 流式传输 mp4

如何使用 MPEG DASH 流式传输和捕获 MP4 文件?

如何在使用 NAudio 流式传输 mp3 时获取当前时间?

如何以 mp3 格式从麦克风流式传输声音?

如何使用套接字传输 pdf、mp3 或 mp4 文件?