Search This Blog

Thursday, March 29, 2012

Continuously looping video in WPF

At the moment I am building a Kinect based application using the Windows Presentation Foundation framework for a client. More details on this application later.

In that application we needed to show a continuously looping video. After looking through some documentation I used the following XAML construct to play and loop the video continuously:

   1:  <MediaElement LoadedBehavior="Play">
   2:      <MediaElement.Triggers>
   3:          <EventTrigger RoutedEvent="MediaElement.Loaded">
   4:              <EventTrigger.Actions>
   5:                  <BeginStoryboard>
   6:                      <Storyboard>
   7:                          <MediaTimeline Source="Instructions.avi" RepeatBehavior="Forever" Storyboard.TargetName="video" />
   8:                      </Storyboard>
   9:                  </BeginStoryboard>
  10:              </EventTrigger.Actions>
  11:          </EventTrigger>
  12:      </MediaElement.Triggers>
  13:  </MediaElement>

Unfortunately this solution is not reliable. After some time it can took a while before the video starts playing again after it has ended. Sometimes the video stops playing completely. Some searching revealed that the MediaElement indeed is not reliable enough. Some alternatives where suggested, for example http://wpfmediakit.codeplex.com/.

The mediakit can indeed be a solution but there is a simpler way without adding a dependency on a third party framework. Instead of using a StoryBoard and a MediaTimeLine you can also manage the repetition yourself. The following code demonstrates this.

   1:  <MediaElement x:Name="instructionVideo" Width="320" Height="240" Source="Videos/Instructions.mp4" LoadedBehavior="Manual" Loaded="instructionVideo_Loaded" MediaEnded="instructionVideo_MediaEnded" VerticalAlignment="Bottom" HorizontalAlignment="Center" Canvas.Top="40"/>

The above XAML fragment is accompanied by the following code-behind:

   1:   private void instructionVideo_Loaded(object sender, RoutedEventArgs e)
   2:   {
   3:       instructionVideo.Play();
   4:   }
   5:   
   6:   private void instructionVideo_MediaEnded(object sender, RoutedEventArgs e)
   7:   {
   8:       instructionVideo.Position = TimeSpan.FromSeconds(0);
   9:   }

Instead of letting WPF manage the video, we specify a LoadedBehavior of Manual which means we can manage the starting and stopping of the video ourselves. To actually start the video the Loaded event handler is used which calls the Play method on the instructionVideo element. When the video reaches the end, the MediaEnded event is dispatched. In this event the Position is set back to 0 so the video starts playing from the beginning again. This proved to be a reliable way of continuously looping videos.

PS. the video in questions is in mp4 format and about 20 seconds in length which must loop all day long.