mirror of
https://github.com/jeertmans/manim-slides.git
synced 2025-06-29 19:28:30 +08:00
feat(lib): add playback rate config options (#320)
* feat(lib): add playback rate config options Basic playback rate config options, closes #309 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
@ -18,6 +18,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Added the `manim-slides render` command
|
||||
to render slides using correct Manim installation.
|
||||
[#317](https://github.com/jeertmans/manim-slides/pull/317)
|
||||
- Added the `playback-rate` and `reversed-playback-rate` options
|
||||
to slide config.
|
||||
[#320](https://github.com/jeertmans/manim-slides/pull/320)
|
||||
|
||||
## [v5](https://github.com/jeertmans/manim-slides/compare/v4.16.0...v5.0.0)
|
||||
|
||||
|
@ -34,9 +34,7 @@ def cli(notify_outdated_version: bool) -> None:
|
||||
manim_info_url = "https://pypi.org/pypi/manim-slides/json"
|
||||
warn_prompt = "Cannot check if latest release of Manim Slides is installed"
|
||||
try:
|
||||
req_info: requests.models.Response = requests.get(
|
||||
manim_info_url, timeout=2
|
||||
)
|
||||
req_info: requests.models.Response = requests.get(manim_info_url, timeout=2)
|
||||
req_info.raise_for_status()
|
||||
stable = req_info.json()["info"]["version"]
|
||||
if stable != __version__:
|
||||
|
@ -140,6 +140,8 @@ class PreSlideConfig(BaseModel): # type: ignore
|
||||
end_animation: int
|
||||
loop: bool = False
|
||||
auto_next: bool = False
|
||||
playback_rate: float = 1.0
|
||||
reversed_playback_rate: float = 1.0
|
||||
|
||||
@field_validator("start_animation", "end_animation")
|
||||
@classmethod
|
||||
@ -190,6 +192,8 @@ class SlideConfig(BaseModel): # type: ignore[misc]
|
||||
rev_file: FilePath
|
||||
loop: bool = False
|
||||
auto_next: bool = False
|
||||
playback_rate: float = 1.0
|
||||
reversed_playback_rate: float = 1.0
|
||||
|
||||
@classmethod
|
||||
def from_pre_slide_config_and_files(
|
||||
@ -200,6 +204,8 @@ class SlideConfig(BaseModel): # type: ignore[misc]
|
||||
rev_file=rev_file,
|
||||
loop=pre_slide_config.loop,
|
||||
auto_next=pre_slide_config.auto_next,
|
||||
playback_rate=pre_slide_config.playback_rate,
|
||||
reversed_playback_rate=pre_slide_config.reversed_playback_rate,
|
||||
)
|
||||
|
||||
|
||||
|
@ -236,6 +236,13 @@ class Player(QMainWindow): # type: ignore[misc]
|
||||
url = QUrl.fromLocalFile(self.current_file)
|
||||
self.media_player.setSource(url)
|
||||
|
||||
if self.playing_reversed_slide:
|
||||
self.media_player.setPlaybackRate(
|
||||
self.current_slide_config.reversed_playback_rate
|
||||
)
|
||||
else:
|
||||
self.media_player.setPlaybackRate(self.current_slide_config.playback_rate)
|
||||
|
||||
if start_paused:
|
||||
self.media_player.pause()
|
||||
else:
|
||||
|
@ -255,7 +255,13 @@ class BaseSlide:
|
||||
self._current_animation += 1
|
||||
|
||||
def next_slide(
|
||||
self, *, loop: bool = False, auto_next: bool = False, **kwargs: Any
|
||||
self,
|
||||
*,
|
||||
loop: bool = False,
|
||||
auto_next: bool = False,
|
||||
playback_rate: float = 1.0,
|
||||
reversed_playback_rate: float = 1.0,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
"""
|
||||
Create a new slide with previous animations, and setup options
|
||||
@ -276,6 +282,14 @@ class BaseSlide:
|
||||
|
||||
Note that this is only supported by ``manim-slides present``
|
||||
and ``manim-slides convert --to=html``.
|
||||
:param playback_rate:
|
||||
Playback rate at which the video is played.
|
||||
|
||||
Note that this is only supported by ``manim-slides present``.
|
||||
:param reversed_playback_rate:
|
||||
Playback rate at which the reversed video is played.
|
||||
|
||||
Note that this is only supported by ``manim-slides present``.
|
||||
:param kwargs:
|
||||
Keyword arguments to be passed to
|
||||
:meth:`Scene.next_section<manim.scene.scene.Scene.next_section>`,
|
||||
@ -375,7 +389,12 @@ class BaseSlide:
|
||||
|
||||
self._current_slide += 1
|
||||
|
||||
self._pre_slide_config_kwargs = dict(loop=loop, auto_next=auto_next)
|
||||
self._pre_slide_config_kwargs = dict(
|
||||
loop=loop,
|
||||
auto_next=auto_next,
|
||||
playback_rate=playback_rate,
|
||||
reversed_playback_rate=reversed_playback_rate,
|
||||
)
|
||||
self._start_animation = self._current_animation
|
||||
|
||||
def _add_last_slide(self) -> None:
|
||||
|
@ -80,10 +80,22 @@ class Slide(BaseSlide, Scene): # type: ignore[misc]
|
||||
self.next_slide(*args, **kwargs)
|
||||
|
||||
def next_slide(
|
||||
self, *args: Any, loop: bool = False, auto_next: bool = False, **kwargs: Any
|
||||
self,
|
||||
*args: Any,
|
||||
loop: bool = False,
|
||||
auto_next: bool = False,
|
||||
playback_rate: float = 1.0,
|
||||
reversed_playback_rate: float = 1.0,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
Scene.next_section(self, *args, **kwargs)
|
||||
BaseSlide.next_slide(self, loop=loop, auto_next=auto_next)
|
||||
BaseSlide.next_slide(
|
||||
self,
|
||||
loop=loop,
|
||||
auto_next=auto_next,
|
||||
playback_rate=playback_rate,
|
||||
reversed_playback_rate=reversed_playback_rate,
|
||||
)
|
||||
|
||||
def render(self, *args: Any, **kwargs: Any) -> None:
|
||||
"""MANIM render."""
|
||||
|
@ -182,6 +182,20 @@ class TestSlide:
|
||||
with pytest.raises(ValidationError):
|
||||
self.next_slide()
|
||||
|
||||
@assert_constructs
|
||||
class TestPlaybackRate(Slide):
|
||||
def construct(self) -> None:
|
||||
text = Text("Some text")
|
||||
|
||||
self.add(text)
|
||||
|
||||
assert "playback_rate" not in self._pre_slide_config_kwargs
|
||||
|
||||
self.next_slide(playback_rate=2.0)
|
||||
self.play(text.animate.scale(2))
|
||||
|
||||
assert self._pre_slide_config_kwargs["playback_rate"] == 2.0
|
||||
|
||||
@assert_constructs
|
||||
class TestWipe(Slide):
|
||||
def construct(self) -> None:
|
||||
|
Reference in New Issue
Block a user