MediaElement 的 DownloadProgress、DownloadProgressOffset 和 BufferProgress






4.67/5 (5投票s)
本文介绍 MediaElement 的 DownloadProgress、DownloadProgressOffset 和 BufferProgress。
引言
本文介绍 MediaElement
的 DownloadProgress
、DownloadProgressOffset
和 BufferProgress
属性。
背景
我正在使用 MediaElement
,因为我需要从 HTTP URL 播放视频。我遇到了一个奇怪的问题。在正常情况下,MediaElement
的 DownloadProgress
属性会更新 UI 进度条。它在下载时工作正常,DownloadProgress
会增加。但是,当用户单击文件中的另一个位置时,DownloadProgress
值会变为 1.0 (100%),DownloadProgressOffset
也是如此。过一段时间后,它会自行纠正。您可以在以下链接中找到相同的问题:http://silverlight.net/forums/p/69162/167219.aspx。
在解释问题之前,我先解释一些我将用来解释显示 DownloadProgress
和 DownloadProgressOffset
问题的定义。
字节范围请求
HTTP 请求有一个选项可以进行部分内容范围请求。为了解释它,让我们举一个场景。假设我想从一个服务请求一个非常大的文件,但在我这样做之前,我想确切地知道它有多大,以及该服务是否支持“范围请求”。为此,我对我要检索的大资源发出一个 HEAD 请求。HEAD 方法是一种标准的 HTTP 方法,其作用就像我发出了一个 GET 请求,但它只返回头信息而不返回主体。这使我能够在不花费时间或带宽下载的情况下了解资源的信息。例如,我可以读取 Content-Length 头并确定资源的大小。
另一个非常重要的头是 Accept-Ranges 头。如果存在,它可能包含值“bytes”。如果是这样,我就知道我可以发出一个 GET 请求并请求一个字节范围来检索这些字节。这是第一个重要的组成部分。
所以,现在我知道我可以向该服务发出范围请求,通过发送一个包含 Range 头(指定我请求的字节范围)的标准 GET 请求来完成,如下所示:Range: bytes=0-999。然后,该服务应该响应一个 206 Partial Content 状态码、一个 Content-Range 头以及请求的字节范围。这是第二个关键组成部分。
我应该注意到,服务不能强制客户端发出范围请求。这完全取决于客户端是否发出此类请求,因此服务应遵守所有不包含 Range 头部的标准 GET 请求,并发送所请求资源的完整表示。如果您的服务允许范围请求,最好通过 Accept-Ranges 头告知客户端。如果您想明确告知客户端您不允许范围请求,请在 Accept-Ranges 头中发送“none”的值。
我从以下文章中获得了此定义,因此如果对您来说不清楚,您可以参考以下文章:http://benramsey.com/archives/206-partial-content-and-range-requests/。
DownloadProgress
MediaElement
的 DownloadProgress
属性是一个百分比,表示远程服务器上内容的下载完成量。该值范围从 0 到 1。将其乘以 100 即可获得百分比。默认值为 0。设置此属性时,会发生 DownloadProgressChanged
事件。
DownloadProgressOffset
它获取 MediaElement
下载进度的偏移量。当用户跳转到下载进度中的某个点时(例如,视频的第 30 秒),该点将成为下载进度的偏移量。
BufferingProgress
获取一个指示当前缓冲进度的值。它是为媒体内容完成的缓冲量。该值范围从 0 到 1。乘以 100 即可获得百分比。默认值为 0。每当 BufferingProgress
属性更新 0.05 或更多,或者达到 1.0 时,就会发生 BufferingProgressChanged
事件。在某些情况下,BufferingProgress
值在媒体播放时不会保持为 1。
问题解释
当用户播放 HTTP URL 时,它会下载文件,DowloadProgress
和 DownloadProgressOffest
工作正常,但是当用户更改播放位置或第一次“seek”操作发生时,播放器实际上会触发一个 BRR,下载 WMV 文件的索引(位于文件末尾)。此时,DownloadProgress
和 DownloadProgressOffset
都将非常接近终点,所以过一段时间后,DownloadProgress
和 DownloadProgressOffset
都将达到 100%,这实际上意味着索引文件已完全下载。之后,DownloadProgress
会回退到 seek 点。
Using the Code
代码中没有什么需要解释的。它不言自明。我使用 DownloadProgressChanged
和 BufferingProgressChanged
事件来设置 DownloadProgress
、DownloadProgressOffset
和 BufferOffset
进度条。
private void VideoMediaElement_MediaOpened(object sender, RoutedEventArgs e)
{
//VideoMediaElement.Position = TimeSpan.FromDays(1);
//VideoMediaElement.Position = TimeSpan.FromSeconds(0);
}
private void Video_BufferingProgressChanged(object sender, RoutedEventArgs e)
{
BufferProgress.Value = VideoMediaElement.BufferingProgress * 100;
DownloadProgress.Value = VideoMediaElement.DownloadProgress * 100;
OffsetValue.Value = VideoMediaElement.DownloadProgressOffset * 100;
}
private void Video_DownloadProgressChanged(object sender, RoutedEventArgs e)
{
DownloadProgress.Value = VideoMediaElement.DownloadProgress * 100;
OffsetValue.Value = VideoMediaElement.DownloadProgressOffset * 100;
}
private void Pause_Click(object sender, RoutedEventArgs e)
{
VideoMediaElement.Pause();
}
private void Play_Click(object sender, RoutedEventArgs e)
{
if (!Uri.IsWellFormedUriString(URI.Text, UriKind.Absolute))
{
MessageBox.Show("Invalid URI");
return;
}
VideoMediaElement.Source = new Uri(URI.Text);
VideoMediaElement.Play();
}
private void Stop_Click(object sender, RoutedEventArgs e)
{
VideoMediaElement.Stop();
}
private void Farward_Click(object sender, RoutedEventArgs e)
{
//if (VideoMediaElement.CurrentState != MediaElementState.Buffering)
VideoMediaElement.Position = VideoMediaElement.Position +
TimeSpan.FromSeconds(Int16.Parse(Amount.Text));
}
private void Backward_Click(object sender, RoutedEventArgs e)
{
//if (VideoMediaElement.CurrentState != MediaElementState.Buffering)
VideoMediaElement.Position = VideoMediaElement.Position -
TimeSpan.FromSeconds(Int16.Parse(Amount.Text));
}