Hang with MovieStim.draw(): logic error in my script?

I have code that looks like the following (the context is an infant habituation experiment where we measure how long the infant looks at the screen when certain types of video are presented):

def read_movie(fn,loop=False):
    return visual.MovieStim(win,fn,loop=loop) #same behaviour with MovieStim2; MovieStim3 does not work for me
def play(movie):
    print 'drawing',
    movie.draw(win)
    print 'flipping',
    win.flip()
    return movie.status != visual.FINISHED
def getNext():
    #returns the next movie object to be played (loaded in previously using read_movie())
def trial():
        while True:
            print "Entering outer loop"
            movie = getNext()
            movie.play()
            while play(movie):
                # do experiment stuff
                # returns from the trial() function if certain conditions are met

The problem is that this code hangs in the movie.draw(win) function right when the next video file should be played (the console prints drawing but the flipping never comes).

I can think of only one scenario where this makes sense: if I’m trying to play beyond the end of the file, I can imagine the draw call patiently waiting for a next frame that is never going to arrive, thus causing a hang. However, I don’t see how that’s possible, given that, if the movie has finished playing, the while play(movie) loop should have aborted due to movie.status != visual.FINISHED evaluating to False.

Is there an error in the logic of my script, or is there something else I’m doing wrong? I would be more than happy to share the full script and some example stimuli, if necessary. This is with PsychoPy 1.85.1 on a Windows 7 x64 box.

Hi,

First, if you’re doing habituation experiments with movie files, I might have a solution for you beyond this specific issue, which is that I’ve created a PsychoPy script designed to do exactly, precisely this, which I call PyHab (https://github.com/jfkominsky/PyHab). It uses MovieStim3, but it should be straightforward to replace its MovieStim3 with a MovieStim if you can’t get MovieStim3 working on your setup.

Second, for this specific issue, I think you’re probably right in general that it’s trying to draw a frame that is past the end of the movie file or otherwise one that does not exist. That probably has something to do with when the “finished” status is actually tripped, but I don’t know enough about moviestim statuses to be sure (I just calculate duration or num. frames and use that). I think something like this should side-step the issue:

def play(movie):
    if movie.status != visual.FINISHED:
        print 'drawing',
        movie.draw(win)
    print 'flipping',
    win.flip()
    return movie.status != visual.FINISHED

Failing that you might need to determine the number of frames in the movie and use that as a counter.

After some debugging, it turns out that the problem was indeed with the visual.FINISHED property, which was not being triggered properly. We have now successfully implemented a workaround whereby we manually calculate the expected duration of the movie by multiplying a ticker counting the number of movie.draw() calls with the (a priori known) fps value. Thanks for that clever idea.