先说下优缺点
优点:与电脑无关,能播放主流编码格式视频。
缺点:只能播放本地视频,网络视频播放不了。
下面是具体操作和代码
1. 安装Vlc.DotNet.Forms 和 VideoLAN.LibVLC.Windows
Vlc.DotNet.Forms 是播放库,VideoLAN.LibVLC.Windows用于播放显示
2. 界面布局
用到 vlcControl: 视频播放组件 ;滑块 TrackBar :自定义控件,用于显示视频播放进度和音量;button:视频播放和快进
我播放是网上的视频, 所以调用线程先将视频下载到本地,下载完成后在播放。
lTrackBar_vedio 和 lTrackBar_voice 是我自定义的滑块,可以直接用系统默认的滑块控件。
public partial class Form1 : Form
{
private string url = @"http://www.xxxxx.com/video/20240111155329.mp4";
private string vedioPath = AppDomain.CurrentDomain.BaseDirectory + @"Vedio\123.mp4";
private long vedioLength = 0;
private string vedioTime;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
if (!Directory.Exists(AppDomain.CurrentDomain.BaseDirectory + @"\Vedio"))
Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + @"\Vedio");
if (!File.Exists(vedioPath))
{
VedioDownloader urlDownloader = new VedioDownloader(vedioPath, url);
new Thread(new ThreadStart(urlDownloader.DownloadFileAsync)).Start(); ;
}
else
{
InitVedio();
}
}
private void InitVedio()
{
vlcControl1.Play(new FileInfo(vedioPath));
button_play.BackgroundImage = Properties.Resources.audioPlay;
vlcControl1.Audio.Volume = this.lTrackBar_voice.L_Value;
lTrackBar_vedio.L_Maximum = this.lTrackBar_vedio.Width;
lTrackBar_vedio.L_Minimum = 0;
}
//加载播放需要的库
private void vlcControl1_VlcLibDirectoryNeeded(object sender, Vlc.DotNet.Forms.VlcLibDirectoryNeededEventArgs e)
{
var currentAssembly = Assembly.GetEntryAssembly();
var currentDirectory = new FileInfo(currentAssembly.Location).DirectoryName;
if (currentDirectory != null)
{
if (IntPtr.Size == 4)
{
e.VlcLibDirectory = new DirectoryInfo(Path.GetFullPath(@".\libvlc\win-x86"));
}
else
{
e.VlcLibDirectory = new DirectoryInfo(Path.GetFullPath(@".\libvlc\win-x64"));
}
}
if (!e.VlcLibDirectory.Exists)
{
var folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog();
folderBrowserDialog.Description = "Select Vlc libraries folder.";
folderBrowserDialog.RootFolder = Environment.SpecialFolder.Desktop;
folderBrowserDialog.ShowNewFolderButton = true;
if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
{
e.VlcLibDirectory = new DirectoryInfo(folderBrowserDialog.SelectedPath);
}
}
}
private void vlcControl1_TimeChanged(object sender, Vlc.DotNet.Core.VlcMediaPlayerTimeChangedEventArgs e)
{
vedioLength = vlcControl1.VlcMediaPlayer.Length;
string allTime = ConvertTimeStampToDateTime(vedioLength);
string current = ConvertTimeStampToDateTime(vlcControl1.VlcMediaPlayer.Time);
this.lTrackBar_vedio.L_Value = Convert.ToInt32(1.0f * (lTrackBar_vedio.L_Maximum - lTrackBar_vedio.L_Minimum) * vlcControl1.VlcMediaPlayer.Time / vedioLength);
vedioTime = current + " / " + allTime;
SetVedioTime(vedioTime);
}
/// <summary>
/// 使用委托显示视频时间
/// </summary>
/// <param name="text"></param>
delegate void SetTextCallBack(string text);
private void SetVedioTime(string vedioTime)
{
if (this.label_vedioTime.InvokeRequired)
{
SetTextCallBack stcb = new SetTextCallBack(SetVedioTime);
this.BeginInvoke(stcb, new object[] { vedioTime });
}
else
{
this.label_vedioTime.Text = vedioTime;
}
}
private string ConvertTimeStampToDateTime(long vedioLength)
{
DateTime dt = new DateTime(vedioLength * 10000);
return dt.Hour.ToString().PadLeft(2, '0') + ":" + dt.Minute.ToString().PadLeft(2, '0') + ":" + dt.Second.ToString().PadLeft(2, '0');
}
private void button_play_Click(object sender, EventArgs e)
{
if (vlcControl1.State == Vlc.DotNet.Core.Interops.Signatures.MediaStates.Playing)
{
vlcControl1.Pause();
button_play.BackgroundImage = Properties.Resources.audioPause2;
}
else
{
if (vlcControl1.State == Vlc.DotNet.Core.Interops.Signatures.MediaStates.Ended)
{
InitVedio();
}
else
{
button_play.BackgroundImage = Properties.Resources.audioPlay;
vlcControl1.Play();
}
}
}
private void button_voice_Click(object sender, EventArgs e)
{
if (lTrackBar_voice.L_Value != 0)
{
lTrackBar_voice.L_Value = 0;
button_voice.BackgroundImage = Properties.Resources.voice_close;
}
else
{
lTrackBar_voice.L_Value = 80;
button_voice.BackgroundImage = Properties.Resources.voice_open;
}
}
private void lTrackBar_voice_LValueChanged(object sender, LEventArgs e)
{
vlcControl1.Audio.Volume = lTrackBar_voice.L_Value;
}
private void vlcControl1_Stopped(object sender, Vlc.DotNet.Core.VlcMediaPlayerStoppedEventArgs e)
{
button_play.BackgroundImage = Properties.Resources.audioPause2;
}
private void lTrackBar_vedio_MouseMove(object sender, MouseEventArgs e)
{
PlayInNewLocation(sender,e);
}
private void lTrackBar_vedio_MouseDown(object sender, MouseEventArgs e)
{
PlayInNewLocation(sender,e);
}
private void PlayInNewLocation(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (vlcControl1.State == Vlc.DotNet.Core.Interops.Signatures.MediaStates.Ended)
{
InitVedio();
}
vlcControl1.VlcMediaPlayer.Time = this.lTrackBar_vedio.L_Value * vedioLength / (lTrackBar_vedio.L_Maximum - lTrackBar_vedio.L_Minimum);
}
}
private void button1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
vlcControl1.Rate = 2.5f;
}
private void button1_MouseUp(object sender, MouseEventArgs e)
{
vlcControl1.Rate = 1;
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
// vlcControl在stop的过程中可能会产生子窗口消息,然而子窗口消息是在主线程(UI线程)中处理的,而stop()方法也是在主线程中调用的,这就造成了竞争性死锁。所以先释放掉主窗体,在释放vlcControl
this.Dispose();
if (vlcControl1.State != Vlc.DotNet.Core.Interops.Signatures.MediaStates.Stopped)
vlcControl1.Stop();
vlcControl1.Dispose();
}
}