採用VLC解碼器,能播放市面上幾乎所有格式影片。
Models:SysInfo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MvvmPlayer.Models
{
public class SysInfo
{
public string Title { get; set; } //標題
public string MediaFile { get; set; } //媒體文件
public float MediaPosition { get; set; } //播放進度
public string MediaTime { get; set; } //播放時間
//public double MediaVolume { get; set; } //音量
//public bool IsMute { get; set; } //是否靜音
}
}
ViewModels:VideoPlayerViewModel
using GalaSoft.MvvmLight;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Vlc.DotNet.Core;
using Vlc.DotNet.Wpf;
using MvvmPlayer.Models;
using System.Windows.Media;
using System.Windows.Input;
using GalaSoft.MvvmLight.Command;
using Microsoft.Win32;
using Vlc.DotNet.Core.Medias;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
namespace MvvmPlayer.ViewModels
{
public class VideoPlayerViewModel : ViewModelBase
{
#region 構造方法
public VideoPlayerViewModel()
{
if (!VlcContext.IsInitialized)
InitEncoder();
_sysInfo = new SysInfo();
myVideo = new VlcControl();
this.Title = "作者:騰飛大俠 郵箱:[email protected]";
this.MediaTime = "作者:騰飛大俠 郵箱:[email protected]";
this.PlayerWindowStyle = WindowStyle.ThreeDBorderWindow; this.PlayerWindowState = WindowState.Normal; this.GridVideoScaleY = 1; this.MyVideo.TimeChanged += myVideo_TimeChanged; //定義視頻播放時間改變事件 this.MyVideo.PositionChanged += myVideo_PositionChanged;
//定義播放位置改變事件 } #endregion #region 初始化事件 // 播放控件拖放事件 void gridVideo_Drop(object sender, DragEventArgs e) { //獲取拖拽的文件 string fileName = ((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString(); this.MyVideo.Stop(); this.MyVideo.Media = new
PathMedia(fileName); System.Threading.Thread.Sleep(1); this.MyVideo.Play(); } //播放控件拖放事件 void gridVideo_DragEnter(object sender, DragEventArgs e) { //僅支持文件的拖放 if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effects = DragDropEffects.Link; else e.Effects
= DragDropEffects.None; } // 窗口關閉事件 private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { VlcContext.CloseAll(); //關閉解碼器環境 } // 播放位置改變事件 private void myVideo_PositionChanged(VlcControl sender, VlcEventArgs<float> e) { if (myPositionChanging)
//如果正在拖動進度條,則暫時不改變進度條的值 return; this.MediaPosition = e.Data; //改變進度條的值 } #region 進度條處理事件 // 進度條拖動事件 private bool myPositionChanging; private void sliderPosition_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { myPositionChanging
= true; //位置改變設置爲true this.MediaPosition = (float)sliderPosition.Value; //媒體進度值等於進度條的值 this.MyVideo.PositionChanged -= myVideo_PositionChanged; //刪除播放位置改變事件 } // 完成拖播放進度條 private void sliderPosition_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs
e) { this.MyVideo.Position = (float)sliderPosition.Value; //設置播放進度,等於進度條的值 this.MyVideo.PositionChanged += myVideo_PositionChanged; //添加播放位置改變事件 myPositionChanging = false; } // 進度條值改變 void sliderPosition_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double>
e) { this.MediaPosition = (float)e.NewValue; //設置播放位置 } #endregion // 鼠標移動時,顯示播放進度條 DispatcherTimer timer1 = null; void gridVideo_MouseMove(object sender, MouseEventArgs e) { if (timer1 == null) { timer1 = new DispatcherTimer(); } if (this.PlayerWindowState
== WindowState.Maximized) //判斷窗口是否爲最大化 { SliderPositionVisibility = Visibility.Visible; //顯示播放進度條 Mouse.OverrideCursor = null; //恢復鼠標顯示 timer1.Interval = TimeSpan.FromSeconds(4); //鼠標4秒不動,自動隱藏 timer1.Tick += (s, e1) => { SliderPositionVisibility = Visibility.Hidden;
//隱藏播放進度條 Mouse.OverrideCursor = Cursors.None; //隱藏鼠標 timer1.IsEnabled=false; //禁用計時器 }; timer1.IsEnabled=true; } else if(this.playerWindowState==WindowState.Normal) { timer1.IsEnabled=false; SliderPositionVisibility = Visibility.Visible; //顯示進度條 Mouse.OverrideCursor
= null; //恢復鼠標顯示 } } // 播放時間改變 private void myVideo_TimeChanged(VlcControl sender, VlcEventArgs<TimeSpan> e) { var duration = this.MyVideo.Media == null ? TimeSpan.Zero : this.MyVideo.Media.Duration; var time = TimeSpan.FromMilliseconds(duration.TotalMilliseconds
* this.MediaPosition); //顯示播放時間 this.MediaTime = string.Format("時間:" + "{0:00}:{1:00}:{2:00}/{3:00}:{4:00}:{5:00}", time.Hours, time.Minutes, time.Seconds, duration.Hours, duration.Minutes, duration.Seconds ); //設置媒體時間屬性 } //private void Media_ParsedChanged(MediaBase
sender, VlcEventArgs<int> e) //{ // this.MediaTime = string.Format( // "時間:{0:00}:{1:00}:{2:00}", // this.MyVideo.Media.Duration.Hours, // this.MyVideo.Media.Duration.Minutes, // this.MyVideo.Media.Duration.Seconds // ); // this.MediaVolume = myVideo.AudioProperties.Volume;
//} #endregion #region 初始化屬性 private double gridVideoScaleY; public double GridVideoScaleY //視頻翻轉 { get { return gridVideoScaleY; } set { gridVideoScaleY = value; RaisePropertyChanged("GridVideoScaleY"); } } private bool playerTopmost; public bool PlayerTopmost
//窗口置頂 { get { return playerTopmost; } set { playerTopmost = value; RaisePropertyChanged("PlayerTopmost"); } } private WindowStyle playerWindowStyle; public WindowStyle PlayerWindowStyle //窗口樣式 { get { return playerWindowStyle; } set { playerWindowStyle =
value; RaisePropertyChanged("PlayerWindowStyle"); } } private Visibility sliderPositionVisibility; public Visibility SliderPositionVisibility //進度條狀態 { get { return sliderPositionVisibility; } set { sliderPositionVisibility = value; RaisePropertyChanged("SliderPositionVisibility");
} } private Visibility ctrolPanelVisibility; public Visibility CtrolPanelVisibility //控制面板狀態 { get { return ctrolPanelVisibility; } set { ctrolPanelVisibility = value; RaisePropertyChanged("CtrolPanelVisibility"); } } private WindowState playerWindowState;
public WindowState PlayerWindowState //器窗口狀態 { get { return playerWindowState; } set { if (playerWindowState != value) { playerWindowState = value; RaisePropertyChanged("PlayerWindowState"); } } } private VlcControl myVideo; public VlcControl MyVideo //定義VlcControl控件
{ get { return myVideo; } } private SysInfo _sysInfo; public SysInfo SysInfo //系統信息 { get { return _sysInfo; } set { _sysInfo = value; } } public string Title //標題 { get { return SysInfo.Title; } set { SysInfo.Title = value; RaisePropertyChanged("Title");
} } public string MediaFile //媒體文件 { get { return SysInfo.MediaFile; } set { SysInfo.MediaFile = value; RaisePropertyChanged("MediaFile"); } } public float MediaPosition //播放位置 { get { return SysInfo.MediaPosition; } set { if (SysInfo.MediaPosition != value)
{ SysInfo.MediaPosition = value; RaisePropertyChanged("MediaPosition"); } } } public int MediaVolume //音量 { get { return MyVideo.AudioProperties.Volume; } set { if (MyVideo.AudioProperties.Volume != value) { MyVideo.AudioProperties.Volume = value; RaisePropertyChanged("MediaVolume");
} } } public string MediaTime //播放時間 { get { return SysInfo.MediaTime; } set { SysInfo.MediaTime = value; RaisePropertyChanged("MediaTime"); } } #endregion #region 初始化命令 public ICommand WindowCommand //窗體命令 { get { return new RelayCommand<RoutedEventArgs>((e)
=> { if (Application.Current.Properties["VideoPlayerArgName"] != null) //如果啓動的時候帶媒體參數 { string fname = Application.Current.Properties["VideoPlayerArgName"].ToString(); //ArbitraryArgName要與APP裏面設置的名字相同 this.MyVideo.Media = new PathMedia(fname); MyVideo.Play();
} Window videoPlayer=e.OriginalSource as Window; videoPlayer.Closing += Window_Closing; }); } } public ICommand TxtgridVideoScaleTransformCommand //視頻翻轉 { get { return new RelayCommand<MouseButtonEventArgs>((e) => { if (this.GridVideoScaleY == 1) { this.GridVideoScaleY
= -1; } else if (this.GridVideoScaleY == -1) { this.GridVideoScaleY = 1; } }); } } Slider sliderPosition = null; public ICommand SliderPositionCommand //進度條初始化命令 { get { return new RelayCommand<RoutedEventArgs>((e) => { sliderPosition = e.OriginalSource as
Slider; sliderPosition.PreviewMouseLeftButtonDown += sliderPosition_MouseLeftButtonDown; sliderPosition.PreviewMouseLeftButtonUp += sliderPosition_MouseLeftButtonUp; sliderPosition.ValueChanged += sliderPosition_ValueChanged; }); } } int i = 0; Grid gridVideo
= null; public ICommand GridVideoCommand //播放控件命令 { get { return new RelayCommand<RoutedEventArgs>((e) => { gridVideo = e.OriginalSource as Grid; //獲取事件觸發源 gridVideo.MouseLeftButtonDown += gridVideo_MouseLeftButtonDown; gridVideo.DragEnter += gridVideo_DragEnter;
gridVideo.Drop += gridVideo_Drop; }); } } /// <summary> /// 播放控件鼠標單擊事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void gridVideo_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { i++; DispatcherTimer timer = new
DispatcherTimer(); timer.Interval = new TimeSpan(0, 0, 0, 0, 300); //雙擊間隔時間爲300毫秒 timer.Tick += (s, e1) => { timer.IsEnabled = false; i = 0; }; timer.IsEnabled = true; if (i % 2 == 0) { timer.IsEnabled = false; i = 0; if (this.PlayerWindowState != WindowState.Maximized)
//雙擊全屏 { gridVideo.MouseMove += gridVideo_MouseMove; //鼠標移動事件 this.PlayerWindowStyle = WindowStyle.None; //設置窗口樣式 this.PlayerWindowState = WindowState.Maximized; //設置窗口大小 //如果想讓開始菜單顯示出來,跟上面正好相反 //this.WindowState = WindowState.Maximized; //this.WindowStyle
= WindowStyle.None; this.CtrolPanelVisibility = Visibility.Collapsed; //隱藏控件 this.SliderPositionVisibility = Visibility.Collapsed; gridVideo.Margin = new Thickness(0, 0, 0, 0); //設置邊界 //gridVideo.Width = SystemParameters.WorkArea.Width; this.PlayerTopmost
= true; //窗口置頂 } else if (this.playerWindowState == WindowState.Maximized) //全屏狀態下,雙擊恢復正常狀態 { timer1.IsEnabled = false; //禁用timer1,否則從全屏切換到正常狀態下,進度條會隱藏 gridVideo.MouseMove -= gridVideo_MouseMove; this.PlayerWindowState = WindowState.Normal; this.PlayerWindowStyle
= WindowStyle.SingleBorderWindow; this.CtrolPanelVisibility = Visibility.Visible; this.SliderPositionVisibility = Visibility.Visible; gridVideo.Margin = new Thickness(0, 0, 0, 54); this.PlayerTopmost = false; Mouse.OverrideCursor = null; } } } public ICommand
OpenMediaFile //打開 { get { return new RelayCommand(() => { this.MyVideo.Stop(); this.MediaPosition = 0; var ofd = new OpenFileDialog { FileName = "", Title = "打開媒體文件", Filter = "所有文件|*.*" }; //ofd.InitialDirectory = Environment.CurrentDirectory; ofd.RestoreDirectory
= true; if (ofd.ShowDialog() != true || ofd.FileName == null) return; this.Title = System.IO.Path.GetFileName(ofd.FileName); this.MediaFile = ofd.FileName; this.MyVideo.Media = new PathMedia(this.MediaFile); //this.MyVideo.Media.ParsedChanged += Media_ParsedChanged;
this.MyVideo.Play(); }); } } public ICommand PlayMedia //播放 { get { return new RelayCommand(() => { this.MyVideo.Play(); }); } } public ICommand PauseMedia //暫停 { get { return new RelayCommand(() => { this.MyVideo.Pause(); }); } } public ICommand StopMedia
//停止 { get { return new RelayCommand(() => { this.MyVideo.Stop(); this.MediaPosition = 0; this.MediaTime = "作者:騰飛大俠 郵箱:[email protected]"; }); } } #endregion /// <summary> /// 初始化解碼器 /// </summary> private void InitEncoder() { #region 初始化 // 設置解碼器路徑 //VlcContext.LibVlcDllsPath
= System.IO.Path.Combine(Environment.CurrentDirectory, "libs"); VlcContext.LibVlcDllsPath = @"D:\VLC"; // 設置解碼器插件路徑 //VlcContext.LibVlcPluginsPath = System.IO.Path.Combine(Environment.CurrentDirectory, @"libs\plugins"); VlcContext.LibVlcPluginsPath = @"D:\VLC\plugins";
// 忽略解碼器配置文件 VlcContext.StartupOptions.IgnoreConfig = true; // 是否記錄日誌文件 VlcContext.StartupOptions.LogOptions.LogInFile = false; // 顯示解碼器日誌控件臺 VlcContext.StartupOptions.LogOptions.ShowLoggerConsole = false; // 設置解碼器記錄日誌級別 VlcContext.StartupOptions.LogOptions.Verbosity
= VlcLogVerbosities.Debug; // 顯示媒體文件名稱 VlcContext.StartupOptions.AddOption("--no-video-title-show"); // 最後一個畫面顯示播放或暫停 //VlcContext.StartupOptions.AddOption("--play-and-pause"); // 初始化解碼器 VlcContext.Initialize(); #endregion } }}
Views:VideoPlayer.xaml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MvvmPlayer.ViewModels"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:Custom="http://www.galasoft.ch/mvvmlight"
x:Class="MvvmPlayer.Views.VideoPlayer"
Title="{Binding Title}" Height="600" Width="800" Icon="Application.ico"
Background="#FF47A2D6" WindowStyle="{Binding PlayerWindowStyle}"
Topmost="{Binding PlayerTopmost}"
WindowState="{Binding PlayerWindowState}"
WindowStartupLocation="CenterScreen">
<Window.DataContext>
<local:VideoPlayerViewModel/>
</Window.DataContext>
<!--動畫-->
<!--<Window.Resources>
<Storyboard x:Key="gridVideoStoryboard">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="gridVideo">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="-1"/>
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="-1"/>
<EasingDoubleKeyFrame KeyTime="0:0:3" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="UIElement.MouseRightButtonDown" SourceName="gridVideo">
<BeginStoryboard Storyboard="{StaticResource gridVideoStoryboard}" x:Name="bs1"/>
</EventTrigger>
</Window.Triggers>-->
<Grid x:Name="VideoPanel" Background="#FF280AE8">
<!--<Wpf:VlcControl x:Name="myVideo"/>-->
<!--視頻播放控件-->
<Grid x:Name="gridVideo" Grid.Row="0" Margin="0,0,0,54" RenderTransformOrigin="0.5,0.5" AllowDrop="True" >
<Grid.RenderTransform>
<TransformGroup>
<!--視頻翻轉-->
<ScaleTransform x:Name="gridVideost" ScaleY="{Binding GridVideoScaleY}"/>
<!--<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>-->
</TransformGroup>
</Grid.RenderTransform>
<Grid.Background>
<VisualBrush>
<VisualBrush.Visual>
<Image Source="{Binding MyVideo.VideoSource}"/>
</VisualBrush.Visual>
</VisualBrush>
</Grid.Background>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded" SourceName="gridVideo">
<Custom:EventToCommand Command="{Binding GridVideoCommand}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Grid>
<StackPanel x:Name="CtrolPanel" Visibility="{Binding CtrolPanelVisibility}" Height="36" Margin="0,0,0,1" VerticalAlignment="Bottom" Orientation="Horizontal">
<StackPanel.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF0E21E4" Offset="0"/>
<GradientStop Color="White" Offset="0.474"/>
<GradientStop Color="#FF0C1FEC" Offset="1"/>
</LinearGradientBrush>
</StackPanel.Background>
<TextBlock Margin="8,5,0,0" Height="24.24" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="13.333" Text="音量:"/>
<Slider Width="50" x:Name="sliderVolume" Maximum="200" SmallChange="1" LargeChange="5" Margin="2,0,0,0" Height="24.24" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="13.333" BorderThickness="0,3,0,0" Value="{Binding MediaVolume, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Text="視頻翻轉" Height="24.24" Margin="8,8,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="13.333" x:Name="txtgridVideoScaleTransform" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown" SourceName="txtgridVideoScaleTransform">
<Custom:EventToCommand Command="{Binding TxtgridVideoScaleTransformCommand}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
<Button x:Name="btnOpen" Content="打開" HorizontalAlignment="Center" VerticalAlignment="Center" Width="75" Height="24.24" FontSize="13.333" Margin="10,0,0,0" Command="{Binding OpenMediaFile}"/>
<Button x:Name="btnPlay" Content="播放" HorizontalAlignment="Center" Margin="15,0,0,0" VerticalAlignment="Center" Width="75" Height="24.24" FontSize="13.333" Command="{Binding PlayMedia}"/>
<Button x:Name="btnPause" Content="暫停" HorizontalAlignment="Center" Margin="15,0,0,0" VerticalAlignment="Center" Width="75" Height="24.24" FontSize="13.333" Command="{Binding PauseMedia}"/>
<Button x:Name="btnStop" Content="停止" HorizontalAlignment="Center" Margin="15,0,0,0" VerticalAlignment="Center" Width="75" Height="24.24" FontSize="13.333" Command="{Binding StopMedia}"/>
<TextBlock x:Name="tblTime" Height="24.24" Margin="8,8,0,0" TextWrapping="Wrap" VerticalAlignment="Center" FontSize="13.333" Text="{Binding MediaTime, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
<StackPanel x:Name="SliderPanel" Height="18" Margin="0,0,0,36" VerticalAlignment="Bottom">
<Slider x:Name="sliderPosition" Visibility="{Binding SliderPositionVisibility}" VerticalAlignment="Center" Height="18" Background="{x:Null}" Maximum="1" LargeChange="0.05"
SmallChange="0.01"
Value="{Binding MediaPosition}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded" SourceName="sliderPosition">
<Custom:EventToCommand Command="{Binding SliderPositionCommand}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Slider>
</StackPanel>
</Grid>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<Custom:EventToCommand Command="{Binding WindowCommand}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Window>
App.xaml.cs:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace MvvmPlayer
{
/// <summary>
/// App.xaml 的交互邏輯
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
if (e.Args != null && e.Args.Count() > 0) //如果參數不爲空,且參數個數大於0
{
this.Properties["VideoPlayerArgName"] = e.Args[0];
}
Views.VideoPlayer view = new Views.VideoPlayer();
view.Show();
base.OnStartup(e);
}
}
}