使用 Spring Framework 和 Chrome 设置视频流

jqn*_*qno 8 spring http video-streaming spring-boot

我们正在编写一个 Spring 服务,它使 HTTP 端点可用,通过它可以流式传输来自 Amazon S3 存储的视频(或音频)文件。基本思想是,您可以在 Google Chrome 地址栏中输入一个 url,该服务将从 S3 中获取文件并进行流式传输,这样用户就可以立即开始观看,而无需等待下载完成,并且用户可以单击视频进度条中的随机位置并立即从该位置开始观看视频。

我理解这在理论上应该有效的方式是 Chrome 开始下载文件。该服务以 HTTP 200 响应并包含一个Accept-Ranges: bytes和一个Content-Length: filesize标头。这filesize是已知的,因为我们可以将其作为元数据从 S3 中查询,而无需获取整个文件。包含这些标头会导致浏览器取消下载,并再次请求带有Range: bytes=0-whatever标头的文件(whateverChrome 决定的块大小)。然后服务以 HTTP 206(部分内容)和请求的字节范围进行响应,我们可以轻松确定,因为 S3 支持相同的范围协议。Chrome 然后从服务请求连续的块,直到流结束。

在 Spring 方面,我们将数据发送到 a ResponseEntity<InputStreamResource>(根据这个 SO answer)。

然而,我们在实践中观察到,虽然 Chrome 在几百个字节后取消了它的第一个请求。但是,它会发送带有Range: bytes=0-标头的第二个请求,从而有效地请求整个文件。服务器以 HTTP 206 响应。结果,它只下载了几百字节的视频,并且视频显然没有开始播放。

有趣的是,在 Firefox 中一切正常。不幸的是,我们的应用程序需要支持 Chrome。我们是否遗漏了协议的某些部分?

jqn*_*qno 3

事实证明,我们在响应标头中存在一个相差一的错误Content-Range

\n

语法是Content-Range: bytes start-end/total. 对于totalof 10,如果您想获取整个范围,则需要指定bytes 0-9/10,而不是0-10/10,这就是我们正在做的。

\n

当然,由于实际文件的大小较大,并且这些文件中间的块的实际范围,这个错误比上一段中的人为示例更难注意到...... \xe0\xb2\xa0_\ xe0\xb2\xa0

\n