Rendering MANIM animations directly on a Kivy application with OpenGL
kivy_complex_animation-2022-06-29_03.11.39.mp4
If you want to render MANIM animations on a mobile app, the first step is being able to render MANIM inside Kivy.
Hacking MANIM
- modify the file
manim.renderer.opengl_renderer.OpenGLRenderer
. InsideOpenGLRenderer
, modify the functionget_raw_frame_buffer_object_data
: we are going to intercept the frames that would be sent toffmpeg
and send them to Kivy
def get_raw_frame_buffer_object_data(self, dtype="f1"):
# Copy blocks from the fbo_msaa to the drawn fbo using Blit
# pw, ph = self.get_pixel_shape()
# gl.glBindFramebuffer(gl.GL_READ_FRAMEBUFFER, self.fbo_msaa.glo)
# gl.glBindFramebuffer(gl.GL_DRAW_FRAMEBUFFER, self.fbo.glo)
# gl.glBlitFramebuffer(
# 0, 0, pw, ph, 0, 0, pw, ph, gl.GL_COLOR_BUFFER_BIT, gl.GL_LINEAR
# )
num_channels = 4
ret = self.frame_buffer_object.read(
viewport=self.frame_buffer_object.viewport,
components=num_channels,
dtype=dtype,
)
from kivy.app import App
app = App.get_running_app()
app.update_frame_to_render(ret)
return ret
-
Run
main.py
-
Enjoy rendering MANIM animations inside a cross-platform Kivy app.
Optional:
I you want to make sure ffmpeg is not used, go to manim.scene.scene_file_writer.SceneFileWriter
and change the function write_opengl_frame
:
def write_opengl_frame(self, renderer):
if write_to_movie():
renderer.get_raw_frame_buffer_object_data(),
# self.writing_process.stdin.write(
# renderer.get_raw_frame_buffer_object_data(),
# )
elif is_png_format() and not config["dry_run"]:
target_dir = self.image_file_path.parent / self.image_file_path.stem
extension = self.image_file_path.suffix
self.output_image(
renderer.get_image(),
target_dir,
extension,
config["zero_pad"],
)
Obviously the whole approach is not optimal and a lot of improvements can be done, this is just a minimal runnable example and feel free to improve it, I will probably improve it in the future.