翼度科技»论坛 编程开发 .net 查看内容

基于WPF开发视频播放器

4

主题

4

帖子

12

积分

新手上路

Rank: 1

积分
12
在实际应用中,视频播放功能在很多软件中都会用到,将音频和视频集成到应用程序中不仅可以增强用户体验,还能起到事半功倍的效果。今天本文以一个简单的小例子,简述如何通过WPF中的MediaElement开发视频播放器,仅供学习分享使用,如有不足之处,还请指正!
涉及知识点

在本实例中,开发视频播放器,主要用到MediaElement控件,而MediaElement 是受 Layout 支持的 UIElement,并可用作许多控件的内容。涉及知识点如下:

  • LoadedBehavior,UnloadedBehavior 主要用于控制IsLoaded属性为true和false时的视频播放行为,即视频加载成功和没有加载时的播放行为。此两个属性为MediaState类型,共有五种值供选择,Manual,Play,Stop,Pause,Close。 例如,默认 LoadedBehavior 为 Play,默认 UnloadedBehavior 为 Close。 这意味着,一旦加载 MediaElement 并且预滚完成,媒体开始播放。 一旦播放完毕,媒体就会关闭并且发布所有媒体资源。
  • Source,主要用于指定视频播放源路径,Uri类型。
  • Play、Pause 和 Stop 方法分别用于播放、暂停和停止媒体。 更改 MediaElement 的 Position 属性可让你在媒体中跳转。 最后,Volume 和 SpeedRatio 属性用于调整媒体的音量和播放速度。
注意:MediaElement 的 LoadedBehavior 属性必须设置为 Manual 才能以交互方式停止、暂停和播放媒体。
依赖库

所谓麻雀虽小,五脏俱全,本实例虽然是一个视频播放器的小例子,但是也遵循MVVM的设计思想。主要采用CommunityToolkit.Mvvm,可通过Nuget包管理器进行安装,如下所示:

关于CommunityToolkit.Mvvm的使用方法,可参考相关文档,在此不在赘述。
UI布局

虽然MediaElement控件可以实现视频的播放,但是要实现完整的功能,还需要其他的页面布局控件。在本实例中,主要分为三个组成部分:

  • 播放区,主要用于显示视频的播放内容,时长,播放进度等内容
  • 视频列表,主要用于显示播放的视频的列表,以及手动添加视频到列表中,双击列表项进行播放等。
  • 视频控制,主要用于控制视频的播放,暂停,停止,速度,音量等内容。
视频播放器UI源码如下所示:
  1. <Window x:
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5.         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6.         xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
  7.         xmlns:local="clr-namespace:DemoMedia"
  8.         mc:Ignorable="d"
  9.         Title="Windows Media Player" Height="450" Width="800" Background="AliceBlue">
  10.     <Window.Resources>
  11.         <ResourceDictionary Source="\Resources\Icons.xaml"></ResourceDictionary>
  12.     </Window.Resources>
  13.     <i:Interaction.Triggers>
  14.         <i:EventTrigger EventName="Loaded">
  15.             <i:InvokeCommandAction Command="{Binding LoadedCommand}" PassEventArgsToCommand="True"/>
  16.         </i:EventTrigger>
  17.     </i:Interaction.Triggers>
  18.     <Grid>
  19.         <Grid.ColumnDefinitions>
  20.             <ColumnDefinition></ColumnDefinition>
  21.             <ColumnDefinition Width="Auto" MinWidth="150" MaxWidth="200"></ColumnDefinition>
  22.         </Grid.ColumnDefinitions>
  23.         <Grid>
  24.             <Grid.RowDefinitions>
  25.                 <RowDefinition></RowDefinition>
  26.                 <RowDefinition Height="Auto"></RowDefinition>
  27.                 <RowDefinition Height="Auto"></RowDefinition>
  28.             </Grid.RowDefinitions>
  29.             <Border Grid.Row="0" Background="AliceBlue"></Border>
  30.             <MediaElement Grid.Row="0" Name="mediaElement" MinHeight="300" MinWidth="300"
  31.                           Source="{Binding Model.CurSource}"
  32.                           LoadedBehavior="Manual" UnloadedBehavior="Manual" Stretch="Uniform">
  33.                 <i:Interaction.Triggers>
  34.                     <i:EventTrigger EventName="MediaOpened">
  35.                         <i:InvokeCommandAction Command="{Binding MediaOpenedCommand}"/>
  36.                     </i:EventTrigger>
  37.                     <i:EventTrigger EventName="MediaEnded">
  38.                         <i:InvokeCommandAction Command="{Binding MediaEndedCommand}"/>
  39.                     </i:EventTrigger>
  40.                 </i:Interaction.Triggers>
  41.             </MediaElement>
  42.             <Button Command="{Binding PlayCommand}" HorizontalAlignment="Center" VerticalAlignment="Center" Opacity="0.6" Visibility="{Binding Model.PlayButtonVisibility}" Cursor="Hand">
  43.                 <Button.Template>
  44.                     <ControlTemplate>
  45.                         <Border Background="AliceBlue">
  46.                             <Path Data="{StaticResource play}" Fill="#3259CE" Stroke="#3259CE" Width="30" Height="30" Stretch="Fill" ></Path>
  47.                         </Border>
  48.                     </ControlTemplate>
  49.                 </Button.Template>
  50.             </Button>
  51.             <Grid Grid.Row="1" VerticalAlignment="Bottom" Margin="2 0 2 4">
  52.                 <Grid.ColumnDefinitions>
  53.                     <ColumnDefinition Width="Auto"></ColumnDefinition>
  54.                     <ColumnDefinition></ColumnDefinition>
  55.                     <ColumnDefinition Width="Auto"></ColumnDefinition>
  56.                 </Grid.ColumnDefinitions>
  57.                 <TextBlock Grid.Column="0" Text="00:00" VerticalAlignment="Bottom"></TextBlock>
  58.                 <ProgressBar Grid.Column="1"  Height="5" Background="Black"  Foreground="White" Value="{Binding Model.Position}" Minimum="0" Maximum="{Binding Model.MediaMaximum}"></ProgressBar>
  59.                 <StackPanel Grid.Column="2" Orientation="Horizontal" VerticalAlignment="Bottom">
  60.                     
  61.                     <TextBlock  Text="{Binding Model.TimeLen}"></TextBlock>
  62.                 </StackPanel>
  63.             </Grid>
  64.             <StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center">
  65.                 <Button x:Name="btnPlay" Margin="5" Command="{Binding PlayCommand}">
  66.                     <Button.Template>
  67.                         <ControlTemplate>
  68.                             <Border Background="AliceBlue">
  69.                                 <Path Data="{StaticResource play}" Fill="#3259CE" Stroke="#3259CE" Width="30" Height="30" Stretch="Fill"></Path>
  70.                             </Border>
  71.                         </ControlTemplate>
  72.                     </Button.Template>
  73.                 </Button>
  74.                 <Button x:Name="btnPause" Margin="5"  Command="{Binding PauseCommand}">
  75.                     <Button.Template>
  76.                         <ControlTemplate>
  77.                             <Border Background="AliceBlue">
  78.                                 <Path Data="{StaticResource pause}" Fill="#3259CE" Stroke="#3259CE" Width="30" Height="30" Stretch="Fill"></Path>
  79.                             </Border>
  80.                         </ControlTemplate>
  81.                     </Button.Template>
  82.                 </Button>
  83.                 <Button x:Name="btnStop" Margin="5"  Command="{Binding StopCommand}">
  84.                     <Button.Template>
  85.                         <ControlTemplate>
  86.                             <Border Background="AliceBlue">
  87.                                 <Path Data="{StaticResource stop}" Fill="#3259CE" Stroke="#3259CE" Width="30" Height="30" Stretch="Fill"></Path>
  88.                             </Border>
  89.                         </ControlTemplate>
  90.                     </Button.Template>
  91.                 </Button>
  92.                 <TextBlock Foreground="#3259CE" VerticalAlignment="Center" Margin="5" Text="音量"></TextBlock>
  93.                 <Slider Name="volumeSlider" VerticalAlignment="Center" Value="{Binding ElementName=mediaElement, Path=Volume, Mode=TwoWay}"
  94.                         Minimum="0" Maximum="1" Width="70"/>
  95.                 <TextBlock Foreground="#3259CE" Margin="5"  VerticalAlignment="Center" Text="速度"></TextBlock>
  96.                 <Slider Name="speedRatioSlider" VerticalAlignment="Center"  Value="{Binding ElementName=mediaElement, Path=SpeedRatio, Mode=TwoWay}"  Width="70" />
  97.             </StackPanel>
  98.         </Grid>
  99.         <GridSplitter Grid.Column="0" HorizontalAlignment="Right" Width="2"></GridSplitter>
  100.         <Grid Grid.Column="1" Background="AliceBlue">
  101.             <Grid.RowDefinitions>
  102.                 <RowDefinition Height="Auto" MinHeight="30"></RowDefinition>
  103.                 <RowDefinition></RowDefinition>
  104.             </Grid.RowDefinitions>
  105.             <Border Background="Transparent" BorderBrush="White" BorderThickness="1" Grid.Row="0"></Border>
  106.             <Grid Grid.Row="0" Margin="2">
  107.                 <TextBlock Text="播放列表" VerticalAlignment="Center" HorizontalAlignment="Left"></TextBlock>
  108.                 <Button x:Name="btnOpen" Width="18" Height="18" Command="{Binding BrowserCommand}" Margin="5" HorizontalAlignment="Right">
  109.                     <Button.Template>
  110.                         <ControlTemplate>
  111.                             <Border Background="AliceBlue">
  112.                                 <Path Data="{StaticResource browser}" Stroke="#27A2DF" Fill="White" Width="18" Height="18" Stretch="Fill"></Path>
  113.                             </Border>
  114.                         </ControlTemplate>
  115.                     </Button.Template>
  116.                 </Button>
  117.             </Grid>
  118.             <ListView Grid.Row="1" Margin="2" ItemsSource="{Binding Model.Movies}" BorderThickness="0" SelectionMode="Single" Background="AliceBlue">
  119.                 <ListView.ItemTemplate>
  120.                     <DataTemplate>
  121.                         <StackPanel Orientation="Horizontal">
  122.                             <TextBlock Text="{Binding Id, StringFormat='[00]'}" Margin="2 3"></TextBlock>
  123.                             <TextBlock Text="{Binding Name}" Margin="3 3" ToolTip="{Binding Url}"></TextBlock>
  124.                         </StackPanel>
  125.                     </DataTemplate>
  126.                 </ListView.ItemTemplate>
  127.                 <i:Interaction.Triggers>
  128.                     <i:EventTrigger EventName="MouseDoubleClick">
  129.                         <i:InvokeCommandAction Command="{Binding MouseDoubleCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}, Path=SelectedItem}"/>
  130.                     </i:EventTrigger>
  131.                 </i:Interaction.Triggers>
  132.             </ListView>
  133.         </Grid>
  134.     </Grid>
  135. </Window>
复制代码
在本实例中,为了UI美观,所有按钮都采用图标显示,而图标的实现方式采用几何图形,具体实现方式可参考相关文章。
核心源码

在本实例中,业务逻辑和UI分离,主要实现手动添加视频,及视频的播放,暂停,停止,音量,进度等功能。
浏览视频并加入到播放列表,如下所示:
  1. private void Browser()
  2. {
  3.         OpenFileDialog dialog = new OpenFileDialog();
  4.         dialog.Title = "请选择要播放的影片";
  5.         dialog.Filter = "MP4|*.mp4";
  6.         dialog.Multiselect = true;
  7.         if (dialog.ShowDialog()==true)
  8.         {
  9.                 var files=dialog.FileNames;
  10.                 foreach (var file in files)
  11.                 {
  12.                         var maxId = this.Model.Movies.Count>0 ? this.Model.Movies.Max(x => x.Id):0;
  13.                         if (this.Model.Movies.FirstOrDefault(item => item.Url == file) == null)
  14.                         {
  15.                                 this.Model.Movies.Add(new Movie()
  16.                                 {
  17.                                         Id = maxId + 1,
  18.                                         Name = Path.GetFileNameWithoutExtension(file),
  19.                                         Url = file
  20.                                 });
  21.                         }
  22.                 }
  23.         }
  24. }
复制代码
视频播放功能,开始播放后,单独打开一个线程,用来刷新播放的进度,如下所示:
  1. private void Play()
  2. {
  3.         //影片播放,如果没有,则打开选择文件夹
  4.         if (this.Model.CurMovie == null)
  5.         {
  6.                 this.Browser();
  7.                 if (this.Model.Movies.Count < 1)
  8.                 {
  9.                         return;
  10.                 }
  11.                 this.Model.CurMovie = this.Model.Movies.Last();
  12.         }
  13.         this.Model.CurSource = new Uri(this.Model.CurMovie.Url, UriKind.RelativeOrAbsolute);
  14.         if (this.media.NaturalDuration != Duration.Automatic && this.media.Position.TotalSeconds == this.media.NaturalDuration.TimeSpan.TotalSeconds)
  15.         {
  16.                 this.media.Position=new TimeSpan(0,0,0);
  17.         }
  18.         this.media.Play();
  19.         this.IsRunning = true;
  20.         this.Model.PlayButtonVisibility = Visibility.Collapsed;
  21.         //
  22.         this.mediaTask = Task.Run(() =>
  23.         {
  24.                 while (this.IsRunning)
  25.                 {
  26.                         Application.Current.Dispatcher.Invoke(() =>
  27.                         {
  28.                                 this.Model.Position = this.media.Position.TotalSeconds;
  29.                         });
  30.                         Thread.Sleep(100);
  31.                 }
  32.         });
  33. }
复制代码
注意,MediaElement的Position并非依赖属性,无法进行绑定,所以采用后台线程刷新的方式进行实现。
视频暂停功能,通过MediaElement的Pause方法即可控制视频的暂停,如下所示:
  1. private void Pause()
  2. {
  3.         if (this.Model.CurMovie == null)
  4.         {
  5.                 return;
  6.         }
  7.         this.media.Pause();
  8.         this.IsRunning = false;
  9. }
复制代码
视频停止功能,通过MediaElement的Stop方法即可控制视频的停止,如下所示:
  1. private void Stop()
  2. {
  3.         if (this.Model.CurMovie == null)
  4.         {
  5.                 return;
  6.         }
  7.         this.media.Stop();
  8.         this.IsRunning= false;
  9. }
复制代码
注意,暂停功能是将播放位置保持在当前位置;停止功能是将视频的播放位置重置到初始位置。
视频打开事件,即当视频开始时触发的路由事件,如下所示:
  1. private void MediaOpened()
  2. {
  3.         if (this.media.NaturalDuration.TimeSpan.TotalMinutes < 60)
  4.         {
  5.                 this.Model.TimeLen = this.media.NaturalDuration.TimeSpan.ToString(@"mm\:ss");
  6.         }
  7.         else
  8.         {
  9.                 this.Model.TimeLen = this.media.NaturalDuration.TimeSpan.ToString(@"hh\:mm\:ss");
  10.         }
  11.         this.Model.MediaMaximum = this.media.NaturalDuration.TimeSpan.TotalSeconds;
  12. }
复制代码
注意:在这里,视频开始时,初始化播放时长等内容。
视频结束事件,当视频播放结束时触发的路由事件,如下所示:
  1. private void MediaEnded()
  2. {
  3.         this.Model.PlayButtonVisibility = Visibility.Visible;
  4.         this.IsRunning = false;
  5. }
复制代码
注意,视频播放结束时,将播放状态置为flase,不在监控播放位置。
视频播放器效果

视频播放器初始化页面,如下图所示:

添加视频到播放列表,如下所示:

视频播放效果截图,如下所示:

源码下载

WPF版本的视频播放器,可通过两种方式获取源码:
1. 关注“老码识途”公众号,并回复关键字“WMEDIA”进行获取,如下所示:

2. 通过Gitee仓库【下载网址:https://gitee.com/ahsiang/wpf-media】进行下载,如下所示:

以上就是《基于WPF开发视频播放器》的全部内容,旨在抛砖引玉,一起学习,共同进步!

来源:https://www.cnblogs.com/hsiang/p/18550163
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具