WPF MediaElement在播放时下载文件

本文关键字:下载 文件 播放 MediaElement WPF | 更新日期: 2023-09-27 18:27:28

是否可以使用MediaElement从服务器播放文件(视频或音频类型),同时将数据保存到特定的文件位置,以便下次可以直接从本地系统加载。在我的项目中,我使用的是WPF Media Element

WPF MediaElement在播放时下载文件

没有简单的方法。这是可能的——至少有两种方法可以做到。但这并不容易。

MediaElement处理其源流的方式很棘手,因为它在内部使用Windows Media Player(这意味着它在幕后使用MediaFoundation或DirectShow,这取决于你运行的是哪个版本的Windows)。编写某种拦截器来中继底层流,同时将其保存到磁盘,这种"显而易见"的解决方案是可能的,但你必须离开.NET世界才能做到这一点,因为MediaElement无法与.NET流一起工作。

这并不是说这是不可能的。您"只需"编写一个自定义源筛选器,并使用自定义协议实现进行设置。http://msdn.microsoft.com/en-us/library/ms787558(VS.85).aspx描述了视频渲染基础结构如何根据传入的URL来决定创建哪种对象来表示视频源。MediaElement将源URL直接传递到该基础结构中,因此,如果您编写自定义筛选器并将其与myhack:协议相关联,则如果您将源设置为myhack://whatever,它最终会加载你的过滤器。然后,如果您将过滤器作为http:过滤器的包装器,您将能够将传入数据的副本保存到磁盘。

这不是小事。

另一种选择可能是托管本地HTTP服务器。如果您可以选择打开一个可以监听的本地套接字,那么您可以编写一个HTTP实现,该实现使用.NET内置的HTTP客户端类型之一来获取数据,同时保存一个副本并提供该数据。这也很简单,但可能比编写自定义源代码过滤器更容易。

我发现,如果我在开始下载之前设置了下载文件的文件大小,那么MediaElement将在下载时播放整个视频/音频。

using (var httpClient = new HttpClient() {Timeout = TimeSpan.FromMinutes(25)})
using (var response = await httpClient.GetAsync(theDownloadUrl, HttpCompletionOption.ResponseHeadersRead))
using (var videoFileStream = File.Open(fileName, FileMode.Create, FileAccess.Write, FileShare.Read)) {
    videoFileStream.SetLength(response.Content.Headers.ContentLength.GetValueOrDefault());
    var copying = response.Content.CopyToAsync(videoFileStream);
    //await Task.Delay(1000);
    MediaSource = fileName;
    await copying;
}