Usage
Examples
See Examples to get started fast.
This library has a single class: parallel_animate.Animator.
To make an animation you create your own subclass and define two methods.
Define your animator
setup(self)— no arguments exceptself. Build your figure however you like and return theplt.Figureobject. Store the things you will need to update later (axes, the return values of plotting calls likeax.plot, etc.) as instance attributes so you can access them inupdate().update(self, frame_idx, params)— given the frame index and the per-frame parameters, mutate the artists you created insetup(). Typically you call methods likeline.set_data(...)on attributes you stored.paramscan be any picklable Python object (a dict, tuple, single value, ...).- (Optional)
__init__(self, ...)— add any custom construction logic. This is handy when you want to create many animators from the same class with different settings, e.g.anim = RecordingAnimator(dataset_path=...).
Keep heavy data out of instance attributes
In parallel mode the whole Animator instance is pickled into every
worker process. Stashing a large array (e.g. a full video tensor) on self
multiplies its memory across workers. Pass per-frame data through
param_by_frame instead, or load it lazily inside setup().
Render the video
Once your animator is defined, a single call renders the video:
anim = MyAnimation()
anim.make_video(
output_file="out.mp4",
param_by_frame=params,
fps=30,
num_workers=-1,
)
Key arguments to make_video:
output_file(Path | str) — output video path.param_by_frame(Iterable) — one element per frame, each passed toupdate()asparams. Can be a list, tuple, or generator. Generators are useful for large per-frame data (e.g. bitmaps) to avoid loading everything into memory at once.fps(int) — frame rate of the output video.n_frames(int | None) — number of frames to render. IfNone, the length ofparam_by_frameis used (when available).num_workers(int) — worker processes to spawn.-1uses all CPU cores,-2all but one, etc.1runs in the main process (no child processes).video_mode(str) — encoder selection passed to parallel-video-io:"auto"(default) uses GPU/NVENC when a CUDA device is available and falls back to CPU/libx264 otherwise;"gpu"forces NVENC and"cpu"forces libx264. Output is always an H.264 MP4.video_quality,video_preset,video_extra_ffmpeg_params— optional encoding-quality controls forwarded to parallel-video-io. Leave asNonefor sensible defaults.
See the API reference for the remaining, less commonly used options (logging intervals, figure reuse, prefetching).
Out-of-order frame parameters
Sometimes the frames in param_by_frame arrive out of order — for example when
the parameters are decoded from a video by a parallel dataloader that returns
frames non-deterministically. Wrap each item in
parallel_animate.IndexedFrameParams, which carries an
explicit frame_id that overrides the iterator ordering:
from parallel_animate import IndexedFrameParams
param_by_frame = [
IndexedFrameParams(frame_id=5, params={"frame": ...}),
IndexedFrameParams(frame_id=0, params={"frame": ...}),
# ...
]
See examples/nondeterministic_video_loader.py for a full
example.