How to properly provide data for <audio>?

旧街凉风 提交于 2020-01-12 05:27:06

问题


I am serving binary data for HTML5 audio thorough .aspx page. The file can be played but there is a problem with SeekBar and replaying in Safari (iPad), Chrome and Firefox.
Edit I have simplified (hopefully not too much) the code and full listing is presented (page file name is obviously 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>

So Content-Length and Content-Type headers are supplied. Two <audio> tags enable compare behavior when the file is accessed directly or thorough an .aspx page.

The question is how to provide data to <audio> tag behave correctly on all required browsers (ff, safari, chrome, IE9+).

Problems

Safari (iPad): When the play button is pressed the sound is played but there is "Streaming ..." instead of Seek Bar and playing seem to last forever and sound cannot be replayed.
Firefox(windows): Seek Bar is displayed but shows increasing time until the end and behaves correctly when replayed.
Chrome(windows): Seek bar correct but cannot be replayed.
IE10: OK

I have found similar questions on but without an answer. From observing another page with fiddler it seems that header Accept-Ranges: bytes and Content-Range: bytes 0-8100780/8100781 can help. However provide necessary features seems to be too difficult as just an attempt so I did not try it.

Note I am looking for solution for other connected problem in How to play .m4a with HTML5 audio in IE(9+) and Safari (Pad)?


回答1:


Simple answer: It is necessary to handle a browser range request.

Complete story

When comparing Fiddler captured communication between Firefox and IIS I have noticed that the response status for the direct link is 206 Partial Content while for the indirect link 200 OK.
More careful analysis of request shown that Firefox requests Range: bytes=0- and iPad Range: bytes=0-1 and later on Range: bytes=0-fullsize (Capture Traffic from iOS Device).
Setting Response.StatusCode = 206 was enough to fool Firefox but not Safari. But I have known the key information and rest was simple. It is necessary to honor the range request see: SO: HTML5 video will not loop. The explanation how to do it I have found in Aha! #1 – ASP.NET ASHX Video Streaming for HTML5 Video. So the new code is (only active part is presented rest is the same as in the answer):

    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(); 
       };      
    }

It is probably convenient to add other headers (Content-Disposition, Accept-Ranges, Access-Control-Allow-Origin) but the intention was present solution as simple as possible.

Lesson taken: If I had not been fixed to <audio> and had looked also for <video>, I would have found the solution more quickly.



来源:https://stackoverflow.com/questions/18336174/how-to-properly-provide-data-for-audio

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!