3b1b / manim

Animation engine for explanatory math videos
MIT License
70.78k stars 6.23k forks source link

Export with transparency on Windows #2110

Open stephanedebove opened 8 months ago

stephanedebove commented 8 months ago

Describe the bug

I have spent a couple of days working on my animations and exporting them as .mp4 for testing purposes. I thought switching to a .mov format with transparent background would be as easy as adding the -t flag to my manim command, but apparently it’s not.

manim -qh myfile.py BounceImage

works. It produces a .mp4 and I can see my animation (a simple image entering the screen with a bouncing effect, see code below). But with

manim -tqh myfile.py BounceImage

it’s producing a .mov file that can only be opened in VLC and not Premiere ("File import failure: The file has no audio or video stream") neither Windows Media Player, Media Player, Movies & TV ("The file is encoded in rle format which isn’t supported").

Plus, when opened in VLC, I do not see the boucing animation, I just see my image at its final position.

I’m using Manim Community v0.18.0 inside a Conda environment on Windows if it matters.

If it’s a known bug, what would be the best workaround? Can ffmpeg remove the solid background from a .mp4 for instance? Or is it better to export as a series of transparent .png and then use ffmpeg to merge them into a .mov file that can be read by Premiere (which is the final editing software I will be importing into)?

My bouncing effect:

class BounceImage(Scene):

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.img_path = "path/to/image.jpg"

    def construct(self):
        img = ImageMobject(self.img_path)
        video_width = config.frame_width
        img_width = video_width * 0.4
        img.scale_to_fit_width(img_width)

        margin = 0.02 * video_width
        final_pos = np.array([-config.frame_width / 2 + margin + img_width / 2, config.frame_height / 2 - margin - img.height / 2, 0])

        img.move_to(final_pos + 5*UP)
        img_start = img.copy()

        points = [
            final_pos + 5*UP,
            final_pos + 2*UP,
            final_pos + 0.3*UP,
            final_pos - 0.15*UP,
            final_pos + 0.15*UP,
            final_pos + 0.05*UP,
            final_pos,
            final_pos - 0.075*UP,
            final_pos + 0.075*UP,
            final_pos - 0.05*UP,
            final_pos
        ]

        path = VMobject().set_points_smoothly(points)

        self.play(MoveAlongPath(img_start, path, rate_func=smooth), run_time=1)
        self.wait(10)