{"id":5861,"date":"2025-02-25T19:21:15","date_gmt":"2025-02-25T10:21:15","guid":{"rendered":"https:\/\/blog.criware.com\/?p=5861"},"modified":"2025-08-06T17:33:10","modified_gmt":"2025-08-06T08:33:10","slug":"video-player-with-seek-bar","status":"publish","type":"post","link":"https:\/\/blog.criware.com\/index.php\/2025\/02\/25\/video-player-with-seek-bar\/","title":{"rendered":"Video player with seek bar"},"content":{"rendered":"<p>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.\u00a0 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.<\/p>\n<p>\nUnfortunately, 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.<\/p>\n<div class=\"2col\" style=\"display:flex; border: 4px solid #8ba9d9; padding: 20px; border-radius: 10px; margin-bottom:30px;\">\n<div class=\"left\" style=\"width: 350px;\">\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.criware.com\/wp-content\/uploads\/2025\/02\/\u753b\u50cf1.png\" alt=\"\" width=\"331\" height=\"274\" class=\"alignnone size-full wp-image-5863\" srcset=\"https:\/\/blog.criware.com\/wp-content\/uploads\/2025\/02\/\u753b\u50cf1.png 331w, https:\/\/blog.criware.com\/wp-content\/uploads\/2025\/02\/\u753b\u50cf1-300x248.png 300w\" sizes=\"auto, (max-width: 331px) 100vw, 331px\" \/>\n<\/div>\n<div class=\"right\" style=\"flex: 1;\">\n<p>\nWhen 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:<\/p>\n<ul>\n<li style=\"font-size: 14px;\">Precise frame-by-frame control (<strong>frameNo<\/strong>)<\/li>\n<li style=\"font-size: 14px;\">Stop control when seeking (<strong>StopForSeek())<\/strong><\/li>\n<li style=\"font-size: 14px;\">Dedicated enumeration for state management (<strong>Player.Status<\/strong>)<\/li>\n<li style=\"font-size: 14px;\">Memory and game performance optimizations<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<p>In this post, we showcase a simple video player with a seek bar. It can be found in the official SDK:<br \/>\n<strong>\\SDK\\unity\\samples\\UnityProject\\Assets\\CriAssetSamples\\Scenes\\crimana\\basic\\Scene_05_Seek.unity<\/strong><\/p>\n<div style=\"max-width: 700px; margin: 0 auto; margin-bottom: 30px;\">\n<div style=\"width: 800px;\" class=\"wp-video\"><video class=\"wp-video-shortcode\" id=\"video-5861-1\" width=\"800\" height=\"450\" preload=\"metadata\" controls=\"controls\"><source type=\"video\/mp4\" src=\"https:\/\/blog.criware.com\/wp-content\/uploads\/2025\/02\/Sofdec_Timeline.mp4?_=1\" \/><a href=\"https:\/\/blog.criware.com\/wp-content\/uploads\/2025\/02\/Sofdec_Timeline.mp4\">https:\/\/blog.criware.com\/wp-content\/uploads\/2025\/02\/Sofdec_Timeline.mp4<\/a><\/video><\/div>\n<\/div>\n<p>Below is a part of the <strong>MovieSeekBar.cs<\/strong> script used in the game scene and that relates to the video playback function.<\/p>\n<pre style=\"width: 94%; margin-bottom: 0px; padding-bottom: 40px;\"><code class=\"hljs php\">\r\nprivate void OnGUI() {\r\n  if (movie==null) {\r\n    return;\r\n  }\r\n\r\n  Scene_00_GUI.BeginGui(\"01\/SampleMain_Seek\");\r\n\r\n  \/* Set UI skin. *\/\r\n  GUI.skin=Scene_00_SampleList.uiSkin;\r\n\r\n  if (<b style=\"background-color: #bfe0ef;\"> movie.player.status<\/b>==Player.Status.Playing || <b style=\"background-color: #bfe0ef;\"> movie.player.status<\/b>==Player.Status.PlayEnd) {\r\n    totalFrameCnt=<b style=\"background-color: #bfe0ef;\">movie.player.movieInfo.totalFrames<\/b>;\r\n\r\n    seekFrameNo=(int)Mathf.Clamp(Scene_00_GUI.HorizontalSlider(seekBarRect, seekFrameNo, 0, totalFrameCnt - 1), 0, totalFrameCnt - 1);\r\n    GUI.enabled=false;\r\n\r\n      {\r\n      Scene_00_GUI.HorizontalSlider(playbackBarRect,\r\n        (movie.player.frameInfo !=null) ? <b style=\"background-color: #bfe0ef;\"> movie.player.frameInfo.frameNo<\/b> % totalFrameCnt : 0,\r\n        0, totalFrameCnt - 1);\r\n    }\r\n\r\n    GUI.enabled=true;\r\n    var oldFrameNo=seekFrameNo;\r\n    seekFrameNo=(int)Scene_00_GUI.HorizontalSliderButton(seekButtonRect, seekFrameNo, 0, totalFrameCnt - 1, totalFrameCnt \/ 20);\r\n\r\n    if (GUI.changed || seekFrameNo !=oldFrameNo) {\r\n      \/* Stop the playback. (Seeking is not available during playback.)  *\/\r\n      movie.player.<b style=\"background-color: #bfe0ef;\">StopForSeek()<\/b>;\r\n      isSeeking=true;\r\n    }\r\n  }\r\n\r\n  else {\r\n    GUI.enabled=false;\r\n    Scene_00_GUI.HorizontalSlider(playbackBarRect, 0, 0, totalFrameCnt - 1);\r\n    GUI.enabled=true;\r\n    Scene_00_GUI.HorizontalSlider(seekBarRect, seekFrameNo, 0, totalFrameCnt - 1);\r\n    Scene_00_GUI.HorizontalSliderButton(seekButtonRect, seekFrameNo, 0, totalFrameCnt - 1, totalFrameCnt \/ 20);\r\n  }\r\n\r\n  Scene_00_GUI.EndGui();\r\n}\r\n\r\nprivate void Update() {\r\n  if (movie==null) {\r\n    return;\r\n  }\r\n\r\n  if (isSeeking && movie.player.status==Player.Status.Stop) {\r\n    \/* Seek the movie and start the playback.  *\/\r\n    <b style=\"background-color: #bfe0ef;\">movie.player. SetSeekPosition(seekFrameNo)<\/b>;\r\n    <b style=\"background-color: #bfe0ef;\">movie.player.Start<\/b>();\r\n    isSeeking=false;\r\n  }\r\n}\r\n<\/code><\/pre>\n<p>The CriMana API in the sample code is straightforward to use, allowing you to control videos with simple commands\/properties. Let\u2019s describe the different elements used.<\/p>\n<ul>\n<li style=\"font-size: 14px;\"><strong>movie.player.status<\/strong>: property indicating the playback status<\/li>\n<li style=\"font-size: 14px;\"><strong>movie.player.movieInfo.totalFrames<\/strong>: total number of frames in the video<\/li>\n<li style=\"font-size: 14px;\"><strong>movie.player.frameInfo.frameNo<\/strong>: current frame number<\/li>\n<li style=\"font-size: 14px;\"><strong>movie.player.StopForSeek()<\/strong>: function to stop the seek playback<\/li>\n<li style=\"font-size: 14px;\"><strong>movie.player.SetSeekPosition(int frameNo)<\/strong>: function to set the seek position<\/li>\n<li style=\"font-size: 14px;\"><strong>movie.player.Start()<\/strong>: function to start the video playback<\/li>\n<li style=\"font-size: 14px;\"><strong>Player.Status<\/strong>: enumeration of the various playback statuses<\/li>\n<\/ul>\n<p>In addition to its many other features, Sofdec offers advanced control on the video playback, making it possible to even build gameplay around it!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In a game, having a video player with a seek bar can be very useful, for instance to review game<\/p>\n","protected":false},"author":2,"featured_media":5881,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"colormag_page_container_layout":"default_layout","colormag_page_sidebar_layout":"default_layout","footnotes":""},"categories":[6,7,23],"tags":[],"class_list":["post-5861","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-sofdec","category-tutorials","category-unity"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/blog.criware.com\/index.php\/wp-json\/wp\/v2\/posts\/5861","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.criware.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.criware.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.criware.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.criware.com\/index.php\/wp-json\/wp\/v2\/comments?post=5861"}],"version-history":[{"count":19,"href":"https:\/\/blog.criware.com\/index.php\/wp-json\/wp\/v2\/posts\/5861\/revisions"}],"predecessor-version":[{"id":5883,"href":"https:\/\/blog.criware.com\/index.php\/wp-json\/wp\/v2\/posts\/5861\/revisions\/5883"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.criware.com\/index.php\/wp-json\/wp\/v2\/media\/5881"}],"wp:attachment":[{"href":"https:\/\/blog.criware.com\/index.php\/wp-json\/wp\/v2\/media?parent=5861"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.criware.com\/index.php\/wp-json\/wp\/v2\/categories?post=5861"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.criware.com\/index.php\/wp-json\/wp\/v2\/tags?post=5861"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}