SofdecTutorials

Video player with seek bar

In a game, having a video player with a seek bar can be very useful, for instance to review game events after completing a level. The seek bar itself can be an integral part of the gameplay.  For instance, in a mystery game, it could offer a way to examine videos for clues to solve mysteries. Similarly, in a horror game, the player could investigate security camera footage.

Unfortunately, the standard VideoPlayer of Unity, although it provides general-purpose playback features, does not support the most efficient compression formats available or frame-by-frame control.

When advanced video manipulation is required, CRI Sofdec is an ideal solution. Its Unity-optimized video playback library, CriMana, offers advanced playback controls and optimizations for game development, such as:

  • Precise frame-by-frame control (frameNo)
  • Stop control when seeking (StopForSeek())
  • Dedicated enumeration for state management (Player.Status)
  • Memory and game performance optimizations

In this post, we showcase a simple video player with a seek bar. It can be found in the official SDK:
\SDK\unity\samples\UnityProject\Assets\CriAssetSamples\Scenes\crimana\basic\Scene_05_Seek.unity

Below is a part of the MovieSeekBar.cs script used in the game scene and that relates to the video playback function.


private void OnGUI() {
  if (movie==null) {
    return;
  }

  Scene_00_GUI.BeginGui("01/SampleMain_Seek");

  /* Set UI skin. */
  GUI.skin=Scene_00_SampleList.uiSkin;

  if ( movie.player.status==Player.Status.Playing ||  movie.player.status==Player.Status.PlayEnd) {
    totalFrameCnt=movie.player.movieInfo.totalFrames;

    seekFrameNo=(int)Mathf.Clamp(Scene_00_GUI.HorizontalSlider(seekBarRect, seekFrameNo, 0, totalFrameCnt - 1), 0, totalFrameCnt - 1);
    GUI.enabled=false;

      {
      Scene_00_GUI.HorizontalSlider(playbackBarRect,
        (movie.player.frameInfo !=null) ?  movie.player.frameInfo.frameNo % totalFrameCnt : 0,
        0, totalFrameCnt - 1);
    }

    GUI.enabled=true;
    var oldFrameNo=seekFrameNo;
    seekFrameNo=(int)Scene_00_GUI.HorizontalSliderButton(seekButtonRect, seekFrameNo, 0, totalFrameCnt - 1, totalFrameCnt / 20);

    if (GUI.changed || seekFrameNo !=oldFrameNo) {
      /* Stop the playback. (Seeking is not available during playback.)  */
      movie.player.StopForSeek();
      isSeeking=true;
    }
  }

  else {
    GUI.enabled=false;
    Scene_00_GUI.HorizontalSlider(playbackBarRect, 0, 0, totalFrameCnt - 1);
    GUI.enabled=true;
    Scene_00_GUI.HorizontalSlider(seekBarRect, seekFrameNo, 0, totalFrameCnt - 1);
    Scene_00_GUI.HorizontalSliderButton(seekButtonRect, seekFrameNo, 0, totalFrameCnt - 1, totalFrameCnt / 20);
  }

  Scene_00_GUI.EndGui();
}

private void Update() {
  if (movie==null) {
    return;
  }

  if (isSeeking && movie.player.status==Player.Status.Stop) {
    /* Seek the movie and start the playback.  */
    movie.player. SetSeekPosition(seekFrameNo);
    movie.player.Start();
    isSeeking=false;
  }
}

The CriMana API in the sample code is straightforward to use, allowing you to control videos with simple commands/properties. Let’s describe the different elements used.

  • movie.player.status: property indicating the playback status
  • movie.player.movieInfo.totalFrames: total number of frames in the video
  • movie.player.frameInfo.frameNo: current frame number
  • movie.player.StopForSeek(): function to stop the seek playback
  • movie.player.SetSeekPosition(int frameNo): function to set the seek position
  • movie.player.Start(): function to start the video playback
  • Player.Status: enumeration of the various playback statuses

In addition to its many other features, Sofdec offers advanced control on the video playback, making it possible to even build gameplay around it!