下载期间在 Windows Media Player 上播放大文件
我的问题是关于将从网络下载的视频文件写入硬盘并同时使用 Windows Media Player 播放它。 该文件相当大,需要一段时间才能下载。 有必要下载它,而不是直接将其流式传输到 Windows Media Player。
所发生的情况是,虽然我可以写入视频文件并同时从我自己的测试代码中读取它,但无法使用 Windows Media Player 来完成(至少我还没有弄清楚)。 我知道这是可能的,因为亚马逊 Unbox 下载可以做到这一点。 Unbox 允许您在下载 WMV 时播放它们。 Unbox 是用 .NET 编写的,所以...
我读过“C# 文件读/写文件共享似乎不起作用”有关使用 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 Player 指示它正在打开该文件,然后停止并显示无法打开该文件的错误“已在另一个进程中打开”。
我已经尝试了我能想到的一切。 我缺少什么? 如果亚马逊的人可以做到这一点,那么我也可以,对吗?
编辑: 此代码适用于 mplayer、VLC 和 Media Player Classic; 只是不是 Windows Media Player 或 Windows Media Center 播放器。 IOW,我唯一需要他们合作的玩家。 啊!
编辑2: 我什至使用 MiniHttp 将视频流式传输到 Windows Media Player,看看这是否会“欺骗”WMP 播放正在下载的视频。 无所事事。 虽然 WMP 确实打开了该文件,但它会等到 mpeg 文件完全复制后才开始播放。 它是怎么知道的?
编辑3: 经过一番挖掘,我发现了问题。 我正在处理 MPEG2 文件。 问题不一定出在 Windows Media Player 上,而是出在 WMP 用于打开我尝试同时播放和下载的 MPEG2 文件的 Microsoft MPEG2 DirectShow Splitter 上。 拆分器以非共享模式打开文件。 WMV 文件则不然。 WMP 以共享模式打开它们,一切都按预期进行。
My question is about writing a video file to the hard drive that is being downloaded from the network and playing it at the same time using Windows Media Player. The file is pretty big and will take awhile to download. It is necessary to download it rather than just stream it directly to Windows Media Player.
What happens is that, while I can write to the video file and read it at the same time from my own test code, it cannot be done using Windows Media Player (at least I haven't figured it out). I know it is possible to do because Amazon Unbox downloads does it. Unbox lets you play WMVs while it is downloading them. And Unbox is written in .NET so...
I've read the "C# file read/write fileshare doesn’t appear to work" question and answers for opening a file with the FileShare flags. But it's not working for me. Process Monitor says that Media Player is opening the file with Fileshare flags, but it errors out.
In the buffering thread I have this code for reading the file from the network and writing it to a file (no error handling or other stuff to make it more readable):
// 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);
}
This seems to work fine. The file writes to the disk and has the correct permissions.
But then heres the event handler in the other thread for playing back the video
// the playback thread
private void OnBufferingComplete(object sender, BufferingCompleteEventArgs e)
{
axWindowsMediaPlayer1.URL = e.MediaFile.FullName;
}
Windows Media Player indicates that its opening the file and then just stops with an error that the file can't be opened "already opened in another process."
I have tried everything I can think of. What am I missing? If the Amazon guys can do this then so can I, right?
edit:
this code works with mplayer, VLC, and Media Player Classic; just not Windows Media Player or Windows Media Center player. IOW, the only players I need them to work with. ugh!
edit2:
I went so far as to use MiniHttp to stream the video to Windows Media Player to see if that would "fool" WMP into playing a video that is being download. Nothing doing. While WMP did open the file it waited until the mpeg file was completely copied before it started playing. How does it know?
edit3:
After some digging I discovered the problem. I am working with MPEG2 files. The problem is not necessarily with Windows Media Player, but with the Microsoft MPEG2 DirectShow Splitter that WMP uses to open the MPEG2 files that I am trying to play and download at the same time. The Splitter opens the files in non-Shared mode. Not so with WMV files. WMP opens them in shared mode and everything works as expected.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我决定回答我自己的问题,以防其他人遇到这种罕见的情况。
简短的回答是:Windows Media Player(截至撰写本文时)将允许同时下载和播放文件,只要渲染文件所涉及的 CODECS 支持该功能。
引用对问题的最后一次编辑:
经过一番挖掘,我发现了这个问题。 我正在处理 MPEG2 文件。 问题不一定出在 Windows Media Player 上,而是出在 WMP 用于打开我尝试同时播放和下载的 MPEG2 文件的 Microsoft MPEG2 DirectShow Splitter 上。 拆分器以非共享模式打开文件。 WMV 文件则不然。 WMP 以共享模式打开它们,一切都按预期进行。
I've decided to answer my own question in case someone else runs into this rare situation.
The short answer is this: Windows Media Player (as of this writing) will allow a file to be downloaded and play at the same time as long as that functionality is supported by CODECS involved in rendering the file.
To quote from the last edit to the question:
After some digging I discovered the problem. I am working with MPEG2 files. The problem is not necessarily with Windows Media Player, but with the Microsoft MPEG2 DirectShow Splitter that WMP uses to open the MPEG2 files that I am trying to play and download at the same time. The Splitter opens the files in non-Shared mode. Not so with WMV files. WMP opens them in shared mode and everything works as expected.
当您打开文件进行写入时,不应使用 FileShare.ReadWrite。 您应该使用 FileShare.Read:
当 mplayer.exe 进程打开文件进行读取时,它会首先尝试使用 FileShare.Read 打开它,这会失败,但随后会重新尝试使用 FileShare.ReadWrite 来打开它,这会成功。
When you open the file for writing you shouldn't use FileShare.ReadWrite. You should instead use FileShare.Read:
When mplayer.exe process open the file for reading it will first try to open it with FileShare.Read which will fail but it then will reattempt with FileShare.ReadWrite which will succeed.
3 月 16 日在 @darin 评论后更新:
您在写入文件时指定
FileShare.ReadWrite
,理论上这也允许另一个进程打开它进行写入。尝试更改您的代码以仅请求
FileShare.Read
:引用 MSDN:
Updated 16 March after comment by @darin:
You're specifying
FileShare.ReadWrite
when you're writing the file, which theoretically allows another process to open it for writing too.Try altering your code to only request
FileShare.Read
:To quote MSDN: