问题描述
我正在尝试将 LibVLCSharp 与播放列表(或者这就是计划)一起使用,并且正在使用两个不同视频之间的基本循环对其进行测试。我在 WPF 中使用它。用户界面有一个按钮来开始第一个视频播放。如果我不循环并每次都单击按钮,下一个视频将按预期播放。让它循环并在第二个视频上发生线程错误。我已经查看了 SO - How to achieve looping playback with Libvlcsharp 上的其他一些帖子以及其中的各种链接,但我遗漏了一些东西。我希望有人有建议 - 或两个!谢谢。
XAML
<Window
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:wpf="clr-namespace:LibVLCSharp.WPF;assembly=LibVLCSharp.WPF"
xmlns:local="clr-namespace:testVLC"
xmlns:Properties="clr-namespace:testVLC.Properties" x:Class="testVLC.MainWindow"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.ColumnDeFinitions>
<ColumnDeFinition Width=".2*"/>
<ColumnDeFinition Width="1*"/>
<ColumnDeFinition Width="1*"/>
<ColumnDeFinition Width="1*"/>
<ColumnDeFinition Width="1*"/>
<ColumnDeFinition Width=".2*"/>
</Grid.ColumnDeFinitions>
<Grid.RowDeFinitions>
<RowDeFinition Height=".25*"/>
<RowDeFinition Height="2*"/>
<RowDeFinition Height="1*"/>
<RowDeFinition Height=".25*"/>
<RowDeFinition Height=".25*"/>
</Grid.RowDeFinitions>
<wpf:VideoView x:Name="VLC_player" Grid.Column="1" Grid.ColumnSpan="4" Grid.Row="0" Grid.RowSpan="3" Background="Black" Loaded="VLC_player_Loaded"/>
<Button x:Name="go_Btn" Content="Press to view video" Grid.Column="2" HorizontalAlignment="Right" Grid.Row="3" Padding="4,1" Margin="0,1,0" Click="Button_click"/>
<TextBox x:Name="countTBox" Grid.Column="2" HorizontalAlignment="Left" Grid.Row="3" Width="30" VerticalContentAlignment="Stretch"/>
</Grid>
</Window>
CS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using LibVLCSharp.Shared;
using MediaPlayer = LibVLCSharp.Shared.MediaPlayer;
namespace testVLC
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
LibVLC _libVLC;
MediaPlayer media_player;
bool init_flag = false;
bool Web_flag = false;
int count = 0;
public MainWindow()
{
InitializeComponent();
}
private async void Media_play (string URI)
{
if (init_flag)
{
if(Web_flag)
{
_libVLC = new LibVLC("--verbose=2");
Media media = new Media(_libVLC,(URI),FromType.FromLocation);
await media.Parse(MediaParSEOptions.ParseNetwork);
media_player = new MediaPlayer(media.SubItems.First());
VLC_player.MediaPlayer = media_player;
media_player.EndReached += Video_Ended;
media_player.Play();
//MessageBox.Show(Thread.CurrentThread.Name);
}
else
{
_libVLC = new LibVLC();
media_player = new MediaPlayer(_libVLC);
VLC_player.MediaPlayer = media_player;
media_player.EndReached += Video_Ended;
media_player.Play(new Media(_libVLC,URI));
}
}
}
private void Button_click(object sender,RoutedEventArgs e)
{
count++;
this.dispatcher.Invoke((Action)(() =>
{
countTBox.Text = count.ToString();
}));
Main_List();
}
private async void Video_Ended(object sender,EventArgs e)
{
//ThreadPool.QueueUserWorkItem(_ => media_player.Stop());//doesn't work
await Task.Run(() => media_player.Stop());
Web_flag = false;
//Button_click(this,null);//Works fine when commented out and the "Press to view video" button is clicked each time. Not so much when looping.
}
private void Main_List()
{
if (count%2 == 0)//even
{
Media_play("C:\\Users\\echo_\\Downloads\\videoplayback (1).mp4");
}
else//odd
{
Web_flag = true;
Media_play("https://youtu.be/UK4t59mhIhs");
}
}
private void VLC_player_Loaded(object sender,RoutedEventArgs e)
{
init_flag = true;
Core.Initialize();
}
}
}
解决方法
不要尝试在 VideoEnded 事件中调用 Stop,我认为 libvlc 3 中该区域存在一个已知问题,该问题会挂起程序。 改为使用新媒体调用 .Play。
另外,如果可以避免的话,我不建议使用两个不同的 libvlc 实例。 1 个 LibVlc 和 1 个媒体播放器,但在同一个 MediaPlayer 上有多个 Play() 将是常态。如果您需要不同的选项,您可以将不同的选项作为媒体选项传递(尽管有些选项在媒体级别不可用,例如冗长选项(在这种情况下,我会注册一个日志回调并在那里进行过滤))>