如何正确地为 <audio> 提供数据?

Posted

技术标签:

【中文标题】如何正确地为 <audio> 提供数据?【英文标题】:How to properly provide data for <audio>? 【发布时间】:2013-08-22 13:41:35 【问题描述】:

我正在为 html5 音频完整的 .aspx 页面提供二进制数据。该文件可以播放,但 SeekBar 和在 Safari (iPad)、Chrome 和 Firefox 中重播存在问题。编辑我已经简化(希望不会太多)代码和完整列表是呈现(页面文件名明显是play.aspx)。

<%@ Page Language="C#"  %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    
       if ( Request["filename"] != null)
       
           string FilePath = MapPath(Request["filename"]);
           long fSize = (new System.IO.FileInfo(FilePath)).Length;
           //Headers
           Response.AddHeader("Content-Length",fSize.ToString());
           Response.ContentType = "audio/mp3";
           //Data
           Response.WriteFile(FilePath);
           Response.End();   
       ;      
    
</script>
<body>
    <p>Direct</p>
       <audio controls="controls" preload="none">
         <source src="sound.mp3" type="audio/mp3" />
      </audio>
      <p>Provided</p>
      <audio controls="controls" preload="none">
         <source src="play.aspx?filename=sound.mp3" type="audio/mp3" />
      </audio>
</body>
</html>

所以提供了Content-LengthContent-Type 标头。当直接访问文件或通过 .aspx 页面访问文件时,两个 &lt;audio&gt; 标记启用比较行为。

问题是如何向&lt;audio&gt;标签提供数据,在所有必需的浏览器(ff、safari、chrome、IE9+)上都能正常运行。

问题

Safari (iPad): 当按下播放按钮时,会播放声音,但会出现“Streaming ...”而不是 Seek Bar,并且播放似乎永远持续并且无法重播声音。 Firefox(windows): 搜索栏已显示,但显示的时间越来越长,直到结束,并且在重播时行为正确。Chrome(windows): 搜索栏正确但无法重播。IE10:好的

我发现了类似的问题,但没有答案。从用提琴手观察另一个页面看来,标题Accept-Ranges: bytesContent-Range: bytes 0-8100780/8100781 可以提供帮助。但是提供必要的功能似乎太难了,所以我没有尝试。

注意 我正在寻找How to play .m4a with HTML5 audio in IE(9+) and Safari (Pad)?中其他相关问题的解决方案@

【问题讨论】:

你应该看看 jPlayer,它已经为你内置了所有内容,并为不支持 HTML5 的浏览器提供了备用jplayer.org @mattytommo:jPlayer 不错。但是我想在现在的浏览器上我会面临与 HTML5 音频相同的问题(源数据未被控件正确接受)。 【参考方案1】:

简单回答:需要处理浏览器range request

完整故事

比较Fiddler捕获的Firefox和IIS之间的通信时,我注意到直接链接的响应状态是206 Partial Content,而间接链接的响应状态是200 OK。 对请求的更仔细分析表明,Firefox 请求 Range: bytes=0- 和 iPad Range: bytes=0-1 以及后来的 Range: bytes=0-fullsize (Capture Traffic from ios Device)。 设置 Response.StatusCode = 206 足以欺骗 Firefox 而不是 Safari。但我知道关键信息,剩下的很简单。有必要遵守range 请求,请参阅:SO:HTML5 video will not loop。我在Aha! #1 – ASP.NET ASHX Video Streaming for HTML5 Video 中找到了如何做的解释。所以新代码是(仅显示活动部分其余与答案相同):

    protected void Page_Load(object sender, EventArgs e)
    
       if ( Request["filename"] != null)
       
           string FilePath = MapPath(Request["filename"]);
           long fSize = (new System.IO.FileInfo(FilePath)).Length;
           long startbyte = 0;
           long endbyte=fSize-1;
           int statusCode =200;
           if ((Request.Headers["Range"] != null))
           
               //Get the actual byte range from the range header string, and set the starting byte.
               string[] range = Request.Headers["Range"].Split(new char[]  '=','-');
               startbyte = Convert.ToInt64(range[1]);
               if (range.Length >2 && range[2]!="")  endbyte =  Convert.ToInt64(range[2]);
               //If the start byte is not equal to zero, that means the user is requesting partial content.
               if (startbyte != 0 || endbyte != fSize - 1 || range.Length > 2 && range[2] == "")
               statusCode = 206;//Set the status code of the response to 206 (Partial Content) and add a content range header.                                    
           
           long desSize = endbyte - startbyte + 1;
           //Headers
           Response.StatusCode = statusCode;
           Response.ContentType = "audio/mp3";
           Response.AddHeader("Content-Length",desSize.ToString()); 
           Response.AddHeader("Content-Range", string.Format("bytes 0-1/2", startbyte, endbyte , fSize));
           //Data
           Response.WriteFile(FilePath,startbyte,desSize);
           Response.End(); 
       ;      
    

添加其他标头(Content-DispositionAccept-RangesAccess-Control-Allow-Origin)可能很方便,但目的是尽可能简单地提供解决方案。

吸取的教训:如果我没有固定到&lt;audio&gt; 并且还寻找&lt;video&gt;,我会更快地找到解决方案。

【讨论】:

我遇到了无法使用公共 url 访问文件的情况。您提供的示例有效并且很棒。但它强制音频控制器接管整个浏览器窗口。如果我想在现有页面中使用自定义布局和显示元数据提供音频控制器怎么办? @JakobLithner:解决方案被简化为一页。理解的关键大概是src="play.aspx?filename=sound.mp3"。因此,您可以有不同的页面来提供数据(包含呈现的 Page_Load)和控制所在的页面。 非常感谢!这个解决方案非常适合 Safari MacOS、FF 和 Chrome。

以上是关于如何正确地为 <audio> 提供数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何正确地为 PyTorch 中的嵌入、LSTM 和线性层提供输入?

如何通过 Django 正确地为我的 React 生产构建提供服务。当前配置存在 MIME 类型问题

<audio> 的正确加载

从 Javascript 播放 <audio> + <video> 的正确方法

HTML5中 video和audio这两个标签是干嘛的,如何设置其属性?

在iOS微信浏览器中自动播放HTML5 audio(音乐)的2种正确方式