Skip to content

[FEATURE] Integrate with marimo notebook #490

Open
@way-zer

Description

@way-zer

Terms

Description

Marimo is an open-source reactive notebook for Python — reproducible, git-friendly, executable as a script, and shareable as an app. As an alternative to jupyter/ipython.

There is ipython_magic, but not work for marimo(need invoke and ipython).So I make a monkey-patch, but It's better to add support natively.

The monkey-patch add Slide._repr_html_ like ipython_magic. Document about this api

Monkey patch

from manim_slides import Slide

import logging
import mimetypes
from pathlib import Path

from manim import config, logger
from manim.constants import RendererType
from manim.renderer.shader import shader_program_cache

from manim_slides.convert import (
    RevealJS,
    Template,
    file_to_data_uri,
    get_duration_ms,
    os,
)
from manim_slides.present import get_scenes_presentation_config


class PatchedRevealJS(RevealJS):
    def convert(self) -> str:
        if self.data_uri:
            assets_dir = Path("")  # Actually we won't care.
        else:
            raise NotImplementedError()

        revealjs_template = Template(self.load_template())

        options = self.model_dump()
        options["assets_dir"] = assets_dir

        has_notes = any(
            slide_config.notes != ""
            for presentation_config in self.presentation_configs
            for slide_config in presentation_config.slides
        )

        return revealjs_template.render(
            file_to_data_uri=file_to_data_uri,
            get_duration_ms=get_duration_ms,
            has_notes=has_notes,
            env=os.environ,
            **options,
        )


def _extend_mime(cls):
    logging.getLogger("manim-slides").setLevel(logging.getLogger("manim").level)

    renderer = None
    if config.renderer == RendererType.OPENGL:
        from manim.renderer.opengl_renderer import OpenGLRenderer

        renderer = OpenGLRenderer()

    try:
        scene = cls(renderer=renderer)
        scene.render()
    finally:
        # Shader cache becomes invalid as the context is destroyed
        shader_program_cache.clear()

        # Close OpenGL window here instead of waiting for the main thread to
        # finish causing the window to stay open and freeze
        if renderer is not None and renderer.window is not None:
            renderer.window.close()

    if config["output_file"] is None:
        logger.info("No output file produced")
        return

    file_type = mimetypes.guess_type(config["output_file"])[0] or "video/mp4"

    if not file_type.startswith("video"):
        raise ValueError(f"Manim Slides only supports video files, not {file_type}")

    presentation_configs = get_scenes_presentation_config(
        [cls.__name__], Path("./slides")
    )
    out_data = PatchedRevealJS(
        presentation_configs=presentation_configs, data_uri=True
    ).convert()

    return """<div style="position:relative;padding-bottom:56.25%;"><iframe style="width:100%;height:100%;position:absolute;left:0px;top:0px;" frameborder="0" width="100%" height="100%" allowfullscreen allow="autoplay" srcdoc="{srcdoc}"></iframe></div>""".format(
        srcdoc=out_data.replace('"', "'")
    )


Slide._repr_html_ = classmethod(_extend_mime)

Usage:

from manim import Scene, Square, Circle, BLUE, GREEN, PINK, Create, Transform
from manim_slides.slide import Slide

import helper

blue_circle = Circle(color=BLUE, fill_opacity=0.5)
green_square = Square(color=GREEN, fill_opacity=0.8)
class CircleToSquare(Slide):
    def construct(self):
        self.play(Create(blue_circle))
        self.next_slide()

        self.play(Transform(blue_circle, green_square))

CircleToSquare

Screenshots

image

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestlibRelated to the library (a.k.a. module)

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions