Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions manim/renderer/cairo_renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ def play(
# Needed when rendering only some animations, and skipping others.
self.skip_animations = self._original_skipping_status
self.update_skipping_status()
skip_due_to_cache = False

scene.compile_animation_data(*args, **kwargs)

Expand All @@ -96,6 +97,7 @@ def play(
{"hash_current_animation": hash_current_animation},
)
self.skip_animations = True
skip_due_to_cache = True
self.time += scene.duration
# adding None as a partial movie file will make file_writer ignore the latter.
self.file_writer.add_partial_movie_file(hash_current_animation)
Expand All @@ -121,6 +123,9 @@ def play(
self.file_writer.end_animation(not self.skip_animations)

self.num_plays += 1
if skip_due_to_cache:
self.skip_animations = self._original_skipping_status
self.update_skipping_status()

def update_frame( # TODO Description in Docstring
self,
Expand Down
5 changes: 5 additions & 0 deletions manim/utils/caching.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def handle_caching_play(func: Callable[..., None]) -> Callable[..., None]:
def wrapper(self: OpenGLRenderer, scene: Scene, *args: Any, **kwargs: Any) -> None:
self.skip_animations = self._original_skipping_status
self.update_skipping_status()
skip_due_to_cache = False
animations = scene.compile_animations(*args, **kwargs)
scene.add_mobjects_from_animations(animations)
if self.skip_animations:
Expand All @@ -60,6 +61,7 @@ def wrapper(self: OpenGLRenderer, scene: Scene, *args: Any, **kwargs: Any) -> No
{"hash_play": hash_play},
)
self.skip_animations = True
skip_due_to_cache = True
else:
hash_play = f"uncached_{self.num_plays:05}"
self.animations_hashes.append(hash_play)
Expand All @@ -69,5 +71,8 @@ def wrapper(self: OpenGLRenderer, scene: Scene, *args: Any, **kwargs: Any) -> No
{"h": str(self.animations_hashes[:5])},
)
func(self, scene, *args, **kwargs)
if skip_due_to_cache:
self.skip_animations = self._original_skipping_status
self.update_skipping_status()

return wrapper
29 changes: 28 additions & 1 deletion tests/module/scene/test_sound.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import wave
from pathlib import Path

from manim import Scene
from manim import Scene, tempconfig


def test_add_sound(tmpdir):
Expand All @@ -19,3 +19,30 @@ def test_add_sound(tmpdir):

scene = Scene()
scene.add_sound(sound_loc)


def test_add_sound_after_cached_wait(tmpdir):
"""Regression test for https://github.com/ManimCommunity/manim/issues/4751."""
sound_loc = Path(tmpdir, "noise.wav")
with wave.open(str(sound_loc), "w") as f:
f.setparams((1, 2, 44100, 0, "NONE", "not compressed"))
for _ in range(4410):
f.writeframes(struct.pack("h", 1000))

sounds_recorded: list[int] = []

class AudioAfterSilenceScene(Scene):
def construct(self):
self.add_sound(str(sound_loc))
self.wait(0.2)
self.wait(0.2)
self.add_sound(str(sound_loc))
sounds_recorded.append(len(self.renderer.file_writer.audio_segment))

with tempconfig({"media_dir": str(tmpdir), "disable_caching": False}):
AudioAfterSilenceScene().render()
AudioAfterSilenceScene().render()

assert len(sounds_recorded) == 2
assert sounds_recorded[0] > 0
assert sounds_recorded[1] == sounds_recorded[0]
Loading