Воспроизведение больших файлов в проигрывателе Windows Media во время загрузки.
-
22-07-2019 - |
Вопрос
Мой вопрос заключается в записи видеофайла на жесткий диск, загружаемого из сети, и одновременном его воспроизведении с помощью проигрывателя Windows Media.Файл довольно большой, и его загрузка займет некоторое время.Его необходимо загрузить, а не просто транслировать непосредственно в проигрыватель Windows Media.
Происходит следующее: хотя я могу одновременно записывать видеофайл и читать его из своего собственного тестового кода, это невозможно сделать с помощью проигрывателя Windows Media (по крайней мере, я в этом не разобрался).Я знаю, что это возможно, потому что это можно сделать с помощью загрузок Amazon Unbox.Unbox позволяет воспроизводить файлы WMV во время их загрузки.А Unbox написан на .NET, так что...
Я прочитал "Чтение/запись файлов C#, общий доступ к файлам, похоже, не работает"вопрос и ответы по открытию файла с флагами FileShare.Но у меня это не работает.Process Monitor сообщает, что Media Player открывает файл с флагами Fileshare, но выдает ошибку.
В потоке буферизации у меня есть этот код для чтения файла из сети и записи его в файл (без обработки ошибок или других вещей, которые сделают его более читабельным):
// the download thread
void StartStreaming(Stream webStream, int bufferFullByteCount)
{
int bytesRead;
var buffer = new byte[4096];
var fileStream = new FileStream(MediaFile.FullName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
var writer = new BinaryWriter(fileStream);
var totalBytesRead = 0;
do
{
bytesRead = webStream.Read(buffer, 0, 4096);
if (bytesRead != 0)
{
writer.Write(buffer, 0, (int)bytesRead);
writer.Flush();
totalBytesRead += bytesRead;
}
if (totalBytesRead >= bufferFullByteCount)
{
// fire an event to a different thread to tell
// Windows Media Player to start playing
OnBufferingComplete(this, new BufferingCompleteEventArgs(this, MediaFile));
}
} while (bytesRead != 0);
}
Кажется, это работает нормально.Файл записывается на диск и имеет правильные разрешения.
Но вот обработчик событий в другом потоке для воспроизведения видео
// the playback thread
private void OnBufferingComplete(object sender, BufferingCompleteEventArgs e)
{
axWindowsMediaPlayer1.URL = e.MediaFile.FullName;
}
Проигрыватель Windows Media указывает, что он открывает файл, а затем просто останавливается с ошибкой о том, что файл не может быть открыт «уже открыт в другом процессе».
Я перепробовал все, что мог придумать.Что мне не хватает?Если ребята из Amazon могут это сделать, то смогу и я, верно?
редактировать:этот код работает с mplayer, VLC и Media Player Classic;но не проигрыватель Windows Media или проигрыватель Windows Media Center.IOW, единственные игроки, с которыми мне нужно работать.фу!
редактировать2:Я зашел так далеко, что использовал MiniHttp для потоковой передачи видео в проигрыватель Windows Media, чтобы посмотреть, «обманет» ли это WMP, заставив его воспроизвести загружаемое видео.Ничего не делая.Хотя WMP и открывал файл, он ждал, пока файл mpeg не будет полностью скопирован, прежде чем начать воспроизведение.Откуда оно знает?
редактировать3:После некоторого копания я обнаружил проблему.Я работаю с файлами MPEG2.Проблема не обязательно в проигрывателе Windows Media, а в Microsoft MPEG2 DirectShow Splitter, который WMP использует для открытия файлов MPEG2, которые я пытаюсь воспроизвести и загрузить одновременно.Splitter открывает файлы в режиме без общего доступа.С файлами WMV дело обстоит иначе.WMP открывает их в общем режиме, и все работает как положено.
Решение
Я решил ответить на свой вопрос на случай, если кто-то еще столкнется с этой редкой ситуацией.
Краткий ответ таков:Проигрыватель Windows Media (на момент написания этой статьи) позволит одновременно загружать и воспроизводить файл, если эта функциональность поддерживается CODECS, участвующим в рендеринге файла.
Цитирую последнее изменение вопроса:
После некоторого копания я обнаружил проблему.Я работаю с файлами MPEG2.Проблема не обязательно в проигрывателе Windows Media, а в Microsoft MPEG2 DirectShow Splitter, который WMP использует для открытия файлов MPEG2, которые я пытаюсь воспроизвести и загрузить одновременно.Splitter открывает файлы в режиме без общего доступа.С файлами WMV дело обстоит иначе.WMP открывает их в общем режиме, и все работает как положено.
Другие советы
Когда вы открываете файл для записи, вам не следует использовать FileShare.ReadWrite.Вместо этого вам следует использовать FileShare.Read:
var fileStream = new FileStream(
MediaFile.FullName, FileMode.Create, FileAccess.Write, FileShare.Read);
Когда процесс mplayer.exe открывает файл для чтения, он сначала попытается открыть его с помощью FileShare.Read, что завершится неудачей, но затем повторит попытку с помощью FileShare.ReadWrite, которая завершится успехом.
Обновлено 16 марта после комментария @darin:
Вы указываете FileShare.ReadWrite
когда вы пишете файл, что теоретически позволяет другому процессу открыть его и для записи.
Попробуйте изменить свой код, чтобы он только запрашивал FileShare.Read
:
var fileStream
= new FileStream(
MediaFile.FullName,
FileMode.Create,
FileAccess.Write,
FileShare.Read); // Instead of ReadWrite
Цитировать MSDN:
FileShare.Читать:Допускает последующее открытие файла для чтения.
FileShare.ReadWrite:Допускает последующее открытие файла для чтения или писать.