ManimCommunity / manim-voiceover

Manim plugin for all things voiceover
https://voiceover.manim.community/en/stable
MIT License
186 stars 25 forks source link

fix: no voice when use cache #92

Closed Maxwin-z closed 2 months ago

Maxwin-z commented 5 months ago

In the manim source, it will reset skip_animations before each animation play. https://github.com/ManimCommunity/manim/blob/4641c0a80882135db55c396195b55cab264bd37a/manim/renderer/cairo_renderer.py#L68

        # Reset skip_animations to the original state.
        # Needed when rendering only some animations, and skipping others.
        self.skip_animations = self._original_skipping_status
        self.update_skipping_status()

        scene.compile_animation_data(*args, **kwargs)

But when use cached animation (when re-render), the skip_animations will be set to True after play animation done. https://github.com/ManimCommunity/manim/blob/4641c0a80882135db55c396195b55cab264bd37a/manim/renderer/cairo_renderer.py#L93

                if self.file_writer.is_already_cached(hash_current_animation):
                    logger.info(
                        f"Animation {self.num_plays} : Using cached data (hash : %(hash_current_animation)s)",
                        {"hash_current_animation": hash_current_animation},
                    )
                    self.skip_animations = True
                    self.time += scene.duration

And add_sound will check skip_animations, so the next voiceover cannot add sound to scene. https://github.com/ManimCommunity/manim/blob/4641c0a80882135db55c396195b55cab264bd37a/manim/scene/scene.py#L1614

        if self.renderer.skip_animations:
            return
        time = self.renderer.time + time_offset
        self.renderer.file_writer.add_sound(sound_file, time, gain, **kwargs)

This example will recur this problem.

class GTTSExample(VoiceoverScene):
    def construct(self):
        self.set_speech_service(GTTSService(lang="en", tld="com"))

        circle = Circle()
        square = Square().shift(2 * RIGHT)

        with self.voiceover(text="This circle is drawn as I speak.") as tracker:
            self.play(Create(circle), run_time=tracker.duration)         # skip_animations will be set True when re-render

        # the follow sound will not add to scene
        with self.voiceover(text="Let's shift it to the left 2 units.") as tracker:
            self.play(circle.animate.shift(2 * LEFT), run_time=tracker.duration)

        # the follow sound will not add to scene
        with self.voiceover(text="Now, let's transform it into a square.") as tracker:
            self.play(Transform(circle, square), run_time=tracker.duration)

        # the follow sound will not add to scene
        with self.voiceover(text="Thank you for watching."):
            self.play(Uncreate(circle))

        self.wait()