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!


