Сервер для медиафайлов

Здравствуйте.
Пишу HTTP сервер. Файлы передаю вот так:

        private void SendFileAsStream(Socket client, string filePath, long byteStart, long byteEnd)
        {
            try
            {
                using (Stream stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    stream.Position = byteStart;

                    if (byteEnd == -1L || byteEnd < byteStart)
                    {
                        byteEnd = stream.Length == 0L ? 0 : stream.Length - 1L;
                    }
                    long segmentSize = byteStart == byteEnd ? 1L : byteEnd - byteStart + 1;
                    string fileExt = Path.GetExtension(filePath);
                    int errorCode = segmentSize == stream.Length ? 200 : 206;
                    string t = $"HTTP/1.1 {errorCode} OK\r\nContent-Type: {GetContentType(fileExt)}\r\n" +
                        $"Content-Length: {segmentSize}\r\naccept-range: bytes\r\n\r\n";
                    byte[] buf = Encoding.UTF8.GetBytes(t);
                    client.Send(buf);

                    long remaining = segmentSize;
                    buf = new byte[1024];
                    while (client.Connected)
                    {
                        int bytesToRead = remaining > buf.LongLength ? buf.Length : (int)remaining;
                        int bytesRead = stream.Read(buf, 0, bytesToRead);
                        if (bytesRead <= 0)
                        {
                            break;
                        }

                        remaining -= bytesRead;
                        client.Send(buf, 0, bytesRead, SocketFlags.None);
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
                LogEvent(ex.Message.Split('\n')[0]);
            }
        }

заголовок Range:

        private static void ExtractRange(NameValueCollection headers, out long byteFrom, out long byteTo)
        {
            string t = headers.Get("Range");
            if (!string.IsNullOrEmpty(t))
            {
                int n = t.IndexOf('=');
                if (n >= 0)
                {
                    t = t.Substring(n + 1);
                }
                if (!string.IsNullOrEmpty(t) && !string.IsNullOrWhiteSpace(t))
                {
                    string[] splitted = t.Split('-');
                    byteFrom = long.Parse(splitted[0]);
                    byteTo = string.IsNullOrEmpty(splitted[1]) || string.IsNullOrWhiteSpace(splitted[1]) ?
                        -1L : long.Parse(splitted[1]);
                    return;
                }
            }

            byteFrom = 0L;
            byteTo = -1L;
        }

Пробовал качать с него файлы - работает. Даже хэш сходится :grin:
А как сделать, чтобы браузер (или, например, VLC) играл медиафайлы? То есть, чтобы закинул ссылку и файл воспроизвёлся. Так может, например, Apache. Как он это делает? :thinking:
Сейчас если открыть ссылку на медиафайл, то он сначала весь передастся (сколько бы ни весил) и только тогда начинается воспроизведение. Но при этом, перемотка не работает :man_shrugging:
Да, content-type я передаю.

А он делает это именно с этим файлом?

какой?

С любыми медиафайлами

из этого списка:

вот мой вариант:

#Картинки
image/bmp		|.bmp
image/gif		|.gif
image/jpeg		|.jpg, .jpeg, .jfif, .pjpeg, .pjp
image/tiff		|.tiff
image/svg+xml	|.svg
image/vnd.microsoft.icon|.ico
image/webp		|.webp

#Форматы видео
video/3gpp		|.3gp, .3gpp
video/mp2t		|.ts
video/mp4		|.mp4, .m4v
video/mpeg		|.mpg, .mpeg
video/ogg		|.ogg
video/webm		|.webm
video/x-flv		|.flv
video/x-msvideo	|.avi
video/x-ms-wmv	|.wmv

#Форматы аудио
audio/aac		|.aac
audio/mp3		|.mp3
audio/mp4		|.m4a
audio/vnd.wave	|.wav
video/webm		|.weba

#HTML / CSS / JS
text/css			|.css
text/html			|.html
text/javascript		|.js

#Разное
application/json	|.json
application/pdf		|.pdf
application/zip		|.zip

Я пока не все прописал, да и не нужны они все. Проблема в том, что медиафайлы динамически не подгружаются :man_shrugging: то есть, например, перемотали в середину и грузятся данные из середины трека и т.д.

Не все файлы это поддерживают.
В mp4 для этого метаданные должны быть в начале файла, что не всегда так.

Части тоже качаются и правильные?

Тестирую на тех же файлах, которые через apache работают.

Так ведь mp4 это контейнер :thinking: Там всегда есть метаданные. Если распаковать mp4mpvh264, то там уже никаких метаданных нет и плееру требуется много времени чтобы понять, что это за файл. Но, думаю, через apache VLC их бы тоже проигрывал :man_shrugging:

Да. Только что перепроверил. Хэш сходится.

Я одного не пойму :thinking: Ладно, фиг с ним что динамической подгрузки нет (грузится сразу весь файл). Но почему в полностью загруженном файле не работает перемотка? Файл же проигрывается и его длинна известна (браузер её определил).

Кажется, разобрался. Проблема была в заголовках ответа от сервера.
Во-первых: Надо было всегда отправлять заголовок Accept-Ranges: bytes. Я неправильно отправлял Accept-Range: bytes - без s в конце.
Во-вторых: Если клиент (браузер) отправил заголовок Range, то сервер должен вернуть заголовки:

    $"Content-Length: {rangeTo - rangeFrom + 1L}";
    $"Content-Range: bytes {rangeFrom}-{rangeTo}/{fileSize}";

В-третьих: Значение заголовка Range может иметь разный вид. Сервер должен это учитывать.
bytes=5-10 - от пятого байта до десятого.
bytes=0- - от начала файла до конца.
bytes=-666 - последние 666 байт файла.
(Хотя, последний вариант я не прописал, но оно всё-равно работает. Видимо, при воспроизведении файла браузером он не используется)

Тогда всё работает. Перемотка есть и файл предварительно весь не грузится.
Даже немного удивительно, что это оказалось так просто :thinking: