Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Bug Changing VideoPlayer frame from code doesn't update frame [SOLVED]

Discussion in 'Audio & Video' started by user1dedalord, Sep 6, 2022.

  1. user1dedalord

    user1dedalord

    Joined:
    May 23, 2019
    Posts:
    10
    Hello,

    I think I found an issue with some versions of Unity and the VideoPlayer component.
    I made a script to manually update the VideoPlayer frames so I can change the speed of the video given certain parameters. Example:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Video;
    5.  
    6. public class VideoTest : MonoBehaviour
    7. {
    8.     public VideoPlayer player;
    9.  
    10.     public float speed = 1f;
    11.  
    12.     float percent = 0f;
    13.  
    14.     long frame = 0;
    15.  
    16.     void Start()
    17.     {
    18.         player.playOnAwake = false;
    19.         player.isLooping = false;
    20.         player.renderMode = VideoRenderMode.RenderTexture;
    21.         player.audioOutputMode = VideoAudioOutputMode.None;
    22.  
    23.         player.frame = 1;
    24.         player.Play();
    25.     }
    26.  
    27.     // Update is called once per frame
    28.     void Update()
    29.     {
    30.         percent += Time.deltaTime * speed;
    31.  
    32.         if (percent > 1f)
    33.         {
    34.             frame++;
    35.             percent = 0f;
    36.         }
    37.  
    38.  
    39.         player.frame = frame;
    40.  
    41.         player.Play();
    42.     }
    43. }
    44.  
    This works just fine in Unity 2019.4.16f1, but in newer versions (2019.4.40f1, 2020.3.15f1, 2021.3.9f1) the video does not changes the frame.

    I found this bug report that looks like this very same problem, but it's marked as a duplicate of another bug that seems to be something related to video width and height.

    Is this in fact a Unity bug or were there changes in the way we should work with VidePlayer in newer versions?

    Thanks!
     
  2. The_Island

    The_Island

    Unity Technologies

    Joined:
    Jun 1, 2021
    Posts:
    502
    I think I see the issue. Every time you call player.frame = frame, you are doing a seek operation. This operation is async, meaning it can finish the next frame. If you happen to request a new seek before the last one finish, we abort the last seek and start the new one. So from your point of view, it looks stuck, but in reality, you are cancelling all your seek. We observed some seek performance regression on some platforms, which probably was enough to break your code. This is the workflow I recommend you to use instead.
    Code (CSharp):
    1. void Start()
    2. {
    3.     vp = GetComponent<VideoPlayer>();
    4.     vp.seekCompleted += seekCompleted;
    5. }
    6.  
    7. void seekCompleted(VideoPlayer par)
    8. {
    9.     StartCoroutine(WaitToUpdateRenderTextureBeforeEndingSeek());
    10. }
    11.  
    12. public void UpdateVideoPlayerToFrame(int frame)
    13. {
    14.     //If you are currently seeking there is no point to seek again.
    15.     if (!seekDone)
    16.         return;
    17.  
    18.     // You should pause while you seek for better stability
    19.     vp.Pause();
    20.  
    21.     vp.frame = frame;
    22.     seekDone = false;
    23. }
    24.  
    25. IEnumerator WaitToUpdateRenderTextureBeforeEndingSeek()
    26. {
    27.     yield return new WaitForEndOfFrame();
    28.     seekDone = true;
    29. }
     
    CodeRonnie likes this.
  3. user1dedalord

    user1dedalord

    Joined:
    May 23, 2019
    Posts:
    10
    That was it!.

    Now I need to do slightly different time/speed calculations, but I was able to play the video.

    Thank you @The_Island!
     
  4. The_Island

    The_Island

    Unity Technologies

    Joined:
    Jun 1, 2021
    Posts:
    502
    It will probably be easier if you use VideoPlayer.time.
    You can otherwise test VideoPlayer.playbackSpeed. It is not supported on every platform, but it will give you a smoother playback.
     
    user1dedalord likes this.
  5. Thaina

    Thaina

    Joined:
    Jul 13, 2012
    Posts:
    1,157
    It's feel very weird that this behavior felt hidden. And the state of seeking are not natively exposed as API, instead we need to keep tap of it ourselves