Search Unity

Question Internal VideoPlayer Changes in 2021?

Discussion in 'Audio & Video' started by jarmick, May 18, 2021.

  1. jarmick

    jarmick

    Joined:
    Dec 3, 2015
    Posts:
    12
    My situation:

    When the player drags their mouse or finger over the screen, a video clip 'scrubs' through.

    The functionality works in version 2020.1.3 but not in 2021.1.6

    In 2020.1.3, the video frames update every frame / real-time

    In 2021.1.6, the video frames update after the mouse button is up

    I couldn't find any referenced changes to the Video API...

    Code for scrubbing mechanic:

    Code (CSharp):
    1.  using UnityEngine;
    2. using UnityEngine.Video;
    3. public class MouseRotate : MonoBehaviour
    4. {
    5.      public float XSensitivity = 2f;
    6.      public float startTime = 0.5f;
    7.      VideoPlayer video;
    8.      float xRot;
    9.      [HideInInspector]
    10.      public float rotationTime = 0.0f;
    11.      ulong videoDur;
    12.      public bool isActive;
    13.      private void Awake()
    14.      {
    15.          video = GetComponent<VideoPlayer>();
    16.          video.Play();
    17.          video.Pause();
    18.          videoDur = Duration;
    19.          xRot = 360 * startTime;
    20.          rotationTime = startTime;
    21.          Seek(startTime);
    22.      }
    23.      private void Update()
    24.      {
    25.          if (Input.GetMouseButton(0))
    26.          {
    27.              if(isActive)
    28.                  if (Input.mousePosition.x >= 0 && Input.mousePosition.x <= Screen.width)
    29.                  DragSeekFunction();
    30.          }
    31.      }
    32.      public ulong Duration
    33.      {
    34.          get { return (ulong)(video.frameCount / video.frameRate); }
    35.      }
    36.      public void Seek(float nTime)
    37.      {
    38.          nTime = Mathf.Clamp(nTime, 0, 1);
    39.          video.time = nTime * videoDur;
    40.      }
    41.      public void DragSeekFunction()
    42.      {
    43.          xRot += Input.GetAxis("Mouse X") * XSensitivity;
    44.          xRot = Mathf.Clamp(xRot, 0.1f, 359.9f);
    45.          transform.eulerAngles = new Vector3(transform.eulerAngles.x, xRot, transform.eulerAngles.z);
    46.          rotationTime = transform.rotation.eulerAngles.y / 360;
    47.          Seek(rotationTime);
    48.      }
    49. }
     
  2. travelsound84

    travelsound84

    Joined:
    Jan 15, 2014
    Posts:
    34
    I have a similar issue, since using unity 2020.
    When I was using unity 2018 the frame calculation was much much faster.
    Did you ever find a solution for it?
     
  3. The_Island

    The_Island

    Unity Technologies

    Joined:
    Jun 1, 2021
    Posts:
    502
    Weird. It should behave the same way as 2020.1. Can you update your editor to the latest 2021 version? There is a chance we fixed it. Otherwise, I would recommend opening a bug report.
     
  4. jarmick

    jarmick

    Joined:
    Dec 3, 2015
    Posts:
    12
    I never found a solution so I am keeping my project in 2020.3. But I see below it could have been resolved in more recent versions. I will try this.
     
  5. jarmick

    jarmick

    Joined:
    Dec 3, 2015
    Posts:
    12
    Thanks, will try again with a more recent version and submit a report if issue still exists. Appreciate the reply.
     
  6. stevenwanhk

    stevenwanhk

    Joined:
    Jul 20, 2016
    Posts:
    113
    I am having the same issue with 2021.3.8f1
    Changing video.time does not work
     
  7. travelsound84

    travelsound84

    Joined:
    Jan 15, 2014
    Posts:
    34
  8. jarmick

    jarmick

    Joined:
    Dec 3, 2015
    Posts:
    12
    The videos demonstrate the exact same issue I am reporting here. A lag in the frame updating on a scrub. Something changed from 2020 to the recent versions, maybe the way Unity is implementing playback or frame-reading internally?
     
  9. The_Island

    The_Island

    Unity Technologies

    Joined:
    Jun 1, 2021
    Posts:
    502
    Hi! Sorry for the wait. I had to investigate because it is now the third post on a similar bug. I found out that we did fix a similar issue recently, but the patch has not landed on all versions. So the next thing I would recommend is upgrading your project to the latest 2022 versions. We are not suggesting that you start using 2022 in production, but this will let you know in advance if the fix we are talking about is indeed solving the issue. If it is indeed that, we will try to accelerate the process. For more details, I would recommend checking the full answer from my colleague. https://forum.unity.com/threads/vid...-2020-1-16-to-2020-3-25.1226742/#post-7828875
     
  10. jarmick

    jarmick

    Joined:
    Dec 3, 2015
    Posts:
    12
    Thanks for this reply and the link to the other thread. The issue persists in 2022. The issue does not appear in 2020.3
     
  11. The_Island

    The_Island

    Unity Technologies

    Joined:
    Jun 1, 2021
    Posts:
    502
    I see. What puzzle me, is that you said it works in version 2020.1.3 but not in 2021.1.6. So it seems to be a regression. If possible I would like to investigate that, so could you open a bug report? We will try to look at what caused the regression.

    While I don't know why there is a regression, I think I know a way to fix your issue. I made a script showing how to implement smooth scrubbing features. It should improve or fix your issue.
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using UnityEngine.Video;
    4.  
    5. public class ScrubbingController : MonoBehaviour
    6. {
    7.     public VideoPlayer player;
    8.  
    9.     private bool isSeeking;
    10.     private Slider slider;
    11.  
    12.     void Awake()
    13.     {
    14.         slider = GetComponent<Slider>();
    15.     }
    16.  
    17.     private void Player_seekCompleted(VideoPlayer source)
    18.     {
    19.         isSeeking = false;
    20.     }
    21.  
    22.     void Start()
    23.     {
    24.         slider.maxValue = (float)player.length;
    25.     }
    26.  
    27.     public void BeginScrub()
    28.     {
    29.         //It is recommended to pause the player when seeking as otherwise,
    30.         //you will continuously fight the VideoPlayer from playing and buffering frames.
    31.         player.Pause();
    32.  
    33.         //To know when the player has finished seeking      
    34.         player.seekCompleted += Player_seekCompleted;
    35.         isSeeking = false;
    36.     }
    37.  
    38.     public void UpdateScrub()
    39.     {
    40.         //If you are currently seeking there is no point to seek again.
    41.         if (isSeeking)
    42.             return;
    43.  
    44.         //Don't seek, if the time between the slider value and the current player time is too small.
    45.         //We will seek to the closest frame so if the delta is 0.00001f you will most likely seek the same frame.
    46.         //Change the value to fit your use case.
    47.         if(Mathf.Abs((float)player.time - slider.value) < 0.01f)
    48.             return;
    49.  
    50.         player.time = slider.value;
    51.         isSeeking = true;
    52.     }
    53.  
    54.     public void EndScrub()
    55.     {
    56.         //You don't want random event when you are not using this script
    57.         player.seekCompleted -= Player_seekCompleted;
    58.         player.Play();
    59.     }
    60. }
    61.  
    If the comment is not enough, don't hesitate to reach out. I tested it on 2021.1.28f1 and it is smooth on my side
     
  12. stevenwanhk

    stevenwanhk

    Joined:
    Jul 20, 2016
    Posts:
    113
    Weird, did player.time do anything on your side?
    I tested with a simple script
    Code (CSharp):
    1. videoPlayer.Stop();
    2. videoPlayer.Play();
    3. videoPlayer.time = 3f;
    The video simply plays from 0s instead of 3s, and videoPlayer.time is still 0 after set it to 3
    I am using 2021.2.8f1, and the code was working on 2020.3.11f1
     
  13. The_Island

    The_Island

    Unity Technologies

    Joined:
    Jun 1, 2021
    Posts:
    502
    Just tested your code on 2021.2.8f1 and it jumps correctly. At that point, I would recommend opening a bug report. It will be easier to investigate what is happening.
     
    stevenwanhk likes this.
  14. stevenwanhk

    stevenwanhk

    Joined:
    Jul 20, 2016
    Posts:
    113
    Code (CSharp):
    1.     void Update()
    2.     {
    3.         if (_isFrameToSync)
    4.         {
    5.             videoPlayer.time = _timeToSync;
    6.             Debug.Log("Set time to "+ _timeToSync);
    7.             _isFrameToSync = false;
    8.         }
    9.    
    10.         Debug.Log("videoPlayer.time = " + videoPlayer.time);
    11.     }
    It's completely random, sometimes it works, sometimes it does not (in editor)
    It immediately jumps back to 0 and jumps to time set after a few frames when it works
    It simply jumps back to 0 and continue to play if it fails to set the time
     

    Attached Files:

    • 1.jpg
      1.jpg
      File size:
      75.6 KB
      Views:
      272
    • 2.jpg
      2.jpg
      File size:
      68.8 KB
      Views:
      263
    Last edited: Feb 8, 2022
  15. The_Island

    The_Island

    Unity Technologies

    Joined:
    Jun 1, 2021
    Posts:
    502
    Sorry for the long delay. We had the "jumps back to 0" issue in the past and it should be fixed. Are you on the latest version of 2021? If not, I would recommend updating to the latest.
     
  16. stevenwanhk

    stevenwanhk

    Joined:
    Jul 20, 2016
    Posts:
    113
    Tested 2021.3.2f1, still not work
     
  17. jgmakes

    jgmakes

    Joined:
    Jan 10, 2019
    Posts:
    75
    After upgrading to 2021.3 LTS, I can no longer set the _videoPlayer.time value. It always jumps to 0. The same code always worked in my 2019 LTS project.

    I hit the my custom player's pause button. The time value reports correctly.

    But upon playing I try to set it to any value it goes to 0.

    In my scenario I am storing the time at the pause event because I'd like to restart 0.5 seconds before the pause happened. Complicated to explain why, but it's the best UX in my scenario :)

    Again, this code has always worked. All I did was upgrade.

    @The_Island – any progress here in 2021 LTS?
     
  18. The_Island

    The_Island

    Unity Technologies

    Joined:
    Jun 1, 2021
    Posts:
    502
    Hi @jgmakes @stevenwanhk! I could not reproduce it on my computer for some reason, but after speaking with my colleague, I learned it was similar to a known issue. Sorry for the confusion. You can follow the case and the full details with the links below. Unfortunately, it has not been backported to 2021 yet, but it is in the process. I would try 2022.1 to make sure this fix does resolve your issue. Otherwise, we can discuss it further.

    https://issuetracker.unity3d.com/is...-dot-width-and-height-returns-expected-values
    https://forum.unity.com/threads/vid...-2020-1-16-to-2020-3-25.1226742/#post-7828875
     
  19. artfail

    artfail

    Joined:
    Apr 18, 2017
    Posts:
    34
    I am hitting a similar issue in Unity 2022.3.1

    Code (CSharp):
    1. Service.videoPlayer.time = currentPlayTime;
    2. Service.videoPlayer.Prepare();
    3. yield return new WaitUntil(() => Service.videoPlayer.isPrepared);
    4. Service.videoPlayer.Play();
    Sometimes this works and sometimes I get an error:
    Error details: NSError code: -11821
    domain: AVFoundationErrorDomain
    desc: Cannot Decode
    reason: The media data could not be decoded. It may be damaged.


    If I reverse the order
    Code (CSharp):
    1. Service.videoPlayer.Play();
    2. yield return new WaitUntil(() => Service.videoPlayer.frame > 50);
    3. Service.videoPlayer.time = currentPlayTime;
    Then i get the error when I try to set the time. I have not figured out how to reliably set time.
     
  20. jarmick

    jarmick

    Joined:
    Dec 3, 2015
    Posts:
    12
    @artfail this seems like a codec issue and not necessarily an issue in Unity video playback. try re-rendering a native .mp4 video file (or any friendly codec) out of software and ensuring it's at a reasonable data-rate/framerate/resolution. Apologies if you've already re-rendered a million times ;)
     
  21. artfail

    artfail

    Joined:
    Apr 18, 2017
    Posts:
    34
    It is "solved" or I have a work around at least. All my videos were a very standard hevc H265 mp4. I changed my video to H264 mp4. The whole project is larger now but it will still work. I guess the real bug is that Unity does not seem to fully support H265 yet which chafes me a little bit because it is promoted as a great way to do 360 video but if you are working at a reasonable resolution your world is nothing but pain. I don't even really want to be working in H265 what I really need is AV1 codec support.
     
  22. jarmick

    jarmick

    Joined:
    Dec 3, 2015
    Posts:
    12
    ...yes the endless compromise and dial-turning of the video codec game is exhausting. Also, you may already know but you can encode H265 videos in-engine through Unity's import settings. It may be worth rendering a high-quality / low-compression .mov or .avi file, then transcoding an H265 in Unity to test. Glad you have something working.
     
  23. The_Island

    The_Island

    Unity Technologies

    Joined:
    Jun 1, 2021
    Posts:
    502
    Hi. You can check our H265 support on this page. To support H265, we need to get one from the platform. All Apple and Android platforms come with it but Windows is a little bit special. They didn't want to provide one by default. So you and your users have to install a 1$ extension pack which is often a deal breaker for most. In the future, we want to support codecs from GPU (AMD and NVIDIA) which then would fix this issue on Windows and also support other codecs like AV1.
     
  24. artfail

    artfail

    Joined:
    Apr 18, 2017
    Posts:
    34
    Yes. They were standard h265 hevc mp4s which is what made this bug so hard to figure out. I was testing on mac, and windows. They play fine. They stop fine. Pause and unpause all works. Just setting time only works once and gives the error I posted the second time around that crashes the game.

    On a related note setting time before playing fails regardless of codec. But it doesn't give an error that crashes, it just gets ignored. That is another bug, I reported it, it was confirmed and it is in review now.
     
    The_Island likes this.