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:
Jérome Eertmans
2023-11-23 12:26:25 +01:00
committed by GitHub
parent 1f0c94dc5c
commit eb8efa8e3d
7 changed files with 66 additions and 7 deletions

View File

@ -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)

View File

@ -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__:

View File

@ -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,
)

View File

@ -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:

View File

@ -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:

View File

@ -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."""

View File

@ -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: