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)?
In computer the audio signals are stored in the form of digital. ... then each 0 and 1 is stored into a memory as a raw data buffer corresponding to the recorded audio. it can be stored as file on disk and compressed as mp3 with a compression algorithm. with some audio command, you directly listen to the file.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With