How to Know video player is finished playing video?

I want to have callback when video player is finished playing video.
If i use videoplayer.isPlaying , this won’t work because this will send call back in case i want to pause video.
there is no bool to know video is stopped or not.

2 Likes
videoPlayer.loopPointReached += EndReached;

And then the EndReached method

void EndReached(UnityEngine.Video.VideoPlayer vp)
{
    vp.playbackSpeed = vp.playbackSpeed / 10.0F;
}

and if you haven’t started playing it yet you can use isPlaying:

13 Likes

@abhayaagrawal I was also looking for an answer for this and found this thread but could not really make heads or tails of it. My video only plays once so there is no looping involved. But I made up my own way of checking if the video is finished playing!

//Play the video!
VP.GetComponent<VideoPlayer>().Play();

//Invoke repeating of checkOver method
InvokeRepeating("checkOver", .1f,.1f);
//checkOver function will use current frame and total frames of video player video
//to determine if the video is over.

private void checkOver()
{
       long playerCurrentFrame = VP.GetComponent<VideoPlayer>().frame;
       long playerFrameCount = Convert.ToInt64(VP.GetComponent<VideoPlayer>().frameCount);
     
       if(playerCurrentFrame < playerFrameCount)
       {
           print ("VIDEO IS PLAYING");
       }
       else
       {
           print ("VIDEO IS OVER");
          //Do w.e you want to do for when the video is done playing.
       
          //Cancel Invoke since video is no longer playing
           CancelInvoke("checkOver");
       }
}

Hope this helps someone else! I spent way too much time on figuring this out and figured I would share!

9 Likes

Thanks for this idea. It works well but I found that InvokeRepeating significantly slowed down my video compared to just running checkOver(); in Update. I’m not well versed in code optimization but I wonder why this is? I also wonder how much System.Covert.ToInt64 running every frame (or every Invoke) slows things down. Maybe someone who knows the engine well and code optimizations can chime in.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Video;

public class Scene_Intro : MonoBehaviour {
public VideoPlayer vid;


void Start(){vid.loopPointReached += CheckOver;}

void CheckOver(UnityEngine.Video.VideoPlayer vp)
{
     print  ("Video Is Over");
}

}

This works great too. As far as I understand it the VideoPlayer has a delegate system. vid.loopPointReached invokes the CheckOver(); function. Works, even if your video is not looping. I’m still unsure this is the most optimized way to do it. Optimization is pretty key when running HD video on mobile devices.

16 Likes
    public double time;
    public double currentTime;
    // Use this for initialization
    void Start () {

    time = gameObject.GetComponent<VideoPlayer> ().clip.length;
    }

   
    // Update is called once per frame
    void Update () {
        currentTime = gameObject.GetComponent<VideoPlayer> ().time;
        if (currentTime >= time) {
            Debug.Log ("//do Stuff");
        }
    }

i usually do this

8 Likes

Thank you !!!

1 Like

videoPlayer.loopPointReached += EndReached works for me!

if ((ulong)videoPlayer.frame == videoPlayer.frameCount)
        {
            //Video Finished
        }

For me the loopPointReached delegate for non-looping video wasn’t triggered. Also the solution with checking frames gives me weird result.

It worked when I casted to float instad of ulong.

Other thing is that the VideoPlayer.frame stops a couple of frames before the frameCount. I needed to adjust for that:

(float)m_GameIntro.frame < m_GameIntro.frameCount - 3

@metroidsnes
Why would you mix ulong into this?

You need to cast because otherwise there’s a compile error, it cannot compare ulong with long. In the picture I compare -1 to 3000 and the result is that -1 is bigger.

In the picture I compare -1 to 3000
No, you compare -1 cast to 18446744073709551615 to 3000.
a being bigger is expected behavior.

Yeah, apparently this is the result of casting -1 to ulong. Thanks for pointing this out.

I think this started only with 2018.3, didn’t? I suddenly need to add this, but before it was working (last frame was correctly reported)

I don’t how it was before. I’m having this problem with Unity 2018.3.0f1.

@unitynoob24
thanks man… saved a lot of time because you

FYI, if I used double currentTime = gameObject.GetComponent ().time; it didn’t work on Android 10 (it worked on Android 8). Instead I used as it was advised by @FMark92 : videoPlayer.loopPointReached += EndReached; and I put it under Start() and worked on Android 10 too.

General note: avoid calling
gameObject.GetComponent ()
or any GetComponent in Update(), or in any function which runs a lot, as it’s wasteful and unnecessary. Cache it in Start and use the local reference.

1 Like

Hi Guys, I think I found out a solution… its a pretty good solution if you want to play a queue of videos… check out…
Hope it helps…

//function to play the clips, if the video player object is present
    public bool playVideoClip(VideoClip video) {
        VideoPlayer videoPlayer = getVideoPlayerInstance();
        if (videoPlayer == null)
            return false;

        //set the functions
        videoPlayer.Stop();
        videoPlayer.clip = video;
        videoPlayer.source = VideoSource.VideoClip;

        videoPlayer.Prepare();

        videoPlayer.Play();

        return true;
    }


    //function to fetch the instance of the videoplayer component
    public VideoPlayer getVideoPlayerInstance() {
        GameObject videoPlayerObject = GameObject.FindGameObjectWithTag(VIDEO_PLAYER_TAG);
        if (videoPlayerObject == null)
            return null;

        return videoPlayerObject.GetComponent<VideoPlayer>();
    }



    //Coroutine to play a queue of videos one by one
    IEnumerator playVideoClipQueue(VideoClip []clips) {
        VideoPlayer vp = getVideoPlayerInstance();

        for (int i = 0; i < clips.Length; i++) {
            playVideoClip(clips);

            while (vp.frame < (long)vp.frameCount - 1) { //as frame goes upto frameCount - 1
                yield return null;
            }
        }

    }


void Start()
    {
        //play the intro clips if any
        //playIntroClips();

        IEnumerator introRoutine = playVideoClipQueue(introClips);
        StartCoroutine(introRoutine);