Why is the last frame always excluded, when converting images into a video?

275 Views Asked by At

I have a folder with 225 pictures of maps. So, I compiled it to an mp4 file using imageio. Whether it's compiling 10 maps, 150, or all 225, the last picture is always not included in the video.

import os
from natsort import humansorted
import imageio

os.chdir(r'folder/path/')
filenames = humansorted((fn for fn in os.listdir('.') if fn.endswith('.png')))
with imageio.get_writer('earthquake_video.mp4', mode='I', fps=2) as writer:
    for filename in filenames:
        image = imageio.imread(filename)
        writer.append_data(image)
    writer.close()
1

There are 1 best solutions below

1
On BEST ANSWER

For me, your code works fine for 10, 150, or even 225 images – as long as I open the resulting video in Windows Media Player. If I open the video in VLC media player, I get distorted playback, not only skipping the last frame. (I have numbers counting from 0 to 224, so every mistaken frame is noticed.) So, if you use VLC media player, your problem most likely is the one discussed in this StackOverflow Q&A.

On the imageio GitHub issue tracker, there's also this issue, linking to this other StackOverflow question, which seems to be same issue as you have. But, still, I think it's the afore-mentioned issue with the VLC media player.

Unfortunately, I couldn't get the workaround from the first linked Q&A working using the output_params from imageio, i.e. setting -framerate or -r. So, my workaround here would be to set up a desired fps (here: 2), and a fps for the actual playback (in VLC media player), e.g. 30, and then simply add as many identical frames as needed to fake the desired fps, i.e. 30 // 2 = 15 here.

Here's some code:

import os
import imageio

os.chdir(r'folder/path')
filenames = [fn for fn in os.listdir('.') if fn.endswith('.png')]
fps = 2             # Desired, "real" frames per second
fps_vlc = 30        # Frames per second needed for proper playback in VLC
with imageio.get_writer('earthquake_video.mp4', fps=fps_vlc) as writer:
    for filename in filenames:
        image = imageio.imread(filename)
        for i in range(fps_vlc // fps):
            writer.append_data(image)
    writer.close()

The resulting video "looks" the same as before (in Windows Media player), but now, it's also properly played in VLC media player.

Even, if that's not YOUR actual problem, I guess this information will help other coming across your question, but actually suffering from the stated issue with the VLC media player.

----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.16299-SP0
Python:        3.9.1
PyCharm:       2021.1.1
imageio:       2.9.0
----------------------------------------