博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
快速构建Windows 8风格应用21-构建简单媒体播放器
阅读量:5812 次
发布时间:2019-06-18

本文共 10428 字,大约阅读时间需要 34 分钟。

本篇博文主要介绍如何构建一个简单的媒体播放器。

《快速构建Windows 8风格应用20-MediaElement》博文中提到了如何使用MediaElement对象进行播放视频的简单功能,但是在实际应用中需要更复杂的功能,例如:控制视频播放的控件、全屏模式、进度条等等其他功能。
 
本篇博文中示例使用应用程序中包含的媒体文件,当然我们也可以通过网络或者本地[使用 ]进行加载某一媒体文件。
 
MSDN中关于媒体播放器的示例代码下载地址: 。
 
构建基本的MediaElement控件
首先我们创建一个MediaElement控件并添加到
XAML代码如下:
 
 
  1. <ContentControl x:Name="videoContainer" KeyUp="VideoContainer_KeyUp" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"  Height="400" Grid.Row="0" > 
  2.             <MediaElement Name="videoMediaElement" Source="Video/Azure_Tmobile_500k.wmv"   
  3.                               MediaOpened="videoElement_MediaOpened"   
  4.                               MediaEnded="videoMediaElement_MediaEnded"   
  5.                               MediaFailed="videoMediaElement_MediaFailed" 
  6.                               CurrentStateChanged="videoMediaElement_CurrentStateChanged" 
  7.                               PosterSource="Media/1.png" 
  8.                               AutoPlay="False" /> 
  9. </ContentControl> 

MediaElement控件的Source属性指向要播放的音频或视频文件。,该属性可以设置为应用中的某一文件的URI或网络上的文件的 URI。当然我们也可以使用 

MediaElement控件声明了
最后设置PosterSource属性值,PosterSource是一个图像,它在媒体加载前为MediaElement控件提供视觉展示。
通常PosterSource在以下情况下显示:
1)未设置有效的源,例如:未设置Source、Source设置为Null、或源无效;
2)加载媒体时;
3)“播放到”流式播放期间;
 
构建控制MediaElement播放控件
一般控制MediaElement播放包括播放,停止和暂停等功能。
常用控制MediaElement播放功能包括:
1)停止:调用 
2)暂停:调用 
3)快进:将MediaElement控件的
4)快退:将MediaElement控件的DefaultPlaybackRate属性的值设置为 -2.0,我们可以调整此值,以提高或降低快退的速率。然后,处理程序调用 
5)播放:如果MediaElement控件的DefaultPlaybackRate属性值不是 1.0,则将DefaultPlaybackRate 设置为 1.0。然后,处理程序调用 
6)静音:在 true 和false 间切换 
7)音量增加、音量降低:如果IsMuted为true,则取消音量静音,然后处理程序按 0.1 增加或降低
对应这些控制功能的XAML代码可如下:
<
StackPanel 
Orientation
="Horizontal">
    
<
Button 
Name
="btnPlay" 
Click
="btnPlay_Click"
            
Style
="{StaticResource transportStyle}" 
Content
="Play" 
/>
    
<
Button 
Name
="btnPause" 
Click
="btnPause_Click"
            
Style
="{StaticResource transportStyle}" 
Content
="Pause" 
/>
    
<
Button 
Name
="btnStop" 
Click
="btnStop_Click"
            
Style
="{StaticResource transportStyle}" 
Content
="Stop" 
/>
    
<
Button 
Name
="btnReverse" 
Click
="btnReverse_Click"
            
Style
="{StaticResource transportStyle}" 
Content
="Rewind" 
/>
    
<
Button 
Name
="btnForward" 
Click
="btnForward_Click"
            
Style
="{StaticResource transportStyle}" 
Content
="Forward" 
/>
    
<
Button 
Name
="btnMute" 
Click
="btnMute_Click"
            
Style
="{StaticResource transportStyle}" 
Content
="Mute" 
/>
    
<
Button 
Name
="btnFullScreenToggle" 
Click
="btnFullScreenToggle_Click"
            
Style
="{StaticResource transportStyle}" 
Content
="Full" 
/>
    
<
ComboBox 
Name
="cbAudioTracks"
              
SelectionChanged
="cbAudioTracks_SelectionChanged"
              
Width
="75" 
/>
    
<
Button 
Name
="btnVolumeUp" 
Click
="btnVolumeUp_Click"
            
Style
="{StaticResource transportStyle}" 
Content
="-" 
/>
    
<
Button 
Name
="btnVolumeDown" 
Click
="btnVolumeDown_Click"
            
Style
="{StaticResource transportStyle}" 
Content
="+" 
/>
    
<
TextBlock 
Name
="txtVolume" 
FontSize
="14"
               
Text
="{Binding Volume, ElementName=videoMediaElement}"
               
VerticalAlignment
="Center" 
HorizontalAlignment
="Right" 
/>
</
StackPanel
>
相应的C#代码如下:
private 
void btnPlay_Click(
object sender, RoutedEventArgs e)
{
    
if (videoMediaElement.DefaultPlaybackRate != 1)
    {
        videoMediaElement.DefaultPlaybackRate = 1.0;
    }
 
    videoMediaElement.Play();
}
 
private 
void btnPause_Click(
object sender, RoutedEventArgs e)
{
        videoMediaElement.Pause();
}
 
private 
void btnStop_Click(
object sender, RoutedEventArgs e)
{
    videoMediaElement.Stop();
}
 
private 
void btnForward_Click(
object sender, RoutedEventArgs e)
{
    videoMediaElement.DefaultPlaybackRate = 2.0;
    videoMediaElement.Play();
}
 
private 
void btnReverse_Click(
object sender, RoutedEventArgs e)
{
    videoMediaElement.DefaultPlaybackRate = -2;
    videoMediaElement.Play();;
}
 
private 
void btnVolumeDown_Click(
object sender, RoutedEventArgs e)
{
    
if (videoMediaElement.IsMuted)
    {
        videoMediaElement.IsMuted = 
false;
    }
 
    
if (videoMediaElement.Volume < 1)
    {
        videoMediaElement.Volume += .1;
    }
}
 
private 
void btnMute_Click(
object sender, RoutedEventArgs e)
{
    videoMediaElement.IsMuted = !videoMediaElement.IsMuted;
}
 
private 
void btnVolumeUp_Click(
object sender, RoutedEventArgs e)
{
    
if (videoMediaElement.IsMuted)
    {
        videoMediaElement.IsMuted = 
false;
    }
 
    
if (videoMediaElement.Volume > 0)
    {
        videoMediaElement.Volume -= .1;
    }
}
 
构建MediaElement的全屏播放功能
启用全屏视频播放功能,需要将MediaElement的Width和Height设置为当前窗口的Windows.Bounds(使用的是Window.Current.Bounds.Width和 Window.Current.Bounds.Height)。
启用全屏视频播放功能步骤如下:
1)隐藏应用程序中的所有UI 元素;
2)将MediaElement的Width和Height设置为显示的最大范围,这会让MediaElement控件的高度和宽度与窗口的对应尺寸一致。但是需要首先保存当前Height和Width,方便在应用退出全屏模式时将控件恢复为正确的大小。然后,可以将ContentControl和MediaElement的尺寸设置为当前窗口的
退出全屏视频播放功能步骤如下:
1)侦听键盘事件以检测用户希望何时退出全屏模式,通常我们使用Esc 键通来退出全屏模式。在ContentControl控件中添加
2)恢复 UI 元素的可见性;
3)将ContentControl和MediaElement的Width和Height恢复为其原来的尺寸;
C#代码可如下:
private 
bool _isFullscreenToggle = 
false;
public 
bool IsFullscreen
{
    get { 
return _isFullscreenToggle; }
    set { _isFullscreenToggle = 
value; }
}
 
private Size _previousVideoContainerSize = 
new Size();
 
private 
void FullscreenToggle()
{
    
this.IsFullscreen = !
this.IsFullscreen;
 
    
if (
this.IsFullscreen)
    {   
        TransportControlsPanel.Visibility = Visibility.Collapsed;
 
        _previousVideoContainerSize.Width = videoContainer.ActualWidth;
        _previousVideoContainerSize.Height = videoContainer.ActualHeight;
 
        videoContainer.Width = Window.Current.Bounds.Width;
        videoContainer.Height = Window.Current.Bounds.Height;
        videoMediaElement.Width = Window.Current.Bounds.Width;
        videoMediaElement.Height = Window.Current.Bounds.Height;
    }
    
else
    {
        TransportControlsPanel.Visibility = Visibility.Visible;
 
        videoContainer.Width = _previousVideoContainerSize.Width;
        videoContainer.Height = _previousVideoContainerSize.Height;
        videoMediaElement.Width = _previousVideoContainerSize.Width;
        videoMediaElement.Height = _previousVideoContainerSize.Height;
    }
}
 
private 
void btnFullScreenToggle_Click(
object sender, RoutedEventArgs e)
{
    FullscreenToggle();
}
 
private 
void VideoContainer_KeyUp(
object sender, KeyRoutedEventArgs e)
{
    
if (IsFullscreen && e.Key == Windows.System.VirtualKey.Escape)
    {
        FullscreenToggle();
    }
 
    e.Handled = 
true;
}
 
构建MediaElement的滑动进度条功能
通常我们使用Slider控件来显示或更改视频位置,大致思路为设置Slider控件并使用
首先XAML中声明Slider控件。
<
Slider 
Name
="timelineSlider" 
Margin
="10,0" 
Width
="200"/>
注意:Slider控件的
如果我们想采用更高的精度可以使用设置为250 毫秒的最低频率调节这些数字。
C#代码中声明以下代码:
private 
double SliderFrequency(TimeSpan timevalue)
{
    
double stepfrequency = -1;
 
    
double absvalue = (
int)Math.Round(
        timevalue.TotalSeconds, MidpointRounding.AwayFromZero);
 
    stepfrequency = (
int)(Math.Round(absvalue / 100));
 
    
if (timevalue.TotalMinutes >= 10 && timevalue.TotalMinutes < 30)
    {
        stepfrequency = 10;
    }
    
else 
if (timevalue.TotalMinutes >= 30 && timevalue.TotalMinutes < 60)
    {
        stepfrequency = 30;
    }
    
else 
if (timevalue.TotalHours >= 1)
    {
        stepfrequency = 60;
    }
 
    
if (stepfrequency == 0) stepfrequency += 1;
 
    
if (stepfrequency == 1)
    {
        stepfrequency = absvalue / 100;
    }
 
    
return stepfrequency;
}
我们需要
另外我们需要在以下情况中关闭掉计时器:
1)MediaElement当前状态为暂停或停止时;
2)滑块的滑条移动时;
3)进度条不可见时,例如:全屏模式下。这里需要注意的是进度条在推出全屏模式后重新开始计时;
下面C#代码是如何创建和设置DispatcherTimer:
private DispatcherTimer _timer;
 
private 
void SetupTimer()
{
    _timer = 
new DispatcherTimer();
    _timer.Interval = TimeSpan.FromSeconds(timelineSlider.StepFrequency);
    StartTimer();
}
 
private 
void _timer_Tick(
object sender, 
object e)
{
    
if (!_sliderpressed)
    {
        timelineSlider.Value = videoMediaElement.Position.TotalSeconds;
    }
}
 
private 
void StartTimer()
{
    _timer.Tick += _timer_Tick;
    _timer.Start();
}
 
private 
void StopTimer()
{
    _timer.Stop();
    _timer.Tick -= _timer_Tick;
}
同时我们需要在页面的Loaded事件和
最后,
C#代码如下:
private 
void MainPage_Loaded(
object sender, RoutedEventArgs e)
{
    timelineSlider.ValueChanged += timelineSlider_ValueChanged;
 
    PointerEventHandler pointerpressedhandler = 
new PointerEventHandler(slider_PointerEntered);
    timelineSlider.AddHandler(Control.PointerPressedEvent, pointerpressedhandler, 
true);
 
    PointerEventHandler pointerreleasedhandler = 
new PointerEventHandler(slider_PointerCaptureLost);
    timelineSlider.AddHandler(Control.PointerCaptureLostEvent, pointerreleasedhandler, 
true);
}
 
void videoElement_MediaOpened(
object sender, RoutedEventArgs e)
{
    
double absvalue = (
int)Math.Round(
        videoMediaElement.NaturalDuration.TimeSpan.TotalSeconds,
        MidpointRounding.AwayFromZero);
 
    timelineSlider.Maximum = absvalue;
 
    timelineSlider.StepFrequency =
        SliderFrequency(videoMediaElement.NaturalDuration.TimeSpan);
 
    SetupTimer();
 
    
// Helper method to populate the combobox with audio tracks.
    PopulateAudioTracks(videoMediaElement, cbAudioTracks);
}
最后需要在C#代码中处理显示指针位置更改和
private 
bool _sliderpressed = 
false;
 
void slider_PointerEntered(
object sender, PointerRoutedEventArgs e)
{
    _sliderpressed = 
true;
}
 
void slider_PointerCaptureLost(
object sender, PointerRoutedEventArgs e)
{
    videoMediaElement.Position = TimeSpan.FromSeconds(timelineSlider.Value);
    _sliderpressed = 
false;
}
 
void timelineSlider_ValueChanged(
object sender, Windows.UI.Xaml.Controls.Primitives.RangeBaseValueChangedEventArgs e)
{
    
if (!_sliderpressed)
    {
        videoMediaElement.Position = TimeSpan.FromSeconds(e.NewValue);
    }
}
 
void videoMediaElement_CurrentStateChanged(
object sender, RoutedEventArgs e)
{
    
if (videoMediaElement.CurrentState == MediaElementState.Playing)
    {
        
if (_sliderpressed)
        {
            _timer.Stop();
        }
        
else
        {
            _timer.Start();
        }
    }
 
    
if (videoMediaElement.CurrentState == MediaElementState.Paused)
    {
        _timer.Stop();
    }
 
    
if (videoMediaElement.CurrentState == MediaElementState.Stopped)
    {
        _timer.Stop();
        timelineSlider.Value = 0;
    }
}
 
void videoMediaElement_MediaEnded(
object sender, RoutedEventArgs e)
{
    StopTimer();
    timelineSlider.Value = 0.0;
}
 
private 
void videoMediaElement_MediaFailed(
object sender, ExceptionRoutedEventArgs e)
{
    
// get HRESULT from event args
    
string hr = GetHresultFromErrorMessage(e);
 
    
// Handle media failed event appropriately
}
 
private 
string GetHresultFromErrorMessage(ExceptionRoutedEventArgs e)
{
    String hr = String.Empty;
    String token = 
"HRESULT - ";
    
const 
int hrLength = 10;      
// eg "0xFFFFFFFF"
 
    
int tokenPos = e.ErrorMessage.IndexOf(token, StringComparison.Ordinal);
    
if (tokenPos != -1)
    {
        hr = e.ErrorMessage.Substring(tokenPos + token.Length, hrLength);
    }
 
    
return hr;
}
到此为止一个简单的媒体播放器就基本完成了!运行效果图如下:
注意:本博文介绍的媒体播放器在实际应用开发中,对于开发者是远远不够理想的,我们需要在此基础上进一步去优化。
最后引用MSDN中给到的
性能注意事项
音频和视频播放是非常耗费资源的操作。有关媒体应用性能的详细信息,可参阅
1)尽可能显示全屏视频播放
XAML 框架可以在只呈现视频时优化呈现的视频,这种情况类似于全屏播放的情况。 此方法使用较少的电源,并且产生高于同时显示其他元素情况下的频率。若要优化媒体播放,请将 
2)延迟设置 MediaElement 源
XAML 框架尽可能长地延迟加载 DLL 和创建大型对象。
3)将视频分辨率与设备分辨率匹配
解码视频主要使用内存和 GPU,因此应选择与要在其上显示的设备的分辨率接近的视频格式。例如,解码高清 (1080) 视频,然后将其缩小至相当小的尺寸进行显示会占有不必要的资源。许多应用不会将相同的视频解码为不同的分辨率,但如果可用,请使用接近显示设备的分辨率的解码。
4)请勿动态显示 MediaElement 对象。
动画和媒体播放都会耗费大量系统资源。 在合适的上下文中使用动画可以创建完美动人的效果。 但是,出于性能方面考虑,请避免在使用 C++、C# 或 Visual Basic 的 Metro 风格应用中动态显示 
 
 本文转自 王祖康 51CTO博客,原文链接:http://blog.51cto.com/wzk89/1033384
,如需转载请自行联系原作者
你可能感兴趣的文章
USNews大学排名遭美国计算机研究学会怒怼,指排名荒谬要求撤回
查看>>
struts1——静态ActionForm与动态ActionForm
查看>>
七大关键数据 移动安全迎来历史转折点
查看>>
在AngularJS中学习javascript的new function意义及this作用域的生成过程
查看>>
盘点物联网网关现有联网技术及应用场景
查看>>
网络钓鱼大讲堂 Part3 | 网络钓鱼攻击向量介绍
查看>>
阿里云与Intel联合发布加密计算,亚洲首个云上“芯片级”数据保护
查看>>
1、下载安装scala编译器(可以理解为scala的jdk),地址:http://www.scala
查看>>
mui 总结2--新建第一个app项目
查看>>
nginx的lua api
查看>>
考研太苦逼没坚持下来!看苑老师视频有点上头
查看>>
HCNA——RIP的路由汇总
查看>>
zabbix监控php状态(四)
查看>>
定时任务的创建
查看>>
实战Django:小型CMS Part2
查看>>
原创]windows server 2012 AD架构试验系列 – 16更改DC计算机名
查看>>
统治世界的十大算法
查看>>
linux svn安装和配置
查看>>
SSH中调用另一action的方法(chain,redirect)
查看>>
数据库基础
查看>>