5

I want to smoothly play video in backwards direction in WPF. I am using MediaElement to play the video. I read this post which suggests changing MediaElement.Position periodically to mimic the rewinding behaviour.

I tried following code for changing position of MediaElement.Position

private void Button_Click(object sender, RoutedEventArgs e)
{
    mePlayer.Pause();                               //Pause the media player first
    double m = 1 / frameRate;                       //Calculate the time for each frame
    double t = 120;                                 //Total length of video in seconds
    mePlayer.Position = TimeSpan.FromMinutes(2);    //Start video from 2 min
    while (t >= 60)                                 //Check if time exceeds 1 min
    {
        t = t - m;                                  //Subtract the single frame time from total seconds
        mePlayer.Position = TimeSpan.FromSeconds(t);//set position of video
    }
}

In above code I am trying to play video backwards from 2 min to 1 min. It's giving me 'System.OverflowException' on mePlayer.Position = TimeSpan.FromSeconds(t).

If anyone know how play video backwards in WPF, please help me to achieve this effect. Thank you.

Community
  • 1
  • 1
Bhavesh Jadav
  • 695
  • 1
  • 13
  • 33

1 Answers1

2

To do it smoothly you should use a Timer. Assuming the frame rate is 24 fps, then it means that is one frame every 1/24 = 0.0416 second or approximately 42 millisecond. So if your timer ticks every 42ms you can move mePlayer.Position backward:

XAML:

<MediaElement x:Name="mePlayer" Source="C:\Sample.mp4"
              LoadedBehavior="Manual" ScrubbingEnabled="True"/>

Code:

    System.Windows.Threading.DispatcherTimer dispatcherTimer;
    int t = 240000; // 4 minutes = 240,000 milliseconds

    public MainWindow()
    {
        InitializeComponent();

        dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
        dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
        //tick every 42 millisecond = tick 24 times in one second
        dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 42);

    }

    private void dispatcherTimer_Tick(object sender, EventArgs e)
    {
        // Go back 1 frame every 42 milliseconds (or 24 fps)
        t = t - 42;
        mePlayer.Position = TimeSpan.FromMilliseconds(t);
    }
    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        mePlayer.Play();
    }
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        // Pause and go to 4th minute of the video then start playing backward
        mePlayer.Pause();                               
        mePlayer.Position = TimeSpan.FromMinutes(4);
        dispatcherTimer.Start();
    }
PaulF
  • 6,673
  • 2
  • 18
  • 29
Bahman_Aries
  • 4,658
  • 6
  • 36
  • 60
  • I already tried what you said. It only works smoothly for low quality video. It might work smoothly for high quality video if system specs are high. – Bhavesh Jadav Jun 22 '15 at 07:34
  • If you can re-encode your videos it may be worth using FFmpeg or similar to play around with key frame settings for this solution. It'll increase your file size, but more key frames *might* provide smoother playback. See: http://stackoverflow.com/questions/14117757/how-to-control-key-frame-generation-of-ffmpeg . – goobering Jun 22 '15 at 14:12