将 mp3 从服务器流式传输到 html5 音频时传递持续时间

Posted

技术标签:

【中文标题】将 mp3 从服务器流式传输到 html5 音频时传递持续时间【英文标题】:Passing duration when streaming mp3 from server to html5 audio 【发布时间】:2012-08-21 14:04:30 【问题描述】:

我有一个 node.js 服务器即时转换和流式传输 mp3。 我正在使用 html5 音频标签来使用此流,而我遇到的问题是音频元素在播放完整个内容(显然)之前不知道 mp3 的持续时间。 有什么办法,因为我的服务器在发送它之前知道 mp3 的持续时间,我可以在来自服务器的响应的标头中包含持续时间或其他东西,以便使用它的客户端知道持续时间?

谢谢

【问题讨论】:

我想知道浏览器是否可以从元信息和内容长度中弄清楚这一点。除非有某种新的 http 标头,否则这将是唯一可能的方法。 是的,也许,至少这是我所希望的。有没有办法覆盖实际计算这个的音频标签的功能?因为那样我就可以添加这个逻辑...... 【参考方案1】:

一岁半了,但我上周才遇到这个,所以......

206 Partial Content 支持添加到您的http 服务器实现中,这个问题就消失了。在内容中寻找也开始起作用了..

音频和视频 html5 标签正在发出 Range 请求:

Range: bytes=0-  or..
Range: bytes=0-12345

spec 正确响应的重要部分:

HTTP/1.1 206 PARTIAL CONTENT
Accept-Ranges: bytes
Content-Range: bytes 0-12345

没有 206 响应代码,您将获得您遇到的行为。

我在 Perl 中这样做,其中 $request 包含来自客户端的请求标头,已标准化。例如,SERVER_PROTOCOL 在大多数情况下包含 'HTTP/1.1'

my $crlf = "\012";
if ( $request->RANGE && $request->RANGE =~ /bytes=(\d*)-(.*)$/ ) 
    $offset = $1;
    $end = $2 || $size; # end is optional in the spec.  Default to size.
    $header = $request->SERVER_PROTOCOL . ' 206 PARTIAL CONTENT' . $crlf .
    'Content-Range: bytes ' . $offset . '-' . $end . '/' . $size . $crlf;
 else 
    $header = $request->SERVER_PROTOCOL . ' 200 OK' . $crlf;

my $left = $end - $offset;
$header .= 'Server: ' . $SERVER_NAME . $crlf .
    'Accept-Ranges: bytes' . $crlf . 
    'Date: ' . $http_date . $crlf .
    'Content-Type: ' . ($self->simplemime($raw_path) || magic($fh)) . $crlf .
    'Last-Modified: ' . $http_date . $crlf .
    'Content-Length: ' . $size . $crlf .
    'Connection: Keep-Alive' . $crlf .
    'Cache-Control: max-age=' . $EXPIRE . $crlf . $crlf;

您当然必须通过为请求的内容提供适当的字节范围来满足请求。 客户端通常还会“停止”下载以匹配播放速度,因此适当的事件驱动服务器(例如 Mojolicious、AnyEvent 或 Node.js)将扩展,而每个连接模型(例如 php)只有 1 个线程不是。 (好吧,我想Ratchet 会进行一些黑客攻击,或者使用Xsendfile)

顺便说一句,大多数范围请求最终只是:

Range: bytes=0- 

这意味着只要他们不能 seek 并且缓存被禁用(并且浏览器实际上支持它..),您实际上只需重写普通 HTTP/1.1 200 响应 HTTP/1.1 206 响应的重要位,它适用于 一些 内容。具体来说,这似乎适用于在文件的 end 处没有所需元数据的内容。对于那些文件类型,我已经看到 Range 请求寻求结束,然后在文件开头重新启动。 出于这个原因,最好只实现实际的搜索,但上述方法确实有效......使用后果自负。

【讨论】:

你知道我怎样才能在 node.js 上得到同样的结果吗?我正在尝试流式传输音频文件,但它给了我这个错误:net::ERR_CONTENT_LENGTH_MISMATCH【参考方案2】:

我认为就目前而言,就广泛支持的解决方案而言,您无法通过单独的请求(或以其他方式在您的链接的某种清单中 - 包含在您使用的播放列表中)发送这些内容例如,指向适当的 URI)。当然,这可以由您的服务器在首次添加歌曲时动态生成,然后从那时起静态提供。

在我正在构建的媒体播放器中,我正在做类似的事情 - 下载一个 json 文件,其中包含通常包含在 .mp3 元数据中的内容(也将支持非 mp3 版本等)。

这远非理想,但这也是 html5 音频/视频在其第一次迭代中无意解决的问题之一。

【讨论】:

以上是关于将 mp3 从服务器流式传输到 html5 音频时传递持续时间的主要内容,如果未能解决你的问题,请参考以下文章

查找带有 HTML5 <audio> 标签的流式 MP3 文件

通过 Azure 媒体服务从 Azure 云存储 Blob 流式传输 mp3(仅限音频)

流式传输 MP3 而不是使用 HTML5 音频标签下载它

将音频从 Node.js 服务器流式传输到 HTML5 <audio> 标签

将 MP3 流式传输到 Discord.net 2.0 - 音频速度超快(花栗鼠)。想法?

使用 MPEG DASH 流式传输纯音频 (.mp3) 文件