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!