Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rendered output missing first frame #155

Closed
gazzar opened this issue Apr 13, 2015 · 7 comments
Closed

Rendered output missing first frame #155

gazzar opened this issue Apr 13, 2015 · 7 comments
Labels
stale For issues lacking activity, whose creators have become unresponsive,... video Related to VideoClip and related classes, or handling of video in general.

Comments

@gazzar
Copy link

gazzar commented Apr 13, 2015

First, thanks for moviepy; very nice work! I was inspired to try it after seeing your blog post data-animations-with-python-and-moviepy

I think moviepy is dropping the first frame in all rendered output. Here is a minimal(-ish) example that should render the first frame with a label of 0, but actually starts at 1. This may be related to bug #122.

import matplotlib.pyplot as plt
from moviepy.video.io.bindings import mplfig_to_npimage
import moviepy.editor as mpy

class MyObj(object):
    def __init__(self):
        self.i = 0

    def iterate(self):
        self.i += 1

    def show_f(self):
        plt.figure()
        plt.title('iteration:%d' % self.i)
        return plt.gcf()


def render_frame(t):
    img = myobj.show_f()
    myobj.iterate()
    return mplfig_to_npimage(img)


if __name__ == '__main__':
    myobj = MyObj()
    duration = 1    # Duration of animation in s
    animation = mpy.VideoClip(render_frame, duration=duration)
    # animation.write_gif("moviepy_test.gif", fps=5)
    animation.write_images_sequence('moviepy_test_%03d.png', fps=5)
@Zulko
Copy link
Owner

Zulko commented Apr 13, 2015

I think it's an issue with your code, you are iterating before rendering the frame, so the first frame being rendered is indeed 1. Try this to see the problem:

def render_frame(t):
    img = myobj.show_f()
    myobj.iterate()
    print myobj.i
    return mplfig_to_npimage(img)

@gazzar
Copy link
Author

gazzar commented Apr 14, 2015

Maybe I am missing something obvious, but the image returned by render_frame() is rendered prior to the myobj.iterate() call, so I think the first frame should be 0. I tried this to test this, and I get 5 images generated by moviepy, and 6 images generated from the savefig call:

def render_frame(t):
    img = myobj.show_f()
    myobj.iterate()
    plt.savefig('i_%d'%myobj.i)
    return mplfig_to_npimage(img)

@Zulko
Copy link
Owner

Zulko commented Apr 14, 2015

Ah yes, sorry. Now I see where the problem may be: it comes from the fact that MoviePy will always compute once the first frame of a clip and then throw it away (unless you tell your clip to memoize it). This is not optimal because that means the first frame gets computed twice in many situations, but it also makes a lot of things easier (debugging, interactivity, etc.).

Normally it shouldn't cause any problem because you are supposed to call your clip with a time t, and if you ask twice for the frame at t=0 you will get twice this frame, no problem. But in your case where you try to hack to use indexes instead it causes a problem.

I see several solutions:

(1) If you only need an index, use the time to infer an index:

i = int(t/fps)

(2) If you need to update a clip or to use different data at each index i you can have a look at these two classes, UpdatedVideoClip and DataVideoClip

(3) If you really need to work frame by frame with an update between each and UpdatedVideoClip doesn't work as you want, the simpler is to use directly imageio:

writer = imageio.get_writer('file.mp4', fps=fps)
fori in range(N):
    writer.append_data(myobj.show_f())
    myobj.iterate()
writer.close()

@gazzar
Copy link
Author

gazzar commented Apr 15, 2015

Thanks for the suggestions. I'll have to look more closely at UpdatedVideoClip when I have some time; it seems like the solution that might match my use case. I tried (1) and (3) and they won't work directly for me.

@ghost
Copy link

ghost commented Feb 22, 2017

Has this issue been resolved?

@keikoro
Copy link
Collaborator

keikoro commented Dec 16, 2018

@gazzar Did you manage to solve your problem, can we close this issue?

@keikoro keikoro added video Related to VideoClip and related classes, or handling of video in general. stale For issues lacking activity, whose creators have become unresponsive,... labels Dec 16, 2018
@gazzar
Copy link
Author

gazzar commented Dec 16, 2018

Sure, go ahead and close it. That was so long ago that I can't remember what I eventually did to resolve my problem anyway.

@keikoro keikoro closed this as completed Dec 16, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stale For issues lacking activity, whose creators have become unresponsive,... video Related to VideoClip and related classes, or handling of video in general.
Projects
None yet
Development

No branches or pull requests

3 participants