使用moviepy制作matplotlib图表的难度很大

时间:2015-04-30 17:46:35

标签: python matplotlib moviepy

我必须制作大量(~90,000)个数字的动画。对于上下文,它是1700年至1950年间每一天的地图,在相关的日子里标记了感兴趣的事件。 我可以使用$r执行此操作,并且我有一些代码可以在一小段测试期间成功完成此操作。然而,对于完整的数字集,这将花费不切实际的时间来渲染并将导致非常大的电影文件。 我已经读过,显然matplotlib.animation.FuncAnimation提供速度和文件大小优势。但是,我无法让它工作 - 我相信我的问题是我不知道如何正确设置moviepyduration参数。

我的代码的简化版本是:

fps

但是,这不会产生为import numpy as np import matplotlib.pyplot as plt from moviepy.video.io.bindings import mplfig_to_npimage import moviepy.editor as mpy fig = plt.figure() ax = plt.axes() x = np.random.randn(10,1) y = np.random.randn(10,1) p = plt.plot(x,y,'ko') time = np.arange(2341973,2342373) def animate(i): xn = x+np.sin(2*np.pi*time[i]/10.0) yn = y+np.cos(2*np.pi*time[i]/8.0) p[0].set_data(xn,yn) return mplfig_to_npimage(fig) fps = 1 duration = len(time) animation = mpy.VideoClip(animate, duration=duration) animation.write_videofile("test.mp4", fps=fps) 的每个元素生成一个帧的预期结果,并将其保存为.mp4。我无法看到我出错的地方,任何帮助或指示都会受到赞赏。

祝福, 路加

1 个答案:

答案 0 :(得分:5)

与JuniorCompressor相同的解决方案,只有一帧保留在内存中以避免RAM问题。这个例子在我的机器上运行30秒,产生一个质量好的400秒的6000帧剪辑,重600k。

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

fig = plt.figure(facecolor="white") # <- ADDED FACECOLOR FOR WHITE BACKGROUND
ax = plt.axes()
x = np.random.randn(10, 1)
y = np.random.randn(10, 1)
p = plt.plot(x, y, 'ko')
time = np.arange(2341973, 2342373)

last_i = None
last_frame = None

def animate(t):
    global last_i, last_frame

    i = int(t)
    if i == last_i:
        return last_frame

    xn = x + np.sin(2 * np.pi * time[i] / 10.0)
    yn = y + np.cos(2 * np.pi * time[i] / 8.0)
    p[0].set_data(xn, yn)

    last_i = i
    last_frame = mplfig_to_npimage(fig)
    return last_frame

duration = len(time)
fps = 15
animation = mpy.VideoClip(animate, duration=duration)
animation.write_videofile("test.mp4", fps=fps)

在旁注中,有一个专门的视频片段叫做DataVideoClip,正是出于这个目的,它看起来更像是matplotlib的animate。目前它不是真正的速度效率(我没有包括上面的那个小记忆技巧)。以下是它的工作原理:

from moviepy.video.VideoClip import DataVideoClip

def data_to_frame(time):
    xn = x + np.sin(2 * np.pi * time / 10.0)
    yn = y + np.cos(2 * np.pi * time / 8.0)
    p[0].set_data(xn, yn)
    return mplfig_to_npimage(fig)

times = np.arange(2341973, 2342373)
clip = DataVideoClip(times, data_to_frame, fps=1) # one plot per second

#final animation is 15 fps, but still displays 1 plot per second
animation.write_videofile("test2.mp4", fps=15)