manim: t values issue that causes the animations to not be finished entirely.
y values are generated with those lines : (progress_through_animations, l883, scene.py).
for t in self.get_animation_time_progression(animations):
dt = t - last_t
last_t = t
for animation in animations:
animation.update_mobjects(dt)
alpha = t / animation.run_time
animation.interpolate(alpha)
self.update_mobjects(dt)
self.update_frame(moving_mobjects, static_image)
self.add_frames(self.get_frame())
get_animation_time_progression returns a ProgressBarDisplay object, from the library tdqm that we use to display the progress bar.
When doing -s, skip_animations is enabled to t value is set to 1.0 (no intermediary values as we just need the last frame).
When running normally, eg with 15 fps, there are logically 15 t values, that are :
0.0
0.06666666666666667
0.13333333333333333
0.2
0.26666666666666666
0.3333333333333333
0.4
0.4666666666666667
0.5333333333333333
0.6
0.6666666666666666
0.7333333333333333
0.8
0.8666666666666667
0.9333333333333333
As you may see, 1 is never reached. In other terms, the animations is stopped at 93%). Not that 1.0 change depending on the rn_time : if the run_time was let’s say 3, last t value would be 2.93.
We can see this issue with a single pixel that should be here :

To give an idea of a fix, I will use the words of @leotrs :
I’ve never used tqdm myself so my question is: is it orthodox/expected/good practice to determine the course of a program by querying the progress bar itself? I’m not sure how this works at all.
It’d be much more reasonable I think for manim to determine its own course of action and then tell the progress bar to reflect that, instead of the other way around
About this issue
- Original URL
- State: open
- Created 4 years ago
- Comments: 35 (34 by maintainers)
Leo you are correct on this. That is why some video standards have fractions in their fps counts. In the US for example the standard for TV is 59.94 FPS or exactly 1% slower than the 60Hz electricity there.
On Mon, Sep 7, 2020, 3:38 PM Leo Torres notifications@github.com wrote:
Only the time between frames is counted toward the animation, so there is no additional 1/15 seconds added by the last frame. For example if you wanted to show an animation at 1 fps for 1 second you’d have to generate a start and end frame, otherwise you wouldn’t have any video at all.
Well, it is not fixed. I’m working on it !
Keep in mind that if we do this then the last frame of animation n and the first frame of animation n+1 will always be the same, which would cause an unavoidable pause between animations which would be especially noticeable at low frame rates. It wouldn’t be possible to create the effect where animation 1 runs from 0s to 1s and animation 2 runs from 1s to 2s. This isn’t technically possible now, since playing an animation for 1s at a given frame rate generates <frame_rate> frames, which is only (frame_rate-1)/frame_rate seconds of video.
If you did want to do this, you’d probably want to increase the number of samples to 1 more than the frame rate so that each animation played for 1s rather than (frame_rate-1)/(frame_rate) seconds as it does now. Consecutive calls to play() would then generate video lengths of 1s, (2 + 1/frame_rate)s, (3 + 2/frame_rate)s, etc.
However, I think the proper solution is just to add a terminating frame at the end of the last animation, so that consecutive calls to play() would generate video with frame counts of 16, 31, 46, etc., which corresponds to video lengths of 1s, 2s, 3s, etc. at 15fps.