diff --git a/CHANGELOG.md b/CHANGELOG.md index a076a45..0a799d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Modified the internal logic to simplify adding configuration options. [#321](https://github.com/jeertmans/manim-slides/pull/321) +(v5.1-chore)= +### Chore + +- Removed subrocess calls to FFMPEG with direct `libav` bindings using + the `av` Python module. This should enhance rendering speed and security. + [#335](https://github.com/jeertmans/manim-slides/pull/335) + ## [v5](https://github.com/jeertmans/manim-slides/compare/v4.16.0...v5.0.0) Prior to v5, there was no real CHANGELOG other than the GitHub releases, diff --git a/manim_slides/defaults.py b/manim_slides/defaults.py index 65ccdd6..33e07b7 100644 --- a/manim_slides/defaults.py +++ b/manim_slides/defaults.py @@ -2,4 +2,3 @@ from pathlib import Path FOLDER_PATH: Path = Path("./slides") CONFIG_PATH: Path = Path(".manim-slides.toml") -FFMPEG_BIN: Path = Path("ffmpeg") diff --git a/manim_slides/logger.py b/manim_slides/logger.py index d0203b9..877b5ba 100644 --- a/manim_slides/logger.py +++ b/manim_slides/logger.py @@ -41,6 +41,9 @@ def make_logger() -> logging.Logger: logger.setLevel(logging.getLogger("manim").level) logger.addHandler(rich_handler) + if not (libav_logger := logging.getLogger("libav")).hasHandlers(): + libav_logger.addHandler(rich_handler) + return logger diff --git a/manim_slides/slide/base.py b/manim_slides/slide/base.py index 8583d2a..e7fd33b 100644 --- a/manim_slides/slide/base.py +++ b/manim_slides/slide/base.py @@ -17,7 +17,7 @@ import numpy as np from tqdm import tqdm from ..config import BaseSlideConfig, PresentationConfig, PreSlideConfig, SlideConfig -from ..defaults import FFMPEG_BIN, FOLDER_PATH +from ..defaults import FOLDER_PATH from ..logger import logger from ..utils import concatenate_video_files, merge_basenames, reverse_video_file from . import MANIM @@ -47,11 +47,6 @@ class BaseSlide: self._canvas: MutableMapping[str, Mobject] = {} self._wait_time_between_slides = 0.0 - @property - def _ffmpeg_bin(self) -> Path: - """Return the path to the ffmpeg binaries.""" - return FFMPEG_BIN - @property @abstractmethod def _frame_height(self) -> float: @@ -492,11 +487,11 @@ class BaseSlide: # We only concat animations if it was not present if not use_cache or not dst_file.exists(): - concatenate_video_files(self._ffmpeg_bin, slide_files, dst_file) + concatenate_video_files(slide_files, dst_file) # We only reverse video if it was not present if not use_cache or not rev_file.exists(): - reverse_video_file(self._ffmpeg_bin, dst_file, rev_file) + reverse_video_file(dst_file, rev_file) slides.append( SlideConfig.from_pre_slide_config_and_files( diff --git a/manim_slides/slide/manim.py b/manim_slides/slide/manim.py index eb9677a..d8e2b4f 100644 --- a/manim_slides/slide/manim.py +++ b/manim_slides/slide/manim.py @@ -13,15 +13,6 @@ class Slide(BaseSlide, Scene): # type: ignore[misc] for slides rendering. """ - @property - def _ffmpeg_bin(self) -> Path: - # Prior to v0.16.0.post0, - # ffmpeg was stored as a constant in manim.constants - try: - return Path(config.ffmpeg_executable) - except AttributeError: - return super()._ffmpeg_bin - @property def _frame_height(self) -> float: return config["frame_height"] # type: ignore diff --git a/manim_slides/utils.py b/manim_slides/utils.py index c575308..49e79fa 100644 --- a/manim_slides/utils.py +++ b/manim_slides/utils.py @@ -1,45 +1,37 @@ import hashlib -import subprocess import tempfile from pathlib import Path from typing import List +import av + from .logger import logger -def concatenate_video_files(ffmpeg_bin: Path, files: List[Path], dest: Path) -> None: +def concatenate_video_files(files: List[Path], dest: Path) -> None: """Concatenate multiple video files into one.""" f = tempfile.NamedTemporaryFile(mode="w", delete=False) f.writelines(f"file '{path.absolute()}'\n" for path in files) f.close() - command: List[str] = [ - str(ffmpeg_bin), - "-f", - "concat", - "-safe", - "0", - "-i", - f.name, - "-c", - "copy", - str(dest), - "-y", - ] - logger.debug(" ".join(command)) - process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - output, error = process.communicate() + input_ = av.open(f.name, options={"safe": "0"}, format="concat") + input_stream = input_.streams.video[0] + output = av.open(str(dest), mode="w") + output_stream = output.add_stream( + template=input_stream, + ) - if output: - logger.debug(output.decode()) + for packet in input_.demux(input_stream): + # We need to skip the "flushing" packets that `demux` generates. + if packet.dts is None: + continue - if error: - logger.debug(error.decode()) + # We need to assign the packet to the new stream. + packet.stream = output_stream + output.mux(packet) - if not dest.exists(): - raise ValueError( - "could not properly concatenate files, use `-v DEBUG` for more details" - ) + input_.close() + output.close() def merge_basenames(files: List[Path]) -> Path: @@ -63,15 +55,44 @@ def merge_basenames(files: List[Path]) -> Path: return dirname.joinpath(basename + ext) -def reverse_video_file(ffmpeg_bin: Path, src: Path, dst: Path) -> None: - """Reverses a video file, writting the result to `dst`.""" - command = [str(ffmpeg_bin), "-y", "-i", str(src), "-vf", "reverse", str(dst)] - logger.debug(" ".join(command)) - process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - output, error = process.communicate() +def link_nodes(*nodes: av.filter.context.FilterContext) -> None: + """Code from https://github.com/PyAV-Org/PyAV/issues/239.""" + for c, n in zip(nodes, nodes[1:]): + c.link_to(n) - if output: - logger.debug(output.decode()) - if error: - logger.debug(error.decode()) +def reverse_video_file(src: Path, dest: Path) -> None: + """Reverses a video file, writting the result to `dest`.""" + input_ = av.open(str(src)) + input_stream = input_.streams.video[0] + output = av.open(str(dest), mode="w") + output_stream = output.add_stream(codec_name="libx264", rate=input_stream.base_rate) + output_stream.width = input_stream.width + output_stream.height = input_stream.height + output_stream.pix_fmt = input_stream.pix_fmt + + graph = av.filter.Graph() + link_nodes( + graph.add_buffer(template=input_stream), + graph.add("reverse"), + graph.add("buffersink"), + ) + graph.configure() + + frames_count = 0 + for frame in input_.decode(video=0): + graph.push(frame) + frames_count += 1 + + graph.push(None) # EOF: https://github.com/PyAV-Org/PyAV/issues/886. + + for i in range(frames_count): + frame = graph.pull() + frame.pict_type = 1 # Otherwise we get a warning saying it is changed + output.mux(output_stream.encode(frame)) + + for packet in output_stream.encode(): + output.mux(packet) + + input_.close() + output.close() diff --git a/poetry.lock b/poetry.lock index ca2bacc..1cfd7fd 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. [[package]] name = "alabaster" @@ -71,6 +71,60 @@ docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib- tests = ["attrs[tests-no-zope]", "zope-interface"] tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +[[package]] +name = "av" +version = "11.0.0" +description = "Pythonic bindings for FFmpeg's libraries." +optional = false +python-versions = ">=3.8" +files = [ + {file = "av-11.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a01f13b37eb6d181e03bbbbda29093fe2d68f10755795188220acdc89560ec27"}, + {file = "av-11.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b2236faee1b5d71dff3cdef81ef6eec22cc8b71dbfb45eb037e6437fe80f24e7"}, + {file = "av-11.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40543a08e5c84aecd2bc84da5d43548743201897f0ba21bf5ae3a4dcddefca2b"}, + {file = "av-11.0.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2907376884d956376aaf3bc1905fa4e0dcb9ba4e0d183e519392a19d89317d1b"}, + {file = "av-11.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8d5581dcdc81cd601e3ce036809f14da82c46ff187bcefe981ec819390e0ab0"}, + {file = "av-11.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:150490f2a62cfa470f3cb60f3a0060ff93afd807e2b7b3b0eeeb5a992eb8d67b"}, + {file = "av-11.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d9bac0de62f09e2cb4e2132b5a46a89bc31c898189aa285b484c17351d991afe"}, + {file = "av-11.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2122ff8bdace4ce50207920f37de472517921e2ca1f0503464f748fdb8e20506"}, + {file = "av-11.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:527d840697fee6ad4cf47eba987eaf30cd76bd96b2d20eaa907e166b9b8065c8"}, + {file = "av-11.0.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abeaedddfca9101886eb6fc47318c5f5ece8480d330d73aacf6917d7421981a2"}, + {file = "av-11.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13790fbb889b955baf885fe3761e923e85537ef414173465ec293177cedb7b99"}, + {file = "av-11.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:fc27e27f52480287f44226ad4ae3eb53346bf027959d0f00a9154530bd98b371"}, + {file = "av-11.0.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:892583e2c6b8c2500e5d24310f499caefcdaa2e48c8f7169ad41041aaaf4da11"}, + {file = "av-11.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6943679d70a9f4de974049e7ae2cf0b20afe0d7ddab650526c02a6cf9adcd08f"}, + {file = "av-11.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6d73b038ccf1df5c16bc643eee5c694fb7732e09375e2f4903c1f4ce90dfb72"}, + {file = "av-11.0.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c83422db3333e97b9680700df5185139352fc3a568b14179da3bdcbeb2f0e91b"}, + {file = "av-11.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8413900f6a3639e0088c018a3a516a1656d4d16799e7aa759a16ddf3bd268e2b"}, + {file = "av-11.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:908e49ee336223801d8f2f7dca5a1deb64e9d8256138b8e7a79013b682a6ebb5"}, + {file = "av-11.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:82411ae4a562da07b76028d2f349fb0e6a86aa78ad2b18d2d7bf5b06b17fba14"}, + {file = "av-11.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:621104bd63e38fa4eca554da3722b1aac329619de39152f27eec8999acc72342"}, + {file = "av-11.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:442878990c094455a16c10127edcc54bc4e78d355e6a13ad2a27608b0ecda38f"}, + {file = "av-11.0.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:658199c92987dc72511f5ee8ade62faef6234b7a04c8b5788de99e366be5e073"}, + {file = "av-11.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad4b381665c49267b46f87297573898b85e5c41384750fee2e70267fbc4ba318"}, + {file = "av-11.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:60de14f71293e36ca4e297cc8a8460f0cf74f38a201694f3c6fc7f40301582f2"}, + {file = "av-11.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a90f04af96374dab94028a7471597bdfcf03083338b9be2eb8ca4805a8ec7ab5"}, + {file = "av-11.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8821ab2d23e4cb5c8abea6b08d2b1bfceca6af2d88fab1d1dc1b3ec7b34933c7"}, + {file = "av-11.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a92342ed307eeaf9509a6b0f3bafd4337c4880c851b50acc18df48c625b63b6"}, + {file = "av-11.0.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbe3502975bc844f5d432c1f24d331bf6ef3e05532ebf06f7ed08b60719b8ea5"}, + {file = "av-11.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c278b3a4fd111b4c9190abe6b1a5ca358d5f91e851d470b62577b957e0187b09"}, + {file = "av-11.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:478aa1d54fbc3058ea65ff41086b6adbe1326b456a027d2f3b59dbe60b4ac2ca"}, + {file = "av-11.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e8df10bb2d56a981d02a8a0b41491912b76dad06305d174a2575ef55ad451100"}, + {file = "av-11.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b30c51e597785a89241bd61865faff2dbd3327856a8285a1e120dbf60e18348b"}, + {file = "av-11.0.0-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a8b8bd92edb096699b306e7b090ad096925ca3bdae6f89656f023fa2a2da627d"}, + {file = "av-11.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9383af733abfc44f6fc29307a6c922fbf671ee343dc97b78b74eac6a2346a46d"}, + {file = "av-11.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a9df4a60579198b560f641cdfe4c2139948a70193ddc096b275f2cf6d94e3e04"}, + {file = "av-11.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8ae5f7ae0a7093fb813686d4aa4c554531f80a28480427f5c155da51b747eff0"}, + {file = "av-11.0.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50fb7d606f8236891d773c701d5650b93af8dbf78eeaac36fc7e1f7f64a9d664"}, + {file = "av-11.0.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:543e0f9bf6ff02dedbe66d906fbc89c8907c80a8ea7413fc3fed68ce4a6e9b44"}, + {file = "av-11.0.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:daa279c884457ab194ce78bdd89c0aa391af733da95fb3258d4c6eb8c258299a"}, + {file = "av-11.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1aacc21f4cf96447117a61edfb776afb73186750a5e08a21484ddfc3599aefb5"}, + {file = "av-11.0.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2568b38eef777b916a5d02e42b8f67f92e12023531239ddd32e1ca4f3cdf8c5b"}, + {file = "av-11.0.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:747c6d347e27c59cc2e78c9c505d23cd88eceff0cc9386be73693ae9009a577c"}, + {file = "av-11.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4bbd8f4941b9d3450eff40003b9b9d904667aec7ab085fa31f0f9bca32d755e0"}, + {file = "av-11.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f39c1244ba0cf185b2722aeec116b8a98a2ee5728ce687cec0bda60ee0360dfc"}, + {file = "av-11.0.0.tar.gz", hash = "sha256:48223f000a252070f8e700ff634bb7fb3aa1b7bc7e450373029fbdd6f369ac31"}, +] + [[package]] name = "babel" version = "2.13.0" @@ -1688,16 +1742,6 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -3043,7 +3087,6 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -3051,15 +3094,8 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -3076,7 +3112,6 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -3084,7 +3119,6 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -4106,4 +4140,4 @@ sphinx-directive = ["docutils", "manim"] [metadata] lock-version = "2.0" python-versions = ">=3.8.1,<3.12" -content-hash = "ceecfed388896985beb4023adae6b9815e2c82103f9cb79a546c3b906860120b" +content-hash = "dc4521c1e0540008ccefc4acc5d842de85d92eb77b34a455a3d223e6ca7940e1" diff --git a/pyproject.toml b/pyproject.toml index 6bf4b69..66016eb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,6 +42,7 @@ repository = "https://github.com/jeertmans/manim-slides" version = "5.1.0-rc2" [tool.poetry.dependencies] +av = ">=9.0.0" click = "^8.1.3" click-default-group = "^1.2.2" docutils = {version = "^0.20.1", optional = true} diff --git a/test_assets/49d7b9453bdd459c0f7582859468b845a0abd7fd15637246ec1914c5c21ee33a.mp4 b/test_assets/49d7b9453bdd459c0f7582859468b845a0abd7fd15637246ec1914c5c21ee33a.mp4 deleted file mode 100644 index 561e09c..0000000 Binary files a/test_assets/49d7b9453bdd459c0f7582859468b845a0abd7fd15637246ec1914c5c21ee33a.mp4 and /dev/null differ diff --git a/test_assets/49d7b9453bdd459c0f7582859468b845a0abd7fd15637246ec1914c5c21ee33a_reversed.mp4 b/test_assets/49d7b9453bdd459c0f7582859468b845a0abd7fd15637246ec1914c5c21ee33a_reversed.mp4 deleted file mode 100644 index 2085330..0000000 Binary files a/test_assets/49d7b9453bdd459c0f7582859468b845a0abd7fd15637246ec1914c5c21ee33a_reversed.mp4 and /dev/null differ diff --git a/test_assets/666c4d3666df4cdb49aaba030b166948270194eee96f1a10eedf33ef7d3c9a7b.mp4 b/test_assets/666c4d3666df4cdb49aaba030b166948270194eee96f1a10eedf33ef7d3c9a7b.mp4 deleted file mode 100644 index d3713c5..0000000 Binary files a/test_assets/666c4d3666df4cdb49aaba030b166948270194eee96f1a10eedf33ef7d3c9a7b.mp4 and /dev/null differ diff --git a/test_assets/666c4d3666df4cdb49aaba030b166948270194eee96f1a10eedf33ef7d3c9a7b_reversed.mp4 b/test_assets/666c4d3666df4cdb49aaba030b166948270194eee96f1a10eedf33ef7d3c9a7b_reversed.mp4 deleted file mode 100644 index 4af8344..0000000 Binary files a/test_assets/666c4d3666df4cdb49aaba030b166948270194eee96f1a10eedf33ef7d3c9a7b_reversed.mp4 and /dev/null differ diff --git a/test_assets/72568c120827bbf8c69201ee416c5bab6f875f1600889d2ee765346bb576887d.mp4 b/test_assets/72568c120827bbf8c69201ee416c5bab6f875f1600889d2ee765346bb576887d.mp4 deleted file mode 100644 index 5d179a9..0000000 Binary files a/test_assets/72568c120827bbf8c69201ee416c5bab6f875f1600889d2ee765346bb576887d.mp4 and /dev/null differ diff --git a/test_assets/72568c120827bbf8c69201ee416c5bab6f875f1600889d2ee765346bb576887d_reversed.mp4 b/test_assets/72568c120827bbf8c69201ee416c5bab6f875f1600889d2ee765346bb576887d_reversed.mp4 deleted file mode 100644 index 5954f46..0000000 Binary files a/test_assets/72568c120827bbf8c69201ee416c5bab6f875f1600889d2ee765346bb576887d_reversed.mp4 and /dev/null differ diff --git a/tests/test_base_slide.py b/tests/test_base_slide.py index afe4bf8..a050042 100644 --- a/tests/test_base_slide.py +++ b/tests/test_base_slide.py @@ -2,7 +2,6 @@ from typing import MutableMapping import pytest -from manim_slides.defaults import FFMPEG_BIN from manim_slides.slide.base import BaseSlide @@ -12,9 +11,6 @@ def base_slide() -> BaseSlide: class TestBaseSlide: - def test_ffmpeg_bin(self, base_slide: BaseSlide) -> None: - assert base_slide._ffmpeg_bin == FFMPEG_BIN - def test_frame_height(self, base_slide: BaseSlide) -> None: with pytest.raises(NotImplementedError): _ = base_slide._frame_height diff --git a/tests/test_defaults.py b/tests/test_defaults.py index 649972b..8c65570 100644 --- a/tests/test_defaults.py +++ b/tests/test_defaults.py @@ -1,7 +1,6 @@ -import shutil from pathlib import Path -from manim_slides.defaults import CONFIG_PATH, FFMPEG_BIN, FOLDER_PATH +from manim_slides.defaults import CONFIG_PATH, FOLDER_PATH def test_folder_path() -> None: @@ -10,13 +9,3 @@ def test_folder_path() -> None: def test_config_path() -> None: assert CONFIG_PATH == Path(".manim-slides.toml") - - -def test_ffmpeg_bin() -> None: - assert FFMPEG_BIN == Path("ffmpeg") - - -def test_ffmpeg_bin_exists() -> None: - assert ( - shutil.which(str(FFMPEG_BIN)) is not None - ), "If this fails, many other tests will fail"