Detect when video ends

Hi there, to play a video i am using the following code

        self.tex = MovieTexture("name")
        success = self.tex.read("A_CLIENT\ASSETS\GAME\CINEMATICS\intro.mp4")
        assert success, "Failed to load video!"

        # Set up a fullscreen card to set the video texture on.
        cm = CardMaker("My Fullscreen Card")
        cm.setFrameFullscreenQuad()

        # Tell the CardMaker to create texture coordinates that take into
        # account the padding region of the texture.
        cm.setUvRange(self.tex)

        # Now place the card in the scene graph and apply the texture to it.
        card = NodePath(cm.generate())
        card.reparentTo(self.base.render2d)
        card.setTexture(self.tex)

        self.sound = self.base.loader.loadSfx("A_CLIENT\ASSETS\GAME\CINEMATICS\intro.mp4")
        # Synchronize the video to the sound.
        self.tex.synchronizeTo(self.sound)
        self.sound.setLoop(False)
        self.sound.play()

but, how can i detect when it ends?
i’ve tried

while self.tex.isPlaying():
    pass

to make the function return only when the video is over, but this never ends, the last frame of the video stays on screen and the while loop never ends!

note: in the while loop self.sound.isPlaying raises an error.

I have this approach for these purposes. Just to compare the length of the video in the task, and the elapsed time.

from direct.showbase.ShowBase import ShowBase
from panda3d.core import NodePath, CardMaker, MovieTexture, TextureStage
from direct.task import Task

class Game(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        self.tex = MovieTexture("logo")

        assert self.tex.read("PandaSneezes.ogv")

        cm = CardMaker("screen");
        cm.set_frame_fullscreen_quad()
        cm.set_uv_range(self.tex)
        
        card = NodePath(cm.generate())
        card.reparent_to(render2d)
        card.set_texture(self.tex)

        taskMgr.add(self.get_time, 'get time')
        
        self.length_video = self.tex.get_video_length()
        
    def get_time(self, task):

        if self.tex.get_time() >= self.length_video:
            self.tex.stop()
            print("Video end")
            return task.done
        return task.cont

game = Game()
game.run()
1 Like

Indeed: Outside of a more-advanced technique, the above will keep the code within that while-loop–and thus unable to do anything else (such as continue the video).

The approach shown by serega above should work, I daresay. As an alternative, you could perhaps do similarly, but combine it with your approach and within the task check the result of the “isPlaying” method. Something like this:

def get_time(self, task):
    if self.tex.isPlaying():
        return task.cont
    
    print ("Video ended!")
    return task.done

That said, I don’t have experience with Panda’s video support, so I don’t know with confidence that the “isPlaying” method does actually work for this purpose. It seems worth trying, however!