我正试图建立一个支持HLS的自定义C#网络服务器,但具体来说,HLS部分不能工作。下面是我使用的代码。我试图让它尽可能的简单。问题是所有的文件类型都能工作,除了HLS协议中使用的文件类型。我试验的文件类型有:
mp4
,
xml
,
mp3
,
jpg
,
png
和没有扩展名的纯二进制数据文件。
public class LocalServer
public bool runListener = true;
private string prefix;
private string baseDirectory = "M:/ftp backup/";
public LocalServer(int port)
prefix = string.Format("http://+:{0}/", port);
Thread listenerThread = new Thread(LocalServerThread);
listenerThread.Start();
public void LocalServerThread()
HttpListener listener = new HttpListener();
listener.Prefixes.Add(prefix);
listener.Start();
Debug.Log(DateTime.Now.ToString(SimpleHTTPServer.dateFormat) + "<color=green>Started local web server</color>");
while (runListener)
IAsyncResult result = listener.BeginGetContext(new AsyncCallback(ListenerCallback), listener);
result.AsyncWaitHandle.WaitOne();
listener.Close();
Debug.Log(DateTime.Now.ToString(SimpleHTTPServer.dateFormat) + "<color=green>Stopped local web server</color>");
public void ListenerCallback(IAsyncResult result)
HttpListener listener = (HttpListener)result.AsyncState;
HttpListenerContext context = listener.EndGetContext(result);
string fileNameComplete = context.Request.Url.AbsolutePath.Substring(1).Replace("%20", " "); //removing the first slash and replacing the %20 web prefix by space
string pathComplete = baseDirectory + fileNameComplete;
Debug.Log(DateTime.Now.ToString(SimpleHTTPServer.dateFormat) + pathComplete + " requested to LocalServer");
using (Stream fileStream = new FileStream(pathComplete, FileMode.Open))
byte[] buffer = new byte[fileStream.Length];
fileStream.Read(buffer, 0, (int)fileStream.Length);
context.Response.ContentLength64 = fileStream.Length;
context.Response.ContentType = SimpleHTTPServer.GetMimeType(fileNameComplete);
//personal headers
context.Response.StatusCode = (int)HttpStatusCode.OK;
////apache headers
//context.Response.StatusDescription = "OK";
//context.Response.ProtocolVersion = new Version("1.1");
//context.Response.SendChunked = false;
//context.Response.KeepAlive = true;
//context.Response.AddHeader("Accept-Ranges", "bytes");
//context.Response.AddHeader("ETag", BinarySocket.RandomString(20));
//context.Response.AddHeader("Connection", "Keep-Alive");
//context.Response.AddHeader("Keep-Alive", "timeout=5, max=100");
////CORS
//context.Response.AddHeader("Access-Control-Allow-Origin", "*");
//context.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
//context.Response.AddHeader("Access-Control-Allow-Headers", "X-Requested-With");
//context.Response.AddHeader("Access-Control-Max-Age", "86400");
context.Response.OutputStream.Write(buffer, 0, buffer.Length);
context.Response.Close();
SimpleHTTPServer是我在之前的尝试中使用的类。这个类使用SimpleHTTPServer类中的mime-type字典。它还使用了SimpleHTTPServer的dateFormat,即:"dd-MM-yyyy HH:mm:ss.fff:"
。用于HLS的mime类型是:".m3u8", "application/vnd.apple.mpegurl"
和".ts", "video/MP2T"
,这与apache使用的类型相同。我注释了Apache和CORS响应属性,因为它对下载没有影响。
来自我的HTTP服务器的HLS流不能被一些媒体播放器(media foundation、direct show)打开。在VLC中打开它会导致VLC非常缓慢地下载每个m3u8播放列表(主播放列表)和子m3u8播放列表(不同的分辨率/带宽),只有在它完成下载所有的播放列表后,它才开始播放4k视频片段。下一个片段的分辨率是1440p,它一直在下降,直到达到360p。然而,通过来自apache或Nginx的流播放完全相同的文件,却能完美工作。
有谁知道我做错了什么,或者为了使HLS工作而实施了错误的方法?我读了HTTP实时流媒体的RFC(RFC-8216),我认为我做了一切正确的事情来使HLS工作,但它没有,所以我一定做错了什么。苹果公司的文档描述说,任何HTTP服务器都可以通过简单地添加mime类型来支持HLS,但这样做并不能解决这个问题。
编辑:当从visual studio控制台应用程序中运行这段代码时,它是有效的,但当在Unity中运行这段代码时,Unity会阻塞,直到下载完成。这似乎是一个线程问题,但它都是在一个单独的线程上运行的,对吗?还是监听器的回调是在主线程上执行的?