Search code examples
pythonmatplotlibffmpegvideo-processing

Set matplotlib video animation size (1920x1080)


I'm trying to create a matplotlib animation that is 1920x1080. The following animation generated is (1152x648), which is the right ratio but too small. I know that I can do this after the fact with ffmpeg, but I'd like to avoid re-encoding if possible.

y = my_data
fig = plt.figure(figsize=(16,9))

def ani(i):
    # Animation Code

animator = FuncAnimation(fig, ani, frames=y.shape[0])

# Can't figure out what extra_args to set here
ffmpeg_writer = FFMpegWriter(fps=y.shape[0]/sound.duration_seconds, extra_args=['-scale', '1920x1080'])
animator.save('mymovie.mp4', writer=ffmpeg_writer)

print(ffmpeg_writer.frame_size) # prints (1152, 648)

ipd.Video('mymovie.mp4')

As you can see above, I have tried a few extra_args, however I can't get anything to work.


Solution

  • You can set the DPI arguments as described in the following post.

    The nominal DPI of your system is 72, so the resolution is 72*16x72*9 = 1152x648.
    We can set the DPI to 1920/16 for getting resolution 1920x1080:

    fig = plt.figure(figsize=(16, 9), dpi=1920/16)
    

    Here is an executable code sample (used for testing):

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.animation as animation
    
    # 72 is the nominal DPI that is the reason figsize=(16, 9) resolution is (1152, 648).
    # Set the DPI to 120 for getting resolution is (1920, 1080)
    fig = plt.figure(figsize=(16, 9), dpi=(1920/16))
    ax = plt.gca()  # Get current axes
    
    l1, = ax.plot(np.arange(1, 10), np.arange(1, 10), **{'marker':'o'})
    
    def init():
        l1.set_data([],[])
        
    def ani(i, l1):
        l1.set_data(i/5, np.sin(0.5*i)*4+5)
        l1.set_markersize(10)
    
    animator  = animation.FuncAnimation(fig, ani, fargs=(l1,), init_func=init, frames=50, interval=1, blit=False)  # 50 frames, interval=1
    
    ffmpeg_writer = animation.FFMpegWriter(fps=10)
    animator.save('mymovie.mp4', writer=ffmpeg_writer)
    
    plt.show()  # Show for testing