I'm trying to animate a 3d line plot for attractors, using Line3DCollection. The animation is initally fast but it gets progressively slower over time. A minimal example of my code:
def generate_video(nframes):
fig = plt.figure(figsize=(16, 9), dpi=120)
canvas_width, canvas_height = fig.canvas.get_width_height()
ax = fig.add_axes([0, 0, 1, 1], projection='3d')
X = np.random.random(nframes)
Y = np.random.random(nframes)
Z = np.random.random(nframes)
cmap = plt.cm.get_cmap("hsv")
line = Line3DCollection([], cmap=cmap)
ax.add_collection3d(line)
line.set_segments([])
def update(frame):
i = frame % len(vect.X)
points = np.array([vect.X[:i], vect.Y[:i], vect.Z[:i]]).transpose().reshape(-1,1,3)
segs = np.concatenate([points[:-1],points[1:]],axis=1)
line.set_segments(segs)
line.set_array(np.array(vect.Y)) # Color gradient
ax.elev += 0.0001
ax.azim += 0.1
outf = 'test.mp4'
cmdstring = ('ffmpeg',
'-y', '-r', '60', # overwrite, 1fps
'-s', '%dx%d' % (canvas_width, canvas_height),
'-pix_fmt', 'argb',
'-f', 'rawvideo', '-i', '-',
'-b:v', '5000k','-vcodec', 'mpeg4', outf)
p = subprocess.Popen(cmdstring, stdin=subprocess.PIPE)
for frame in range(nframes):
update(frame)
fig.canvas.draw()
string = fig.canvas.tostring_argb()
p.stdin.write(string)
p.communicate()
generate_video(nframes=10000)
I used the code from this answer to save the animation to mp4 using ffmpeg instead of anim.FuncAnimation as its much faster for me. But both methods get slower over time and I'm not sure how to make the animation not become slower. Any advice is welcome.
Versions: Matplotlib: 3.4.2 FFMpeg: 4.2.4-1ubuntu0.1