播放 YouTube 的 C# LibVLCSharp 问题
C# LibVLCSharp issue with playing YouTube
我正在尝试在 WPF 应用程序中的多个实例中使用 LibVLC 播放 YouTube。
这可能在 75% 的时间里工作正常,但流会冻结一两秒钟,而在另外 25% 的时间里会被像素化。这似乎是随机的。
这是我的代码:
public async void PlayUri(string path, bool isMuted, bool repeat)
{
await Dispatcher.InvokeAsync(new Action(async () =>
{
Core.Initialize();
using (LibVLC libVLC = new LibVLC(MediaOptions(repeat)))
{
using (var media = new Media(libVLC, path, FromType.FromLocation))
{
await media.Parse(MediaParseOptions.ParseNetwork);
vlcPlayer = new MediaPlayer(media.SubItems.FirstOrDefault());
if (!repeat)
vlcPlayer.EndReached += (sender, args) => ThreadPool.QueueUserWorkItem(_ => waitHandle.Set());
VideoView.MediaPlayer = vlcPlayer;
VideoView.MediaPlayer.Play();
}
// Set the sound and audio output device
SetAudioToDirectsound(isMuted);
}
}));
}
MediaOptions 只是传递一个字符串[]
mediaOptions = new[]
{
"--input-repeat=5",
"--sout-mux-caching=12000"
};
并且(为了完整性)SetAudioToDirectSount(bool)
var directsound = VideoView.MediaPlayer.SetAudioOutput("directsound");
IsMuted = isMuted;
这个“--sout-mux-caching=12000”选项应该缓存接下来的 12 秒视频。
这是正确的吗,我还需要其他选择吗?我查看了所有 cmd 行选项,似乎找不到任何明显的东西。
阅读最佳实践 here,其中提到
“VLC 核心开发人员建议在应用程序的生命周期中只创建一个 LibVLC 类型的实例。您可以从单个 LibVLC 对象创建任意数量的 MediaPlayer 对象。”
在我的例子中,它嵌套在一个 using 语句中,所以我似乎没有遵循最佳实践。所以我应该声明:
Core.Initialize();
public LibVLC libVLC {get; set; } = new LibVLC();
仅一次,并且仅在卸载时处理 MediaPlayer?
最小测试解决方案
名为 VLCStream 的新 WPF 项目
NuGet 安装:
- VideoLAN.LibVLC.Windows
- LibVLCSharp.WPF
- LibVLCSharp
MainWindow.xaml
<Window x:Class="VLCStream.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:vlc="clr-namespace:LibVLCSharp.WPF;assembly=LibVLCSharp.WPF"
xmlns:local="clr-namespace:VLCStream"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800"
Loaded="Window_Loaded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Content="Play" Click="Button_Click" />
<vlc:VideoView x:Name="VideoView" Grid.Row="1" />
</Grid>
</Window>
MainWindow.xaml.cs
using LibVLCSharp.Shared;
using LibVLCSharp.WPF;
using System;
using System.Linq;
using System.Windows;
namespace VLCStream
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Dispatcher.InvokeAsync(new Action(async () =>
{
using (LibVLC libVLC = new LibVLC("--sout-mux-caching=12000"))
{
using (var media = new Media(libVLC, "https://youtu.be/pW-iVG0_D34", FromType.FromLocation))
{
await media.Parse(MediaParseOptions.ParseNetwork);
MediaPlayer vlcPlayer = new MediaPlayer(media.SubItems.FirstOrDefault());
VideoView.MediaPlayer = vlcPlayer;
VideoView.MediaPlayer.Play();
}
}
}));
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Core.Initialize();
}
}
}
问题似乎是随机的,需要超过 1 运行。
对您的代码的一般反馈。
- 在使用媒体播放器的过程中一直对其进行跟踪,用完后将其丢弃。
- 不要在使用 LibVLC 时丢弃它。
- 将每个媒体播放器与视图集成,现在您只是在没有绘图目标的媒体播放器上调用播放。 LibVLC 将随机创建 windows 以供绘制。可能不是你想要的。
现在,打开日志在 VLC 桌面应用程序中播放您的流将提供一些见解:
main error: ES_OUT_SET_(GROUP_)PCR is called too late (pts_delay increased to 2926 ms)
main debug: Received first picture
main error: Timestamp conversion failed for 9480001: no reference clock
main error: Could not convert timestamp 0 for FFmpeg
main debug: Buffering 0%
main debug: Buffering 8%
main debug: Buffering 17%
main debug: Buffering 25%
main debug: Buffering 34%
main debug: Buffering 42%
main debug: Buffering 51%
main debug: Buffering 59%
main debug: Buffering 68%
main debug: Buffering 76%
main debug: Buffering 85%
main debug: Buffering 93%
main debug: Stream buffering done (3000 ms in 7056 ms)
main debug: Decoder wait done in 0 ms
main debug: inserting 307 zeroes
mmdevice debug: state changed: 1
main warning: buffer too late (-217851 us): dropped
main warning: buffer too late (-194631 us): dropped
main error: ES_OUT_SET_(GROUP_)PCR is called too late (pts_delay increased to 3774 ms)
main debug: ES_OUT_RESET_PCR called
main warning: buffer too late (-171411 us): dropped
main debug: Received first picture
main error: Timestamp conversion failed for 15800001: no reference clock
main error: Could not convert timestamp 0 for FFmpeg
mmdevice debug: state changed: 0
这看起来不太好。也许 YouTube 对视频编码不当?或者更可能是 LibVLC 的问题?我不确定。
问题似乎与 youtube.luac 文件有关。
该文件于 2021 年 10 月 19 日左右更新,似乎运行良好。谢谢 Martin 的帮助。
基本项目可用here。
安装的3个包是:
开始之前先删除项目文件夹中的.vs,以及解决方案中的bin和obj文件夹。
转到 here,复制文本块,然后将其粘贴到记事本中。单击文件 ---> 另存为并为其命名 youtube.luac 在该字段下方,通过下拉菜单将“文本文档”(txt) 更改为所有文件,然后单击保存。
替换 32 和 64 包文件夹中的文件。
例如\packages\VideoLAN.LibVLC.Windows.3.0.16\build\x64\lua\playlist
重建您的项目,瞧。
这为我解决了这个问题,并且由于可用的文档很少,希望这会对某人有所帮助..:)
我正在尝试在 WPF 应用程序中的多个实例中使用 LibVLC 播放 YouTube。 这可能在 75% 的时间里工作正常,但流会冻结一两秒钟,而在另外 25% 的时间里会被像素化。这似乎是随机的。
这是我的代码:
public async void PlayUri(string path, bool isMuted, bool repeat)
{
await Dispatcher.InvokeAsync(new Action(async () =>
{
Core.Initialize();
using (LibVLC libVLC = new LibVLC(MediaOptions(repeat)))
{
using (var media = new Media(libVLC, path, FromType.FromLocation))
{
await media.Parse(MediaParseOptions.ParseNetwork);
vlcPlayer = new MediaPlayer(media.SubItems.FirstOrDefault());
if (!repeat)
vlcPlayer.EndReached += (sender, args) => ThreadPool.QueueUserWorkItem(_ => waitHandle.Set());
VideoView.MediaPlayer = vlcPlayer;
VideoView.MediaPlayer.Play();
}
// Set the sound and audio output device
SetAudioToDirectsound(isMuted);
}
}));
}
MediaOptions 只是传递一个字符串[]
mediaOptions = new[]
{
"--input-repeat=5",
"--sout-mux-caching=12000"
};
并且(为了完整性)SetAudioToDirectSount(bool)
var directsound = VideoView.MediaPlayer.SetAudioOutput("directsound");
IsMuted = isMuted;
这个“--sout-mux-caching=12000”选项应该缓存接下来的 12 秒视频。
这是正确的吗,我还需要其他选择吗?我查看了所有 cmd 行选项,似乎找不到任何明显的东西。
阅读最佳实践 here,其中提到
“VLC 核心开发人员建议在应用程序的生命周期中只创建一个 LibVLC 类型的实例。您可以从单个 LibVLC 对象创建任意数量的 MediaPlayer 对象。”
在我的例子中,它嵌套在一个 using 语句中,所以我似乎没有遵循最佳实践。所以我应该声明:
Core.Initialize();
public LibVLC libVLC {get; set; } = new LibVLC();
仅一次,并且仅在卸载时处理 MediaPlayer?
最小测试解决方案
名为 VLCStream 的新 WPF 项目
NuGet 安装:
- VideoLAN.LibVLC.Windows
- LibVLCSharp.WPF
- LibVLCSharp
MainWindow.xaml
<Window x:Class="VLCStream.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:vlc="clr-namespace:LibVLCSharp.WPF;assembly=LibVLCSharp.WPF"
xmlns:local="clr-namespace:VLCStream"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800"
Loaded="Window_Loaded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Content="Play" Click="Button_Click" />
<vlc:VideoView x:Name="VideoView" Grid.Row="1" />
</Grid>
</Window>
MainWindow.xaml.cs
using LibVLCSharp.Shared;
using LibVLCSharp.WPF;
using System;
using System.Linq;
using System.Windows;
namespace VLCStream
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Dispatcher.InvokeAsync(new Action(async () =>
{
using (LibVLC libVLC = new LibVLC("--sout-mux-caching=12000"))
{
using (var media = new Media(libVLC, "https://youtu.be/pW-iVG0_D34", FromType.FromLocation))
{
await media.Parse(MediaParseOptions.ParseNetwork);
MediaPlayer vlcPlayer = new MediaPlayer(media.SubItems.FirstOrDefault());
VideoView.MediaPlayer = vlcPlayer;
VideoView.MediaPlayer.Play();
}
}
}));
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Core.Initialize();
}
}
}
问题似乎是随机的,需要超过 1 运行。
对您的代码的一般反馈。
- 在使用媒体播放器的过程中一直对其进行跟踪,用完后将其丢弃。
- 不要在使用 LibVLC 时丢弃它。
- 将每个媒体播放器与视图集成,现在您只是在没有绘图目标的媒体播放器上调用播放。 LibVLC 将随机创建 windows 以供绘制。可能不是你想要的。
现在,打开日志在 VLC 桌面应用程序中播放您的流将提供一些见解:
main error: ES_OUT_SET_(GROUP_)PCR is called too late (pts_delay increased to 2926 ms)
main debug: Received first picture
main error: Timestamp conversion failed for 9480001: no reference clock
main error: Could not convert timestamp 0 for FFmpeg
main debug: Buffering 0%
main debug: Buffering 8%
main debug: Buffering 17%
main debug: Buffering 25%
main debug: Buffering 34%
main debug: Buffering 42%
main debug: Buffering 51%
main debug: Buffering 59%
main debug: Buffering 68%
main debug: Buffering 76%
main debug: Buffering 85%
main debug: Buffering 93%
main debug: Stream buffering done (3000 ms in 7056 ms)
main debug: Decoder wait done in 0 ms
main debug: inserting 307 zeroes
mmdevice debug: state changed: 1
main warning: buffer too late (-217851 us): dropped
main warning: buffer too late (-194631 us): dropped
main error: ES_OUT_SET_(GROUP_)PCR is called too late (pts_delay increased to 3774 ms)
main debug: ES_OUT_RESET_PCR called
main warning: buffer too late (-171411 us): dropped
main debug: Received first picture
main error: Timestamp conversion failed for 15800001: no reference clock
main error: Could not convert timestamp 0 for FFmpeg
mmdevice debug: state changed: 0
这看起来不太好。也许 YouTube 对视频编码不当?或者更可能是 LibVLC 的问题?我不确定。
问题似乎与 youtube.luac 文件有关。
该文件于 2021 年 10 月 19 日左右更新,似乎运行良好。谢谢 Martin 的帮助。
基本项目可用here。
安装的3个包是:
开始之前先删除项目文件夹中的.vs,以及解决方案中的bin和obj文件夹。
转到 here,复制文本块,然后将其粘贴到记事本中。单击文件 ---> 另存为并为其命名 youtube.luac 在该字段下方,通过下拉菜单将“文本文档”(txt) 更改为所有文件,然后单击保存。
替换 32 和 64 包文件夹中的文件。
例如\packages\VideoLAN.LibVLC.Windows.3.0.16\build\x64\lua\playlist
重建您的项目,瞧。
这为我解决了这个问题,并且由于可用的文档很少,希望这会对某人有所帮助..:)