英文:
WPF MediaElement briefly stutters when trying to buffer/preload next video
问题
我正在尝试编写一个程序,可以以流畅的方式播放一系列视频文件,就像它们是一个长视频一样。我在网上找到的关于这个主题的先前问题建议预加载/缓冲下一个视频,然后仅在新视频准备就绪时切换。我已经编写了一个测试程序,就是这样做的。
切换当前播放器/下一个带缓冲的视频的部分运行正常,但当我分配新的MediaElement.Source/打开下一个文件时,播放会出现短暂的卡顿(只有几分之一秒,但非常明显)。
有没有解决这个问题的想法?我是否需要使用Task.Run()拆分线程?(但担心会在UI线程中创建所有权冲突...)。这只是MediaElement的性能限制,是否有解决方法/替代方案?例如,这个https://github.com/unosquare/ffmediaelement是否会更好?
顺便说一下,我甚至尝试在两个不同的窗口中打开,第二个窗口在自己的线程中运行,但当第二个窗口加载其文件时,第一个视频仍然出现卡顿。
谢谢!
我已经编写了下面的简单测试程序。
窗口上有3个叠加的MediaElements,Player1/Player2/Player3。即使隐藏,Player1总是在播放(出于与当前问题无关的其他原因)。其中两个播放器始终处于隐藏状态(不透明度为0),我在一个播放器可见且正在播放的同时将下一个视频预加载到隐藏的播放器中。
如上所述,问题在于可见播放器中的播放在隐藏播放器加载下一个文件时会短暂卡顿。
MainWindow.xaml:
<Window x:Class="Test_App.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:Test_App"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<MediaElement x:Name="Player1" MediaOpened="P1MediaOpened" Stretch="UniformToFill" LoadedBehavior="Manual" UnloadedBehavior="Stop" />
<MediaElement x:Name="Player2" Stretch="UniformToFill" LoadedBehavior="Manual" UnloadedBehavior="Stop" />
<MediaElement x:Name="Player3" Stretch="UniformToFill" LoadedBehavior="Manual" UnloadedBehavior="Stop" />
</Grid>
</Window>
cs文件:
namespace Test_App
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Player2.Opacity = 0.0;
Player3.Opacity = 0.0;
Player2.Volume = 0.0;
Player3.Volume = 0.0;
Player1.Source = new Uri("I:BaseVideo.mp4");
Player1.Play();
Loaded += LoadNextVideos;
}
private async void LoadNextVideos(object sender, RoutedEventArgs e)
{
Player2.Source = new Uri("002.mp4");
await Task.Delay(3000);
Player2.Play();
Player2.Opacity = 1.0;
Player1.Opacity = 0.0;
await Task.Delay(2000);
Player3.Source = new Uri("003.mp4");
await Task.Delay(2000);
Player3.Play();
Player3.Opacity = 1.0;
Player2.Opacity = 0.0;
Player2.Pause();
await Task.Delay(2000);
Player2.Source = new Uri("004.mp4");
await Task.Delay(2000);
Player2.Play();
Player2.Opacity = 1.0;
Player3.Opacity = 0.0;
Player3.Pause();
await Task.Delay(2000);
Player3.Source = new Uri("005.mp4");
await Task.Delay(2000);
Player3.Play();
Player3.Opacity = 1.0;
Player2.Opacity = 0.0;
Player2.Pause();
await Task.Delay(2000);
Player2.Source = new Uri("006.mp4");
await Task.Delay(2000);
}
}
}
英文:
Am trying to write a program that can play a series of video files in a smooth manner as if it were just one long video. Previous questions on the topic I found online recommended preloading/buffering next video and then switching over only once the new video is ready. I've written a test program doing just that.
The switching between current player / next player with the buffered video works fine, but there is a brief stutter in the playback (only a fraction of a second, but very noticeable) when I assign the new MediaElement.Source / open the next file.
Any idea on how to solve this? do I need to split off a thread with Task.Run()? (but am afraid that will create ownership conflicts with the UI thread...). Is this just a performance limitation with MediaElement and are there workarounds / alternatives? would this https://github.com/unosquare/ffmediaelement work better for instance?
the really crazy thing btw. is that i even tried to open 2 different windows, with second window on its own thread, but the first video still stutters when the second window is loading its file.
thanks!
I have written the simple test program below.
Window has 3 superimposed MediaElements, Player1/Player2/Player3. Player1 is always playing even when hidden (i need that for other reasons that are not relevant to current problem). Two of the players are hidden at all times (opacity = 0) and I preload the next video into a hidden player while another one is visible and playing.
As said above, the problem is that the playback in the visible player stutters briefly when the hidden player loads the next file.
MainWindow.xaml:
<Window x:Class="Test_App.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:Test_App"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<MediaElement x:Name="Player1" MediaOpened="P1MediaOpened" Stretch="UniformToFill" LoadedBehavior="Manual" UnloadedBehavior="Stop" />
<MediaElement x:Name="Player2" Stretch="UniformToFill" LoadedBehavior="Manual" UnloadedBehavior="Stop" />
<MediaElement x:Name="Player3" Stretch="UniformToFill" LoadedBehavior="Manual" UnloadedBehavior="Stop" />
</Grid>
</Window>type here
cs file:
namespace Test_App
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Player2.Opacity = 0.0;
Player3.Opacity = 0.0;
Player2.Volume = 0.0;
Player3.Volume = 0.0;
Player1.Source = new Uri("I:BaseVideo.mp4");
Player1.Play();
Loaded += LoadNextVideos;
}
private async void LoadNextVideos(object sender, RoutedEventArgs e)
{
Player2.Source = new Uri("002.mp4");
await Task.Delay(3000);
Player2.Play();
Player2.Opacity = 1.0;
Player1.Opacity = 0.0;
await Task.Delay(2000);
Player3.Source = new Uri("003.mp4");
await Task.Delay(2000);
Player3.Play();
Player3.Opacity = 1.0;
Player2.Opacity = 0.0;
Player2.Pause();
await Task.Delay(2000);
Player2.Source = new Uri("004.mp4");
await Task.Delay(2000);
Player2.Play();
Player2.Opacity = 1.0;
Player3.Opacity = 0.0;
Player3.Pause();
await Task.Delay(2000);
Player3.Source = new Uri("005.mp4");
await Task.Delay(2000);
Player3.Play();
Player3.Opacity = 1.0;
Player2.Opacity = 0.0;
Player2.Pause();
await Task.Delay(2000);
Player2.Source = new Uri("006.mp4");
await Task.Delay(2000);
}
答案1
得分: 0
这可能是因为您试图在彼此之上显示两个MediaElement。请尝试将Visibility设置为Collapsed,然后设置为Visible,而不是Opacity。
英文:
This might be because you're trying to show two MediaElement on top of one another. please try to set the Visibility to Visibility.Collapsed and set to Visibility.Visible instead of Opacity.
答案2
得分: 0
在最后,我放弃了尝试使用WPF MediaElement解决这个问题,转而使用FMME,结果发现它没有卡顿问题。我会关闭这个问题。
英文:
Ok in the end I gave up on trying to solve this with wpf mediaelement and switched to using FMME, which turns out to not have the stuttering issue. I'll close this question.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论