I have a MediaElement
set up in a custom UserControl for a video player control that I've been making -- play/pause button, slider, time remaining, etc. I have ScrubbingEnabled
set to True
so that I can show the first frame of the video to the user per the SO post here, and also use a Slider
element to allow the user to scrub the video.
Problem: I use a binding to switch the video player's source. On occasion, if I switch videos while a video is playing, the MediaElement
stops responding to Play()
commands. No errors are given, even in the MediaFailed
event. Calling Play()
(or Pause()
then Play()
) fails every time. I can switch the video source after the MediaElement
fails, and then it will start working again.
XAML:
<MediaElement LoadedBehavior="Manual" ScrubbingEnabled="True"
UnloadedBehavior="Stop"
MediaOpened="VideoPlayer_MediaOpened" x:Name="VideoPlayer"/>
Pertinent control code:
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;
}
});
}
If I tell videos to auto-play all the time, the player works 100% of the time, strangely enough. Unfortunately, I need videos to be paused when the source is set. Does anyone know how to avoid the MediaElement
's random, hidden failure while still swapping videos, showing the first frame of the loaded video, etc.?
There are eerily similar questions here and here, but my problem has different symptoms since I am only using 1 MediaElement
.