10

我正在为 HTML5 音频完整的 .aspx 页面提供二进制数据。该文件可以播放,但在 Safari (iPad)、Chrome 和 Firefox 中,SeekBar 和重播存在问题。
编辑我已经简化了(希望不是太多)代码和完整的列表(页面文件名显然是 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提供了标头。<audio>当直接访问文件或通过 .aspx 页面访问文件时,两个标记启用比较行为。

问题是如何提供数据以<audio>在所有必需的浏览器(ff、safari、chrome、IE9+)上正确地标记行为。

问题

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

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

注意 我正在寻找如何在 IE(9+) 和 Safari (Pad) 中使用 HTML5 音频播放 .m4a 中的其他连接问题的解决方案?

4

1 回答 1

11

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

完整的故事

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

    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-Disposition添加其他标题( , Accept-Ranges, )可能很方便,Access-Control-Allow-Origin但目的是尽可能简单地提供解决方案。

吸取的教训:如果我没有被固定<audio>并也在寻找<video>,我会更快地找到解决方案。

于 2013-08-22T15:08:02.763 回答