wpf C# MediaElement --为什么Play()在切换源代码后有时会默默失败?

ia2d9nvy  于 2023-08-07  发布在  C#
关注(0)|答案(2)|浏览(206)

我在一个自定义UserControl中为我一直在制作的视频播放器控件设置了一个MediaElement--播放/暂停按钮、滑块、剩余时间等。我将ScrubbingEnabled设置为True,这样我就可以根据SO post here向用户显示视频的第一帧,并且还使用Slider元素来允许用户清理视频。

问题:我使用绑定来切换视频播放器的源。有时,如果我在播放视频时切换视频 *,MediaElement会停止响应Play()命令。即使在MediaFailed事件中,也不会给出错误。调用Play()(或Pause(),然后Play())每次都失败。我可以在MediaElement出现故障后切换视频源,然后它就会重新开始工作。

XAML:

<MediaElement LoadedBehavior="Manual" ScrubbingEnabled="True" 
              UnloadedBehavior="Stop"
              MediaOpened="VideoPlayer_MediaOpened" x:Name="VideoPlayer"/>

字符串
相关控制代码:

public static DependencyProperty VideoSourceProperty =
            DependencyProperty.Register("VideoSource", typeof(string), typeof(MediaElementVideoPlayer),
                new FrameworkPropertyMetadata(null,
                    FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure,
                    new PropertyChangedCallback(OnSourceChanged)));

private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    MediaElementVideoPlayer player = d as MediaElementVideoPlayer;
    if (player != null)
    {
        player.Dispatcher.Invoke(() => {
            if (player.VideoSource != null && player.VideoSource != "")
            {
                if (player._isPlaying)
                {
                    player.VideoPlayer.Stop();
                    var uriSource = new Uri(@"/ImageResources/vid-play.png", UriKind.Relative);
                    player.PlayPauseImage.Source = new BitmapImage(uriSource);
                    player._isPlaying = false;
                } 
                player.VideoPlayer.Source = new Uri(player.VideoSource);
            }
        });
    }
}

private void VideoPlayer_MediaOpened(object sender, RoutedEventArgs e)
{
    Dispatcher.Invoke(() =>
    {
        VideoPlayer.Pause();
        VideoPlayer.Position = TimeSpan.FromTicks(0);
        Player.IsMuted = false;
        TimeSlider.Minimum = 0;
        // Set the time slider values & time label
        if (VideoPlayer.NaturalDuration != null && VideoPlayer.NaturalDuration != Duration.Automatic)
        {
            TimeSlider.Maximum = VideoPlayer.NaturalDuration.TimeSpan.TotalSeconds;
            TimeSlider.Value = 0;
            double totalSeconds = VideoPlayer.NaturalDuration.TimeSpan.TotalSeconds;
            _durationString = Utilities.numberSecondsToString((int)totalSeconds, true, true);
            TimeLabel.Content = "- / " + _durationString;
        }
    });
}


如果我告诉视频自动播放所有的时间,播放器的工作100%的时间,奇怪的是。不幸的是,我需要视频暂停时,源设置。有人知道如何避免MediaElement的随机,隐藏的故障,同时仍然交换视频,显示加载视频的第一帧,等等?
herehere的问题非常相似,但我的问题有不同的症状,因为我只使用1 MediaElement

ds97pgxw

ds97pgxw1#

奇怪的是,如果将ScrubbingEnabled设置为FalseMediaElement不再随机停止响应。禁用ScrubbingEnabled会破坏第一帧的显示,并使Slider元素不能很好地工作,所以下面是如何在保持这些功能的同时,不会有一个,呃,损坏的MediaElement

显示第一帧:

private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    MediaElementVideoPlayer player = d as MediaElementVideoPlayer;
    if (player != null)
    {
        player.Dispatcher.Invoke(() => {
            if (player.VideoSource != null && player.VideoSource != "")
            {
                if (player._isPlaying)
                {
                    player.VideoPlayer.Stop();
                    var uriSource = new Uri(@"/ImageResources/vid-play.png", UriKind.Relative);
                    player.PlayPauseImage.Source = new BitmapImage(uriSource);
                    player._isPlaying = false;
                } 
                player.VideoPlayer.Source = new Uri(player.VideoSource);
                // Start the video playing so that it will show the first frame. 
                // We're going to pause it immediately so that it doesn't keep playing.
                player.VideoPlayer.IsMuted = true; // so sound won't be heard
                player.VideoPlayer.Play();
            }
        });
    }
}

private void VideoPlayer_MediaOpened(object sender, RoutedEventArgs e)
{
    Dispatcher.Invoke(() =>
    {
        // the video thumbnail is now showing!
        VideoPlayer.Pause();
        // reset video to initial position
        VideoPlayer.Position = TimeSpan.FromTicks(0);
        Player.IsMuted = false; // unmute video
        TimeSlider.Minimum = 0;
        // Set the time slider values & time label
        if (VideoPlayer.NaturalDuration != null && VideoPlayer.NaturalDuration != Duration.Automatic)
        {
            TimeSlider.Maximum = VideoPlayer.NaturalDuration.TimeSpan.TotalSeconds;
            TimeSlider.Value = 0;
            double totalSeconds = VideoPlayer.NaturalDuration.TimeSpan.TotalSeconds;
            _durationString = Utilities.numberSecondsToString((int)totalSeconds, true, true);
            TimeLabel.Content = "- / " + _durationString;
        }
    });
}

字符串

在拖动滑块的同时开启视频的擦洗功能:

// ValueChanged for Slider
private void TimeSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    Dispatcher.Invoke(() => {
        TimeSpan videoPosition = TimeSpan.FromSeconds(TimeSlider.Value);
        VideoPlayer.Position = videoPosition;
        TimeLabel.Content = Utilities.numberSecondsToString((int)VideoPlayer.Position.TotalSeconds, true, true) + " / " + _durationString;
    });
}

// DragStarted event
private void slider_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
{
    Dispatcher.Invoke(() => {
        VideoPlayer.ScrubbingEnabled = true;
        VideoPlayer.Pause();
    });
}

// DragCompleted event
private void slider_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
{
    Dispatcher.Invoke(() => {
        VideoPlayer.ScrubbingEnabled = false;
        TimeSpan videoPosition = TimeSpan.FromSeconds(TimeSlider.Value);
        VideoPlayer.Position = videoPosition;
        if (_isPlaying) // if was playing when drag started, resume playing
            VideoPlayer.Play();
        else
            VideoPlayer.Pause();
    });
}

chhkpiq4

chhkpiq42#

自从引入ScrubbingEnabled属性以来,我还遇到了MediaFailed(MILAVERR_UnexpectedWmpFailure HRESULT:0x8898050C)。由于在Play()期间禁用它而仅在Stop()期间启用它,因此可靠性得到了提高。也就是说,切换文件时必须禁用ScrubbingEnabled。

相关问题