Search Unity

  1. We would like to hear your feedback about Unity and our products. Click here for more information.
    Dismiss Notice

Video RenderTexture retaining last video player frame

Discussion in 'Audio & Video' started by emongev, Oct 4, 2017.

  1. emongev

    emongev

    Joined:
    Jul 5, 2012
    Posts:
    23
    So whenever i try showing the video, I get a single frame of the last frame popping up before playing the video.

    How would I go about fixing this? :)

    Thanks in advance!
     
    Razek07 likes this.
  2. Fl0oW

    Fl0oW

    Joined:
    Apr 24, 2017
    Posts:
    17
    This might be late, but for future reference:

    The videoPlayer retains the last frame instead of resetting to the first frame when the end / the loop point is reached. You can manually reset the frame to the first one by subscribing to the method which is invoked as soon as the videoPlayer reaches the loop point:

    Code (CSharp):
    1. // Subscribe to loopPointReached event
    2.         videoPlayer.loopPointReached += EndReached;
    and then

    Code (CSharp):
    1. void EndReached(UnityEngine.Video.VideoPlayer vp)
    2.     {
    3.         // Reset video to first frame
    4.         videoPlayer.frame = 0;
    5.     }
    Next time you play the video it should start from frame 0 instead of from the last frame.

    Hope this helps!
     
  3. MSachs

    MSachs

    Joined:
    Nov 22, 2017
    Posts:
    101
    Hi,

    I have the same issue and the code you suggested doesn't seem to do the trick... I still see the last frame of the video everytime I start it again...
     
  4. Fl0oW

    Fl0oW

    Joined:
    Apr 24, 2017
    Posts:
    17
    Can you post some code of the script which loads/starts the video? Also, what settings do you have for looping, playOnAwake etc.?
     
  5. MSachs

    MSachs

    Joined:
    Nov 22, 2017
    Posts:
    101
    this is the code. PlayVid() gets called when tapping on a collider.
    Looping is off since I want to disable the gameObject after it played once.
    Play on Awake is on and wait for first frame as well.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Video;
    5.  
    6.  
    7. public class WorldSpaceVideo : MonoBehaviour
    8. {
    9.    
    10.     public GameObject VP;
    11.     public VideoPlayer videoPlayer;
    12.     private int videoClipIndex;
    13.  
    14.  
    15.  
    16.     // Use this for initialization
    17.     void Start ()
    18.     {
    19.         videoPlayer.loopPointReached += EndReached;
    20.     }
    21.        
    22.  
    23.     public void PlayVid()
    24.     {
    25.         if (!VP.activeSelf)
    26.         {
    27.             VP.SetActive (true);
    28.         }
    29.     }
    30.  
    31.        
    32.     void EndReached (VideoPlayer videoPlayer)
    33.     {
    34.         VP.SetActive (false);
    35.     }
     
  6. Fl0oW

    Fl0oW

    Joined:
    Apr 24, 2017
    Posts:
    17
    So did you already try setting videoPlayer.frame = 0 in EndReached?
     
  7. MSachs

    MSachs

    Joined:
    Nov 22, 2017
    Posts:
    101
    Yes I added it right here in the but it had no effect. I don't know if I have to change anything else or if this way of implementing it is completely wrong :D


    Code (CSharp):
    1.     void EndReached (VideoPlayer videoPlayer)
    2.     {
    3.         VP.SetActive (false);
    4.         videoPlayer.frame = 0;
    5.     }
     
  8. kishanrathod

    kishanrathod

    Joined:
    Jan 9, 2018
    Posts:
    1
    I'm having the same issue. The video player hold on to the last frame that it played
     
  9. pamelacook

    pamelacook

    Joined:
    Dec 13, 2017
    Posts:
    5
    I have a problem when I execute VideoPlayer.Stop. It keeps the last frame that played. That is by design according to the scripting documentation. I tried videoPlayer.frame = 0; but it's not working.
     
  10. patrick_scheper

    patrick_scheper

    Joined:
    Mar 18, 2015
    Posts:
    16
    Hey all! I saved the first frame of the video as an Texture2D and used 'Graphics.Blit(firstFrameTexture, videoRenderTexture)' to basically reset the render texture before I call VideoPlayer.Play.

    When you call 'VideoPlayer.Stop' it doesn't clear the render texture, which means once you start it again, it shows the last frame.

    edit:
    Using RenderTexture.DiscardContents did not seem to do the trick, neither does VideoPlayer.frame.
     
    jsleek likes this.
  11. jsleek

    jsleek

    Joined:
    Oct 3, 2014
    Posts:
    43

    Can anyone from Unity comment on why this doesn't work? It's very annoying. Seems like a bug.
     
    patrick_scheper likes this.
  12. codemonkeynorth

    codemonkeynorth

    Joined:
    Dec 5, 2017
    Posts:
    6
    I currently use this when hiding my video ready for the next time

    Code (CSharp):
    1. renderTexture.DiscardContents();
    2. Graphics.Blit(firstFrameTexture, renderTexture);
    but it relies on having a bitmap of the first frame (which I guess you could get from the video at startup etc)

    you could maybe use this technique
    https://forum.unity.com/threads/video-player-preview.527061/#post-3464306
     
    Last edited: Jun 30, 2018
  13. Harrison_Perry

    Harrison_Perry

    Joined:
    Jan 16, 2017
    Posts:
    7
    I got this to go away by using GL.Clear on the Video Player's awake.

    Code (CSharp):
    1. RenderTexture.active = videoplayer.targetTexture;
    2. GL.Clear(true, true, Color.black);
    3. RenderTexture.active = null;
     
  14. Zeratul3D

    Zeratul3D

    Joined:
    Nov 11, 2015
    Posts:
    7
    Changing the frame in the same method as we stop the player won't allow it to render the next (zero) frame before stopping.

    It would be enough to set videoPlayer.frame = 0; then yield return new WaitForEndOfFrame(); and then videoPlayer.stop();
     
  15. konzeptzwei

    konzeptzwei

    Joined:
    Feb 10, 2006
    Posts:
    54
    well, so actually videoPlayer.frame = framenumber does not work at all?
     
  16. patrick_scheper

    patrick_scheper

    Joined:
    Mar 18, 2015
    Posts:
    16
    Nope. Try my solution above, it worked for me.
     
  17. marianomdq

    marianomdq

    Joined:
    Sep 29, 2015
    Posts:
    3
    Hi everyone

    Thanks for all the useful help. I've been trying all the proposed solutions, but in my case it's been a pain in the neck.

    I'm not trying to obtain the 0 frame. My code needs to get an specific frame that it's not the current frame played by the videoplayer. For example, I could have a video from 0 to 500 frames, the current frame being 455 and I would need to obtain the renderTexture from frame 200. This last frame can change depending on player's decisions.

    For this I'm following the next approach:
    • Having a parallel hidden videoplayer2
    • Bind handlers for the videoplayer2.started and videoplayer2.prepareCompleted events
    • Stop the videoplayer2
    • Set videoplayer2.clip = videoplayer1.clip
    • Set videoplayer2.frame = videoplayer1.frame
    • videoplayer2.Prepare()
    • on prepareCompleted -> videoplayer2.Play()
    • on videoplayer2.started -> here I go for the videoplayer2 renderTarget's Texture
    But, I'm still dealing with the issue that the renderTarget it is still not getting updated on this frame.

    The only solution that I've found this far is to add a yield return new WaitForFrames(numberOfFrames) after the videoplayer2.started has began.

    Code (CSharp):
    1. private void VideoPlayer_started(VideoPlayer source)
    2. {
    3.     StartCoroutine(WaitForFramesAndCopyRenderTexture(20, source));
    4. }
    Code (CSharp):
    1. private IEnumerator WaitForFramesAndCopyRenderTexture(int frames, VideoPlayer source)
    2. {
    3.     // Videoplayer has a delay until it renders the targetTexture, we need to wait until it's done
    4.     yield return new WaitForFrames(frames);
    5.  
    6.     source.Pause();
    7.  
    8.     var renderTexture = source.targetTexture;
    9.     var copy = new RenderTexture(renderTexture);
    10.     Graphics.CopyTexture(renderTexture, copy);
    11. }
    But this is awful. Depending on the hardware, this could take more frames to render the texture. Is there actually no other solution for this?

    Thanks, help is appreciated.
     
  18. ookk47oo

    ookk47oo

    Joined:
    Mar 17, 2017
    Posts:
    21
    Code (CSharp):
    1.  videoPlayer.targetTexture.Release();
    This code might work.
     
    Last edited: Apr 4, 2019
    funwingame and chrispi_ like this.