Search Unity

Video [SOLVED] Playing a new video the last frame of the previous video is still visible for a few seconds

Discussion in 'Audio & Video' started by Aewyn, Feb 22, 2019.

  1. Aewyn

    Aewyn

    Joined:
    Mar 28, 2018
    Posts:
    3
    Hey all,

    As the title suggests I have an application that can play multiple files. When I change to a new video file the last frame from the previous video shows instead before playing the new video file. I do all of this with a single Video Player component and in one Unity Scene, if possible I'd like to keep it that way too.

    I don't know how important the fact that I am making this for Oculus Go is, but figured I'd share it.

    I've tried using:
    • VideoPlayer.isPrepared
    • turning the VideoPlayer.clip = null; (and initializing it again)
    • VideoPlayer.targetTexture = null; (and initializing it again)
    • Using coroutines that yield return WaitForSeconds
    I might not have gone around this the correct way. I'd appreciate hearing other people's approaches to this issue.

    Here's the significant part of my code;

    Code (CSharp):
    1.     public VideoPlayer m_VidPlayer;
    2.     public Material m_DefaultSkybox;
    3.     public Material m_VideoSkybox;
    4.  
    5.     public VideoClip[] m_VideoClips;
    6.     public GameObject[] m_GameObjects;
    7.  
    8.     private void Awake()
    9.     {
    10.         m_VidPlayer.loopPointReached += ResetScene;
    11.         OVRManager.HMDUnmounted += PlayerLost;
    12.     }
    13.  
    14.     public void ResetScene(VideoPlayer source)
    15.     {
    16.         source.Stop();
    17.         RenderSettings.skybox = m_DefaultSkybox;
    18.         foreach (GameObject go in m_GameObjects)
    19.         {
    20.             go.SetActive(true);
    21.         }
    22.     }
    23.    
    24.     private void VideoStarted(VideoPlayer source)
    25.     {
    26.         RenderSettings.skybox = m_VideoSkybox;
    27.         foreach (GameObject go in m_GameObjects)
    28.         {
    29.             go.SetActive(false);
    30.         }
    31.     }
    32.  
    33.     public void ChangeToVideoOne()
    34.     {
    35.         VideoStarted(m_VidPlayer);
    36.         m_VidPlayer.clip = m_VideoClips[0];
    37.         m_VidPlayer.Play();
    38.     }
    39.  
    40.     public void ChangeToVideoTwo()
    41.     {
    42.         m_VidPlayer.clip = m_VideoClips[1];
    43.         VideoStarted(m_VidPlayer);
    44.         m_VidPlayer.Play();
    45.     }
     
    dcfreeman likes this.
  2. Aewyn

    Aewyn

    Joined:
    Mar 28, 2018
    Posts:
    3
    I figured it out on my own. I now make a RenderTexture in a new function which I destroy again after a video is done playing. The code looks like this;

    Code (CSharp):
    1.    private RenderTexture CreateRenderTexture()
    2.     {
    3.         RenderTexture m_RenderTexture;
    4.         m_RenderTexture = new RenderTexture(4000, 2880, 16, RenderTextureFormat.ARGB32);
    5.         m_RenderTexture.Create();
    6.         return m_RenderTexture;
    7.     }
    8.  
    9.     public void ResetScene(VideoPlayer source)
    10.     {
    11.         Destroy(source.targetTexture);
    12.         RenderSettings.skybox = m_DefaultSkyboxMaterial;
    13.         foreach (GameObject go in m_GameObjects)
    14.         {
    15.             go.SetActive(true);
    16.         }
    17.     }
    18.  
    19.     private void VideoStarted(VideoPlayer source)
    20.     {
    21.         source.targetTexture = CreateRenderTexture();
    22.         source.aspectRatio = VideoAspectRatio.NoScaling;
    23.         m_VideoSkyboxMaterial.mainTexture = source.targetTexture;
    24.         RenderSettings.skybox = m_VideoSkyboxMaterial;
    25.         foreach (GameObject go in m_GameObjects)
    26.         {
    27.             go.SetActive(false);
    28.         }
    29.     }
     
    LaureneTvl likes this.
  3. LaureneTvl

    LaureneTvl

    Joined:
    Oct 25, 2019
    Posts:
    2
    Hi there,
    I had an identical issue : I use multiple video players to play multiple video dowloaded at run time. I prepared the other video while playing the first one. When I hit NextVideo I just play the video on the next videoplayer. But when I wanted to go back to the previous video, only the sound changed and not the image : the image was the current video that stopped. To solve this, I used what you said : I just assign the videoTexture to the videoplayer.targetTexture each time I want to play a video, then I assign it to null when I am finished. Thank you very much !
     
  4. patSilva

    patSilva

    Joined:
    Mar 25, 2019
    Posts:
    27
    Awesome, actually you only need to release and recreate the texture with renderTexture's Release and Create methods. So when I switched the videoPlayer's videoClip I used videoPlayer.targetTexture.Release() and then when I pressed play, before playing I did videoPlayer.targetTexture.Create() this prevented the frame of the previous video from showing up on the current video.

    Your answer helped after I saw that you called Create after the render texture which meant that the constructor didn't actually create the Render Texture. I also found out that Render Texture do NOT get cleaned up by garbage collection unless you call Release when you are done with it.

    Docs on Render Texture.Release
    Docs on Render Texture.Create
     
  5. BlinksTale

    BlinksTale

    Joined:
    Dec 15, 2013
    Posts:
    13
    This is great for preventing the old video from appearing, but still gives me a "flash" of no video, or seeing whatever is behind the video player, blackness, etc, before the new video starts.

    If you also want to have the next video display instantly, using a prerendered static texture with blit seems to work. The only problem is, a video seems to not render until its frames are loaded - so you might have to use a Coroutine to wait until it's reached frame 1 before you allow it to be seen. Hope this helps someone else!
     
  6. CassiusAbreu

    CassiusAbreu

    Joined:
    Dec 12, 2022
    Posts:
    3
    So simple and perfect thank you!