添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

支持HLS的自定义C#服务器

3 人关注

我正试图建立一个支持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会阻塞,直到下载完成。这似乎是一个线程问题,但它都是在一个单独的线程上运行的,对吗?还是监听器的回调是在主线程上执行的?