前段时间在 WPF 中实现了【MediaElement + 定时器】的自动轮播。用了一段时间之后,没啥大问题,但是发现,个别 MP4 视频,在播放的时候,有卡顿的现象,看网上说是 MediaElement 解码的问题,建议使用 VLC,所以,再次改造,用 VLC 代替 MediaElement 来试试。
很多教程,都是使用二次封装 VLC 的库,但我不想使用二次封装的,所以这里直接使用官方的库(以下地址都是官方地址,内容是英文的,暂时没有中文翻译)。
1. 添加引用
<ItemGroup>
<PackageReference Include="LibVLCSharp.WPF" Version="3.7.0" />
<PackageReference Include="VideoLAN.LibVLC.Windows" Version="3.0.18" />
</ItemGroup>
很多教程,都让安装最新的 VLC 播放器,然后去安装目录找 DLL 什么的,其实没必要,官方有相应的库,直接在 Nuget 添加引用就好了(VideoLAN.LibVLC.Windows)。
2. WPF 文件
// 就是添加了 VLC 的命名空间,同时添加了 VLC 的控件(VideoView)
<Window x:Class="WpfVlcDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfVlcDemo"
xmlns:vlc="clr-namespace:LibVLCSharp.WPF;assembly=LibVLCSharp.WPF"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<vlc:VideoView x:Name="Wrapper" />
</Grid>
</Window>
3. CS 文件
using LibVLCSharp.Shared;
using System;
using System.IO;
using System.Timers;
using System.Windows;
namespace WpfVlcDemo;
public partial class MainWindow : Window
{
private readonly Timer _timer;
private readonly string[] _videos;
private LibVLC _libVlc;
private MediaPlayer _player;
private Media _media1, _media2;
private int _idx = 0;
public MainWindow()
{
InitializeComponent();
_videos = Directory.GetFiles("<播放素材目录>");
_timer = new()
{
Interval = 10000 // 10 秒切换素材
};
_timer.Elapsed += Timer_Elapsed;
Wrapper.Loaded += Wrapper_Loaded;
}
private void Wrapper_Loaded(object sender, RoutedEventArgs e)
{
Core.Initialize();
_libVlc = new();
_player = new(_libVlc);
_player.Opening += Player_Opening;
Wrapper.MediaPlayer = _player;
_media1 = new(_libVlc, new Uri(_videos[_idx++])); // 准备第一个素材
_timer.Start(); // 开始计时
_player.Play(_media1); // 开始播放
}
private void Player_Opening(object sender, EventArgs e)
{
if (_idx == _videos.Length)
{
_idx = 0; // 素材列表播放完毕之后,重新开始播放
}
_media2 = new(_libVlc, new Uri(_videos[_idx++])); // 准备下一个素材
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
_media1 = _media2;
_player.Play(_media1);
}
}
至此,测试代码就全部完毕了,可以直接运行看效果了。
特别说明:
- 上面的代码,没有释放内存,如果用于生产中,需要自己释放 Media、Player 的内存
- 相邻的两个素材,在切换的时候,会有很短暂的黑屏现象,上面用了两个 Media 对象,试图解决这个问题,但是,效果不明显,还在寻求其他方法,比如用两个播放器(类似上一篇文章那样,用两个 MediaElement 交替),或者像网上说的,保留最后一帧的画面作为背景,直到后面的素材开始播放才取消背景
网友评论