I am trying to stream video from server with accept-ranges
to allow users to change position on client-side video player (in my case jwplayer)
When accept-ranges
code is included client (jwplayer or opened only in chrome directly from url) plays about 15s
normally and after it is every chunk asked with new request, practically after 15s only goes through method only one time, connection is broken in or after Response.Flush()
without any error (sometimes Flush()
gets error code 0x800704CD
or 0x800703E3
or 0x80070016
in about 10% of requests), after that is Response.IsClientConnected=false
so method ends.
Client is asked for range for example 123456-empty
, there is not specified end part of range.
I guess that this is not right behavior, maybe there is wrong headers on Response.. or is normal, that client video player is creating new request for every chunk? Actually it takes on my PC about 80% of CPU.
Problem is only while streaming video and when is created a lot of new requests in same time, in usual situations when file is downloaded there is no problem when is establishment of broken downloads for example.
When accept-ranges code missing, there is no problem in video streaming, all server->clients transfers are in while loop and only when user broke connection methods end.
(This solution is running under ASP.NET MVC4
)
Currently used code :
public void Method()
{
string path = @"filePath.mp4";
FileInfo file = new FileInfo(path);
long fileLength = file.Length;
byte[] buffer = new byte[64 * 1024];
long dataToRead = fileLength;
long startbyte = 0;
long location = 0;
long readLength = 0;
Response.AddHeader("Accept-Ranges", "bytes");
Response.ContentType = "video/mp4";
if (!String.IsNullOrEmpty(Request.Headers["Range"]))
{
string[] range = Request.Headers["Range"].Split(new char[] { '=', '-' });
location = long.Parse(range[1]);
if (location >= 0 && location <= fileLength)
{
Response.StatusCode = 206;
Response.AddHeader("content-range", String.Format(" bytes {0}-{1}/{2}", location, fileLength - 1, fileLength));
startbyte = location;
dataToRead = fileLength - startbyte;
Response.AppendHeader("content-length", dataToRead.ToString());
}
}
else
{
Response.StatusCode = 200;
Response.AddHeader("Content-Range", String.Format(" bytes {0}-{1}/{2}", 0, fileLength - 1, fileLength));
Response.AppendHeader("content-length", fileLength.ToString());
}
try
{
using (Stream stream = System.IO.File.OpenRead(path))
{
if (startbyte > 0)
{
stream.Seek(startbyte, SeekOrigin.Begin);
}
while (dataToRead > 0)
{
if (Response.IsClientConnected)
{
readLength = stream.Read(buffer, 0, buffer.Length);
Response.OutputStream.Write(buffer, 0, (int)readLength);
Response.Flush();
dataToRead = dataToRead - readLength;
}
else
{
dataToRead = -1;
}
}
}
}
catch (EndOfStreamException endStream)
{
Log.Error(endStream.Message, endStream);
}
catch (TimeoutException timeout)
{
Log.Error(timeout.Message, timeout);
}
catch (Exception e)
{
Log.Error(e.Message, e);
}
finally
{
Response.End();
}
}
User contributions licensed under CC BY-SA 3.0