mirror of
https://github.com/jeertmans/manim-slides.git
synced 2025-05-19 11:36:37 +08:00
Compare commits
29 Commits
Author | SHA1 | Date | |
---|---|---|---|
8096636cf1 | |||
c7e38bfb38 | |||
421cad3038 | |||
9edf23856c | |||
62236f5796 | |||
1e28d70c0e | |||
6a96b3ab8c | |||
a1c041db80 | |||
4fd3452f95 | |||
ff2be6851b | |||
95289ee7a5 | |||
f1a026208a | |||
b3fd1d209e | |||
8c38db0989 | |||
6da0c36c96 | |||
3b01efa601 | |||
c9ef5e9a75 | |||
bfad43bd38 | |||
6f2cbc9b19 | |||
5bd88c2fd5 | |||
f0c17b1e2a | |||
fce9546a9b | |||
d6ad56120e | |||
5db0261b01 | |||
8ab33ef71f | |||
4da0e2cc2d | |||
0e82e28313 | |||
8b13106fcc | |||
bce4d8188f |
@ -1,5 +1,5 @@
|
||||
[bumpversion]
|
||||
current_version = 4.12.0
|
||||
current_version = 4.14.0
|
||||
commit = True
|
||||
message = chore(version): bump {current_version} to {new_version}
|
||||
|
||||
|
13
.github/dependabot.yml
vendored
Normal file
13
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: github-actions
|
||||
directory: /
|
||||
schedule:
|
||||
interval: daily
|
||||
labels:
|
||||
- dependencies
|
18
.github/workflows/pages.yml
vendored
18
.github/workflows/pages.yml
vendored
@ -46,22 +46,24 @@ jobs:
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install libcairo2-dev libpango1.0-dev ffmpeg freeglut3-dev
|
||||
- name: Install Python dependencies
|
||||
run: pip install manim sphinx sphinx_click furo
|
||||
- name: Install local Python package
|
||||
run: poetry install --with docs
|
||||
run: poetry install --extras=manim --with docs
|
||||
- name: Restore cached media
|
||||
id: cache-media-restore
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: media
|
||||
key: ${{ runner.os }}-media
|
||||
- name: Build animation and convert it into HTML slides
|
||||
- name: Build animations
|
||||
run: |
|
||||
poetry run manim example.py ConvertExample BasicExample ThreeDExample
|
||||
poetry run manim-slides convert ConvertExample docs/source/_static/slides.html -ccontrols=true
|
||||
poetry run manim-slides convert BasicExample docs/source/_static/basic_example.html -ccontrols=true
|
||||
poetry run manim-slides convert ThreeDExample docs/source/_static/three_d_example.html -ccontrols=true
|
||||
- name: Convert animations to HTML slides
|
||||
run: |
|
||||
poetry run manim-slides convert -v DEBUG ConvertExample docs/source/_static/slides.html -ccontrols=true
|
||||
poetry run manim-slides convert -v DEBUG BasicExample docs/source/_static/basic_example.html -ccontrols=true
|
||||
poetry run manim-slides convert -v DEBUG ThreeDExample docs/source/_static/three_d_example.html -ccontrols=true
|
||||
- name: Show docs/source/_static/ dir content (video only)
|
||||
run: tree -L 3 docs/source/_static/ -P '*.mp4'
|
||||
- name: Clear cache
|
||||
run: |
|
||||
gh extension install actions/gh-actions-cache
|
||||
@ -82,6 +84,8 @@ jobs:
|
||||
with:
|
||||
# Upload docs/build/html dir
|
||||
path: docs/build/html/
|
||||
- name: Show docs/build/html/_static/ dir content (video only)
|
||||
run: tree -L 3 docs/build/html/_static/ -P '*.mp4'
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
if: github.event_name != 'pull_request'
|
||||
|
50
.github/workflows/python-publish.yml
vendored
50
.github/workflows/python-publish.yml
vendored
@ -1,4 +1,3 @@
|
||||
# Modified from: https://github.com/pypa/cibuildwheel
|
||||
name: Upload Python Package
|
||||
|
||||
on:
|
||||
@ -8,41 +7,28 @@ on:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
build_wheels:
|
||||
name: Build wheels on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
build_and_release:
|
||||
name: Build and release
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-python@v2
|
||||
- name: Install Poetry
|
||||
run: pipx install poetry
|
||||
|
||||
- name: Install build package
|
||||
run: python -m pip install -U build
|
||||
- name: Install Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.10'
|
||||
cache: poetry
|
||||
|
||||
- name: Build wheels
|
||||
run: python -m build --sdist
|
||||
run: poetry build
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: dist
|
||||
path: dist/*.tar.*
|
||||
|
||||
release:
|
||||
name: Release
|
||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build_wheels]
|
||||
steps:
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: dist
|
||||
path: dist/
|
||||
- name: Upload to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@master
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||
- name: Publish to PyPI
|
||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
|
||||
env:
|
||||
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_API_TOKEN }}
|
||||
run: poetry publish
|
||||
|
3
.github/workflows/test_examples.yml
vendored
3
.github/workflows/test_examples.yml
vendored
@ -1,6 +1,8 @@
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- pyproject.toml
|
||||
- poetry.lock
|
||||
- '**.py'
|
||||
- .github/workflows/test_examples.yml
|
||||
workflow_dispatch:
|
||||
@ -97,7 +99,6 @@ jobs:
|
||||
# Install Manim Slides
|
||||
- name: Install Manim Slides
|
||||
run: |
|
||||
poetry config experimental.new-installer false
|
||||
poetry install --with test
|
||||
|
||||
# Render slides
|
||||
|
@ -12,7 +12,7 @@ repos:
|
||||
- id: isort
|
||||
name: isort (python)
|
||||
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
|
||||
rev: v2.8.0
|
||||
rev: v2.9.0
|
||||
hooks:
|
||||
- id: pretty-format-yaml
|
||||
args: [--autofix]
|
||||
@ -24,11 +24,11 @@ repos:
|
||||
hooks:
|
||||
- id: black
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.0.260
|
||||
rev: v0.0.270
|
||||
hooks:
|
||||
- id: ruff
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v1.1.1
|
||||
rev: v1.3.0
|
||||
hooks:
|
||||
- id: mypy
|
||||
additional_dependencies: [types-requests, types-setuptools]
|
||||
|
66
README.md
66
README.md
@ -8,6 +8,8 @@
|
||||
[![Python version][pypi-python-version-badge]][pypi-version-url]
|
||||
[![PyPI - Downloads][pypi-download-badge]][pypi-version-url]
|
||||
[![Documentation][documentation-badge]][documentation-url]
|
||||
[![DOI][doi-badge]][doi-url]
|
||||
|
||||
# Manim Slides
|
||||
|
||||
Tool for live presentations using either [Manim (community edition)](https://www.manim.community/) or [ManimGL](https://3b1b.github.io/manim/). Manim Slides will *automatically* detect the one you are using!
|
||||
@ -27,6 +29,9 @@ Tool for live presentations using either [Manim (community edition)](https://www
|
||||
- [F.A.Q](#faq)
|
||||
* [How to increase quality on Windows](#how-to-increase-quality-on-windows)
|
||||
- [Contributing](#contributing)
|
||||
* [Reporting an Issue](#reporting-an-issue)
|
||||
* [Seeking for Help](#seeking-for-help)
|
||||
* [Contact](#contact)
|
||||
|
||||
## Installation
|
||||
|
||||
@ -54,6 +59,16 @@ The recommended way to install the latest release is to use pip:
|
||||
pip install manim-slides
|
||||
```
|
||||
|
||||
Optionally, you can also install Manim or ManimGL using extras[^1]:
|
||||
|
||||
```bash
|
||||
pip install manim-slides[manim] # For Manim
|
||||
# or
|
||||
pip install manim-slides[manimgl] # For ManimGL
|
||||
```
|
||||
|
||||
[^1]: NOTE: you still need to have Manim or ManimGL platform-specific dependencies installed on your computer.
|
||||
|
||||
### Install From Repository
|
||||
|
||||
An alternative way to install Manim Slides is to clone the git repository, and install from there: read the [contributing guide](https://eertmans.be/manim-slides/contributing/workflow.html) to know how.
|
||||
@ -190,9 +205,60 @@ in *Settings*->*Display*.
|
||||
|
||||
Contributions are more than welcome! Please read through [our contributing section](https://eertmans.be/manim-slides/contributing/index.html).
|
||||
|
||||
### Reporting an Issue
|
||||
|
||||
<!-- start reporting-an-issue -->
|
||||
|
||||
If you think you found a bug,
|
||||
an error in the documentation,
|
||||
or wish there was some feature that is currently missing,
|
||||
we would love to hear from you!
|
||||
|
||||
The best way to reach us is via the
|
||||
[GitHub issues](https://github.com/jeertmans/manim-slides/issues).
|
||||
If your problem is not covered by an already existing (closed or open) issue,
|
||||
then we suggest you create a
|
||||
[new issue](https://github.com/jeertmans/manim-slides/issues/new/choose).
|
||||
You can choose from a list of templates, or open a
|
||||
[blank issue](https://github.com/jeertmans/manim-slides/issues/new)
|
||||
if your issue does not fit one of the proposed topics.
|
||||
|
||||
The more precise you are in the description of your problem, the faster we will
|
||||
be able to help you!
|
||||
|
||||
<!-- end reporting-an-issue -->
|
||||
|
||||
### Seeking for help
|
||||
|
||||
<!-- start seeking-for-help -->
|
||||
|
||||
Sometimes, you may have a question about Manim Slides,
|
||||
not necessarily an issue.
|
||||
|
||||
There are two ways you can reach us for questions:
|
||||
|
||||
- via the `Question/Help/Support` topic when
|
||||
[choosing an issue template](https://github.com/jeertmans/manim-slides/issues/new/choose);
|
||||
- or via
|
||||
[GitHub discussions](https://github.com/jeertmans/manim-slides/discussions).
|
||||
|
||||
<!-- end seeking-for-help -->
|
||||
|
||||
### Contact
|
||||
|
||||
<!-- start contact -->
|
||||
|
||||
Finally, if you do not have any GitHub account,
|
||||
or just wish to contact the author of Manim Slides,
|
||||
you can do so at: [jeertmans@icloud.com](mailto:jeertmans@icloud.com).
|
||||
|
||||
<!-- end contact -->
|
||||
|
||||
[pypi-version-badge]: https://img.shields.io/pypi/v/manim-slides?label=manim-slides
|
||||
[pypi-version-url]: https://pypi.org/project/manim-slides/
|
||||
[pypi-python-version-badge]: https://img.shields.io/pypi/pyversions/manim-slides
|
||||
[pypi-download-badge]: https://img.shields.io/pypi/dm/manim-slides
|
||||
[documentation-badge]: https://img.shields.io/website?down_color=lightgrey&down_message=offline&label=documentation&up_color=green&up_message=online&url=https%3A%2F%2Feertmans.be%2Fmanim-slides%2F
|
||||
[documentation-url]: https://eertmans.be/manim-slides/
|
||||
[doi-badge]: https://zenodo.org/badge/DOI/10.5281/zenodo.7971361.svg
|
||||
[doi-url]: https://doi.org/10.5281/zenodo.7971361
|
||||
|
@ -2,10 +2,14 @@
|
||||
|
||||
Thank you for your interest in Manim Slides! ✨
|
||||
|
||||
Manim Slides is an open source project, first created as a fork of [manim-presentation](https://github.com/galatolofederico/manim-presentation) (now deprecated in favor to Manim Slides), and we welcome contributions of all forms.
|
||||
|
||||
This section is here to help fist-time contributors know how they can help this project grow. Whether you are already familiar with Manim or GitHub, it is worth taking a few minutes to read those documents!
|
||||
Manim Slides is an open source project, first created as a fork of
|
||||
[manim-presentation](https://github.com/galatolofederico/manim-presentation)
|
||||
(now deprecated in favor to Manim Slides),
|
||||
and we welcome contributions of all forms.
|
||||
|
||||
This section is here to help fist-time contributors know how they can help this
|
||||
project grow. Whether you are already familiar with Manim or GitHub,
|
||||
it is worth taking a few minutes to read those documents!
|
||||
|
||||
```{toctree}
|
||||
:hidden:
|
||||
@ -19,3 +23,24 @@ internals
|
||||
|
||||
[Internals](./internals)
|
||||
: how Manim Slides is built and how the various parts of it work.
|
||||
|
||||
## Reporting an Issue
|
||||
|
||||
```{include} ../../../README.md
|
||||
:start-after: <!-- start reporting-an-issue -->
|
||||
:end-before: <!-- end reporting-an-issue -->
|
||||
```
|
||||
|
||||
## Seeking for Help
|
||||
|
||||
```{include} ../../../README.md
|
||||
:start-after: <!-- start seeking-for-help -->
|
||||
:end-before: <!-- end seeking-for-help -->
|
||||
```
|
||||
|
||||
## Contact
|
||||
|
||||
```{include} ../../../README.md
|
||||
:start-after: <!-- start contact -->
|
||||
:end-before: <!-- end contact -->
|
||||
```
|
||||
|
@ -11,7 +11,7 @@ This document is there to help you recreate a working environment for Manim Slid
|
||||
|
||||
## Forking the repository and cloning it locally
|
||||
|
||||
We used GitHub to host Manim Slides' repository, and we encourage contributors to use git.
|
||||
We use GitHub to host Manim Slides' repository, and we encourage contributors to use git.
|
||||
|
||||
Useful links:
|
||||
|
||||
@ -30,6 +30,32 @@ With Poetry, installation becomes straightforward:
|
||||
poetry install
|
||||
```
|
||||
|
||||
This, however, only installs the minimal set of dependencies to run the package.
|
||||
|
||||
If you would like to install Manim or ManimGL, as documented in the [quickstart](../quickstart),
|
||||
you can use the `--extras` option:
|
||||
|
||||
```bash
|
||||
poetry install --extras manim # For Manim
|
||||
# or
|
||||
poetry install --extras manimgl # For ManimGL
|
||||
```
|
||||
|
||||
Additionnally, Manim Slides comes with group dependencies for development purposes:
|
||||
|
||||
```bash
|
||||
poetry install --with dev # For linters and formatters
|
||||
# or
|
||||
poetry install --with docs # To build the documentation locally
|
||||
```
|
||||
|
||||
Another group is `test`, but it is only used for
|
||||
[GitHub actions](https://github.com/jeertmans/manim-slides/blob/main/.github/workflows/test_examples.yml).
|
||||
|
||||
:::{note}
|
||||
You can combine any number of groups or extras when installing the package locally.
|
||||
:::
|
||||
|
||||
## Running commands
|
||||
|
||||
As modules were installed in a new Python environment, you cannot use them directly in the shell.
|
||||
|
@ -6,21 +6,21 @@ The following summarizes the different presentation features Manim Slides offers
|
||||
:widths: auto
|
||||
:align: center
|
||||
|
||||
| Feature / Constraint | [`present`](reference/cli.md) | [`convert --to=html`](reference/cli.md) | [`convert --to=pptx`](reference/cli.md) |
|
||||
| :--- | :---: | :---: | :---: |
|
||||
| Basic navigation through slides | Yes | Yes | Yes |
|
||||
| Replay slide | Yes | No | No |
|
||||
| Pause animation | Yes | No | No |
|
||||
| Play slide in reverse | Yes | No | No |
|
||||
| Slide count | Yes | Yes (optional) | Yes (optional) |
|
||||
| Animation count | Yes | No | No |
|
||||
| Needs Python with Manim Slides installed | Yes | No | No |
|
||||
| Requires internet access | No | Yes | No |
|
||||
| Auto. play slides | Yes | Yes | Yes |
|
||||
| Loops support | Yes | Yes | Yes |
|
||||
| Fully customizable | No | Yes (`--use-template` option) | No |
|
||||
| Other dependencies | None | A modern web browser | PowerPoint or LibreOffice Impress[^1]
|
||||
| Works cross-platforms | Yes | Yes | Partly[^1][^2] |
|
||||
| Feature / Constraint | [`present`](reference/cli.md) | [`convert --to=html`](reference/cli.md) | [`convert --to=pptx`](reference/cli.md) | [`convert --to=pdf`](reference/cli.md)
|
||||
| :--- | :---: | :---: | :---: | :---: |
|
||||
| Basic navigation through slides | Yes | Yes | Yes | Yes (static image) |
|
||||
| Replay slide | Yes | No | No | N/A |
|
||||
| Pause animation | Yes | No | No | N/A |
|
||||
| Play slide in reverse | Yes | No | No | N/A |
|
||||
| Slide count | Yes | Yes (optional) | Yes (optional) | N/A |
|
||||
| Animation count | Yes | No | No | N/A |
|
||||
| Needs Python with Manim Slides installed | Yes | No | No | No
|
||||
| Requires internet access | No | Yes | No | No |
|
||||
| Auto. play slides | Yes | Yes | Yes | N/A |
|
||||
| Loops support | Yes | Yes | Yes | N/A |
|
||||
| Fully customizable | No | Yes (`--use-template` option) | No | No |
|
||||
| Other dependencies | None | A modern web browser | PowerPoint or LibreOffice Impress[^1] | None |
|
||||
| Works cross-platforms | Yes | Yes | Partly[^1][^2] | Yes |
|
||||
:::
|
||||
|
||||
[^1]: If you encounter a problem where slides do not automatically play or loops do not work, please [file an issue on GitHub](https://github.com/jeertmans/manim-slides/issues/new/choose).
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Application Programming Interface
|
||||
|
||||
Manim Slides' API is very limited: it simply consists in two classes, `Slide` and `ThreeDSlide`, which are subclasses of `Scene` and `ThreeDScene` from Manim.
|
||||
Manim Slides' API is very limited: it simply consists of two classes, `Slide` and `ThreeDSlide`, which are subclasses of `Scene` and `ThreeDScene` from Manim.
|
||||
|
||||
Thefore, we only document here the methods we think the end-user will ever use, not the methods used internally when rendering.
|
||||
|
||||
|
@ -66,6 +66,56 @@ Example using 3D camera. As Manim and ManimGL handle 3D differently, definitions
|
||||
:end-before: [manimgl-3d]
|
||||
```
|
||||
|
||||
## Subclass Custom Scenes
|
||||
|
||||
For compatibility reasons, Manim Slides only provides subclasses for
|
||||
`Scene` and `ThreeDScene`.
|
||||
However, subclassing other scene classes is totally possible,
|
||||
and very simple to do actually!
|
||||
|
||||
[For example](https://github.com/jeertmans/manim-slides/discussions/185),
|
||||
you can subclass the `MovingCameraScene` class from `manim`
|
||||
with the following code:
|
||||
|
||||
```{code-block} python
|
||||
:linenos:
|
||||
|
||||
from manim import *
|
||||
from manim_slides import Slide
|
||||
|
||||
|
||||
class MovingCameraSlide(Slide, MovingCameraScene):
|
||||
pass
|
||||
```
|
||||
|
||||
And later use this class anywhere in your code:
|
||||
|
||||
|
||||
```{code-block} python
|
||||
:linenos:
|
||||
|
||||
class SubclassExample(MovingCameraSlide):
|
||||
def construct(self):
|
||||
eq1 = MathTex("x", "=", "1")
|
||||
eq2 = MathTex("x", "=", "2")
|
||||
|
||||
self.play(Write(eq1))
|
||||
|
||||
self.next_slide()
|
||||
|
||||
self.play(
|
||||
TransformMatchingTex(eq1, eq2),
|
||||
self.camera.frame.animate.scale(0.5)
|
||||
)
|
||||
|
||||
self.wait()
|
||||
```
|
||||
|
||||
:::{note}
|
||||
If you do not plan to reuse `MovingCameraSlide` more than once, then you can
|
||||
directly write the `construct` method in the body of `MovingCameraSlide`.
|
||||
:::
|
||||
|
||||
## Advanced Example
|
||||
|
||||
A more advanced example is `ConvertExample`, which is used as demo slide and tutorial.
|
||||
|
@ -4,7 +4,7 @@ Manim Slides allows you to convert presentations into one HTML file, with
|
||||
[RevealJS](https://revealjs.com/). This file can then be opened with any modern
|
||||
web browser, allowing for a nice portability of your presentations.
|
||||
|
||||
As for every command with Manim Slides, converting slides' fragments into one
|
||||
As with every command with Manim Slides, converting slides' fragments into one
|
||||
HTML file (and its assets) can be done in one command:
|
||||
|
||||
```bash
|
||||
|
@ -67,7 +67,7 @@ and the corresponding tree:
|
||||
## Without Manim Slides installed on the target machine
|
||||
|
||||
An alternative to `manim-slides present` is `manim-slides convert`.
|
||||
Currently, only HTML conversion is available, but do not hesitate to propose
|
||||
Currently, HTML and PPTX conversion are available, but do not hesitate to propose
|
||||
other formats by creating a
|
||||
[Feature Request](https://github.com/jeertmans/manim-slides/issues/new/choose),
|
||||
or directly proposing a
|
||||
@ -150,7 +150,10 @@ reason.
|
||||
|
||||
### With PowerPoint (*EXPERIMENTAL*)
|
||||
|
||||
A recent conversion feature is to the PowerPoint format, thanks to the `python-pptx` package. Even though it is fully working, it is still considered in an *EXPERIMENTAL* status because we do not exactly know what versions of PowerPoint (or LibreOffice Impress) are supported.
|
||||
A recent conversion feature is to the PowerPoint format, thanks to the
|
||||
`python-pptx` package. Even though it is fully working,
|
||||
it is still considered in an *EXPERIMENTAL* status because we do not
|
||||
exactly know what versions of PowerPoint (or LibreOffice Impress) are supported.
|
||||
|
||||
Basically, you can create a PowerPoint in a single command:
|
||||
|
||||
@ -158,6 +161,24 @@ Basically, you can create a PowerPoint in a single command:
|
||||
manim-slides convert --to=pptx BasicExample basic_example.pptx
|
||||
```
|
||||
|
||||
All the videos and necessary files will be contained inside the `.pptx` file, so you can safely share it with anyone. By default, the `poster_frame_image`, i.e., what is displayed by PowerPoint when the video is not playing, is the first frame of each slide. This allows for smooth transitions.
|
||||
All the videos and necessary files will be contained inside the `.pptx` file, so
|
||||
you can safely share it with anyone. By default, the `poster_frame_image`, i.e.,
|
||||
what is displayed by PowerPoint when the video is not playing, is the first
|
||||
frame of each slide. This allows for smooth transitions.
|
||||
|
||||
In the future, we hope to provide more features to this format, so feel free to suggest new features too!
|
||||
In the future, we hope to provide more features to this format,
|
||||
so feel free to suggest new features too!
|
||||
|
||||
### Static PDF presentation
|
||||
|
||||
If you ever need backup slides, that are only made of PDF pages
|
||||
with static images, you can generate such a PDF with the following command:
|
||||
|
||||
```bash
|
||||
manim-slides convert --to=pdf BasicExample basic_example.pdf
|
||||
```
|
||||
|
||||
Note that you will lose all the benefits from animated slides. Therefore,
|
||||
this is only recommended to be used as a backup plan. By default, the last frame
|
||||
of each slide will be printed. This can be changed to be the first one with
|
||||
`-cframe_index=first`.
|
||||
|
@ -1 +1 @@
|
||||
__version__ = "4.12.0"
|
||||
__version__ = "4.14.0"
|
||||
|
@ -54,10 +54,10 @@ def verbosity_option(function: F) -> F:
|
||||
"-v",
|
||||
"--verbosity",
|
||||
type=click.Choice(
|
||||
["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
|
||||
["PERF", "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
|
||||
case_sensitive=False,
|
||||
),
|
||||
help="Verbosity of CLI output",
|
||||
help="Verbosity of CLI output. PERF will log performances (timing) information.",
|
||||
default=None,
|
||||
expose_value=False,
|
||||
envvar="MANIM_SLIDES_VERBOSITY",
|
||||
|
@ -14,7 +14,8 @@ import cv2
|
||||
import pptx
|
||||
from click import Context, Parameter
|
||||
from lxml import etree
|
||||
from pydantic import BaseModel, FilePath, PositiveInt, ValidationError
|
||||
from PIL import Image
|
||||
from pydantic import BaseModel, FilePath, PositiveFloat, PositiveInt, ValidationError
|
||||
from tqdm import tqdm
|
||||
|
||||
from . import data
|
||||
@ -54,7 +55,7 @@ def validate_config_option(
|
||||
class Converter(BaseModel): # type: ignore
|
||||
presentation_configs: List[PresentationConfig] = []
|
||||
assets_dir: str = "{basename}_assets"
|
||||
template: Optional[str] = None
|
||||
template: Optional[Path] = None
|
||||
|
||||
def convert_to(self, dest: Path) -> None:
|
||||
"""Converts self, i.e., a list of presentations, into a given format."""
|
||||
@ -75,6 +76,7 @@ class Converter(BaseModel): # type: ignore
|
||||
"""Returns the appropriate converter from a string name."""
|
||||
return {
|
||||
"html": RevealJS,
|
||||
"pdf": PDF,
|
||||
"pptx": PowerPoint,
|
||||
}[s]
|
||||
|
||||
@ -314,6 +316,8 @@ class RevealJS(Converter):
|
||||
file = presentation_config.files[slide_config.start_animation]
|
||||
file = assets_dir / file.name
|
||||
|
||||
logger.debug(f"Writing video section with file {file}")
|
||||
|
||||
# TODO: document this
|
||||
# Videos are muted because, otherwise, the first slide never plays correctly.
|
||||
# This is due to a restriction in playing audio without the user doing anything.
|
||||
@ -327,9 +331,8 @@ class RevealJS(Converter):
|
||||
|
||||
def load_template(self) -> str:
|
||||
"""Returns the RevealJS HTML template as a string."""
|
||||
if isinstance(self.template, str):
|
||||
with open(self.template, "r") as f:
|
||||
return f.read()
|
||||
if isinstance(self.template, Path):
|
||||
return self.template.read_text()
|
||||
|
||||
if sys.version_info < (3, 9):
|
||||
return resources.read_text(data, "revealjs_template.html")
|
||||
@ -350,6 +353,8 @@ class RevealJS(Converter):
|
||||
)
|
||||
full_assets_dir = dirname / assets_dir
|
||||
|
||||
logger.debug(f"Assets will be saved to: {full_assets_dir}")
|
||||
|
||||
os.makedirs(full_assets_dir, exist_ok=True)
|
||||
|
||||
for presentation_config in self.presentation_configs:
|
||||
@ -364,6 +369,62 @@ class RevealJS(Converter):
|
||||
f.write(content)
|
||||
|
||||
|
||||
class FrameIndex(str, Enum):
|
||||
first = "first"
|
||||
last = "last"
|
||||
|
||||
|
||||
class PDF(Converter):
|
||||
frame_index: FrameIndex = FrameIndex.last
|
||||
resolution: PositiveFloat = 100.0
|
||||
|
||||
class Config:
|
||||
use_enum_values = True
|
||||
extra = "forbid"
|
||||
|
||||
def open(self, file: Path) -> None:
|
||||
return open_with_default(file)
|
||||
|
||||
def convert_to(self, dest: Path) -> None:
|
||||
"""Converts this configuration into a PDF presentation, saved to DEST."""
|
||||
|
||||
def read_image_from_video_file(file: Path, frame_index: FrameIndex) -> Image:
|
||||
cap = cv2.VideoCapture(str(file))
|
||||
|
||||
if frame_index == FrameIndex.last:
|
||||
index = cap.get(cv2.CAP_PROP_FRAME_COUNT)
|
||||
cap.set(cv2.CAP_PROP_POS_FRAMES, index - 1)
|
||||
|
||||
ret, frame = cap.read()
|
||||
|
||||
if ret:
|
||||
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||
return Image.fromarray(frame)
|
||||
else:
|
||||
raise ValueError("Failed to read {image_index} image from video file")
|
||||
|
||||
images = []
|
||||
|
||||
for i, presentation_config in enumerate(self.presentation_configs):
|
||||
presentation_config.concat_animations()
|
||||
for slide_config in tqdm(
|
||||
presentation_config.slides,
|
||||
desc=f"Generating video slides for config {i + 1}",
|
||||
leave=False,
|
||||
):
|
||||
file = presentation_config.files[slide_config.start_animation]
|
||||
|
||||
images.append(read_image_from_video_file(file, self.frame_index))
|
||||
|
||||
images[0].save(
|
||||
dest,
|
||||
"PDF",
|
||||
resolution=self.resolution,
|
||||
save_all=True,
|
||||
append_images=images[1:],
|
||||
)
|
||||
|
||||
|
||||
class PowerPoint(Converter):
|
||||
left: PositiveInt = 0
|
||||
top: PositiveInt = 0
|
||||
@ -510,7 +571,7 @@ def show_template_option(function: Callable[..., Any]) -> Callable[..., Any]:
|
||||
@click.argument("dest", type=click.Path(dir_okay=False, path_type=Path))
|
||||
@click.option(
|
||||
"--to",
|
||||
type=click.Choice(["html", "pptx"], case_sensitive=False),
|
||||
type=click.Choice(["html", "pdf", "pptx"], case_sensitive=False),
|
||||
default="html",
|
||||
show_default=True,
|
||||
help="Set the conversion format to use.",
|
||||
|
@ -5,7 +5,9 @@ https://github.com/ManimCommunity/manim/blob/d5b65b844b8ce8ff5151a2f56f9dc98cebb
|
||||
|
||||
import logging
|
||||
|
||||
from rich.console import Console
|
||||
from rich.logging import RichHandler
|
||||
from rich.theme import Theme
|
||||
|
||||
__all__ = ["logger", "make_logger"]
|
||||
|
||||
@ -33,9 +35,12 @@ def make_logger() -> logging.Logger:
|
||||
RichHandler.KEYWORDS = HIGHLIGHTED_KEYWORDS
|
||||
rich_handler = RichHandler(
|
||||
show_time=True,
|
||||
console=Console(theme=Theme({"logging.level.perf": "magenta"})),
|
||||
)
|
||||
logging.addLevelName(5, "PERF")
|
||||
logger = logging.getLogger("manim-slides")
|
||||
logger.addHandler(rich_handler)
|
||||
|
||||
return logger
|
||||
|
||||
|
||||
|
@ -448,6 +448,21 @@ class Display(QThread): # type: ignore
|
||||
|
||||
lag = now() - last_time
|
||||
sleep_time = 1 / self.current_presentation.fps
|
||||
|
||||
logger.log(
|
||||
5,
|
||||
f"Took {lag:.3f} seconds to process the current frame, that must play at a rate of one every {sleep_time:.3f} seconds.",
|
||||
)
|
||||
|
||||
if sleep_time - lag < 0:
|
||||
logger.warn(
|
||||
"The FPS rate could not be matched. "
|
||||
"This is normal when manually transitioning between slides.\n"
|
||||
"If you feel that the FPS are too low, "
|
||||
"consider checking this issue:\n"
|
||||
"https://github.com/jeertmans/manim-slides/issues/179."
|
||||
)
|
||||
|
||||
sleep_time = max(sleep_time - lag, 0)
|
||||
time.sleep(sleep_time)
|
||||
last_time = now()
|
||||
@ -891,7 +906,7 @@ def start_at_callback(
|
||||
"-s",
|
||||
"--skip-all",
|
||||
is_flag=True,
|
||||
help="Skip all slides, useful the test if slides are working. Automatically sets `--skip-after-last-slide` to True.",
|
||||
help="Skip all slides, useful the test if slides are working. Automatically sets `--exit-after-last-slide` to True.",
|
||||
)
|
||||
@click.option(
|
||||
"-r",
|
||||
|
BIN
paper/docs.png
BIN
paper/docs.png
Binary file not shown.
Before Width: | Height: | Size: 4.3 MiB After Width: | Height: | Size: 4.3 MiB |
@ -59,18 +59,23 @@ evolved very little since its inception and does not work with ManimGL.
|
||||
In 2022, Manim Slides has been created from manim-presentation, with the aim
|
||||
to make it a more complete tool, better documented, and usable on all platforms
|
||||
and with ManimCE or ManimGL. After almost a year of existence, Manim Slides has
|
||||
evolved a lot, has built a small community of contributors, and continues to
|
||||
evolved a lot (see
|
||||
[comparison section](#comparison-with-manim-presentation)),
|
||||
has built a small community of contributors, and continues to
|
||||
provide new features on a regular basis.
|
||||
|
||||
# Easy to Use Commitment
|
||||
|
||||
Manim Slides is commited to be an easy-to-use tool, when minimal installation
|
||||
Manim Slides is commited to be an easy-to-use tool, with minimal installation
|
||||
procedure and few modifications required. It can either be used locally with its
|
||||
graphical user interface (GUI), or shared via HTML thanks to the RevealJS
|
||||
Javascript package [@revealjs].
|
||||
graphical user interface (GUI), or shared via one of the two formats it can
|
||||
convert to:
|
||||
|
||||
* an HTML page thanks to the RevealJS Javascript package [@revealjs];
|
||||
* or a PowerPoint (`.pptx`) file.
|
||||
|
||||
This work has a very similar syntax to Manim and offers a comprehensive
|
||||
documentation hosted on [GitHub pages](https://eertmans.be/manim-slides/), see
|
||||
documentation hosted on [GitHub pages](https://jeertmans.github.io/manim-slides/), see
|
||||
\autoref{fig:docs}.
|
||||
|
||||

|
||||
@ -79,10 +84,10 @@ documentation hosted on [GitHub pages](https://eertmans.be/manim-slides/), see
|
||||
|
||||
We have used manim-presentation for our presentation at the COST
|
||||
Interact, hosted in Lyon, 2022, and
|
||||
[available online](https://eertmans.be/research/cost-interact-presentation/).
|
||||
[available online](https://web.archive.org/web/20230507184944/https://eertmans.be/posts/cost-interact-presentation/).
|
||||
This experience highly motivated the development of Manim Slides, and our
|
||||
EuCAP 2023 presentation slides are already
|
||||
[available online](https://eertmans.be/research/eucap-presentation/), thanks
|
||||
[available online](https://web.archive.org/web/20230507211243/https://eertmans.be/posts/eucap-presentation/), thanks
|
||||
to Manim Slides' HTML feature.
|
||||
|
||||
Also, one of our users created a short
|
||||
@ -92,8 +97,8 @@ and posted it on YouTube.
|
||||
# Stability and releases
|
||||
|
||||
Manim Slides is continously tested on most recent Python versions, both ManimCE
|
||||
and ManimGL, and on all major platforms: **Ubuntu**, **macOS** and **Windows**. As of Manim
|
||||
Slide's exposed API begin very minimal, and the variaty of tests that are
|
||||
and ManimGL, and on all major platforms: **Ubuntu**, **macOS** and **Windows**. Due to Manim
|
||||
Slide's exposed API being very minimal, and the variety of tests that are
|
||||
performed, this tool can be considered stable over time.
|
||||
|
||||
New releases are very frequent, as they mostly introduce enhancements or small
|
||||
@ -111,12 +116,56 @@ presenting Manim content in front of an audience much easier than before,
|
||||
allowing presenters to focus more on the content of their slides, rather than on
|
||||
how to actually present them efficiently.
|
||||
|
||||
## Target Audience
|
||||
|
||||
Manim Slides was developed with the goal of making educational content more
|
||||
accessible than ever. We believe that researchers, professors, teaching
|
||||
assistants and anyone else who needs to teach scientific content can benefit
|
||||
from using this tool. The ability to pace your presentation yourself is
|
||||
essential, and Manim Slides gives you that ability.
|
||||
|
||||
## A Need for Portability
|
||||
|
||||
One of the major concerns with presenting content in a non-standard format
|
||||
(i.e., not just a plain PDF) is the issue of portability.
|
||||
Depending on the programs available, the power of the target computer,
|
||||
or the access to the internet, not all solutions are equal.
|
||||
From the same configuration file, Manim Slides offers a series of solutions to
|
||||
share your slides, which we discuss on our
|
||||
[Sharing your slides](https://jeertmans.github.io/manim-slides/reference/sharing.html)
|
||||
page.
|
||||
|
||||
## Comparison with manim-presentation
|
||||
|
||||
Starting from [@manim-presentation]'s original work, Manim Slides now provides
|
||||
numerous additional features.
|
||||
A non-exhaustive list of those new features is as follows:
|
||||
|
||||
* ManimGL compatibility;
|
||||
* playing slides in reverse;
|
||||
* exporting slides to HTML and PowerPoint;
|
||||
* 3D scene support;
|
||||
* multiple key inputs can map to the same action
|
||||
(e.g., useful when using a pointer);
|
||||
* optionally hiding mouse cursor when presenting;
|
||||
* recording your presentation;
|
||||
* multiple video scaling methods (for speed-vs-quality tradeoff);
|
||||
* and automatic detection of some scene parameters
|
||||
(e.g., resolution or background color).
|
||||
|
||||
The complete and up-to-date set of features Manim Slide supports is
|
||||
available in the
|
||||
[online documentation](https://jeertmans.github.io/manim-slides/).
|
||||
For new feature requests, we highly encourage users to
|
||||
[create an issue](https://github.com/jeertmans/manim-slides/issues/new/choose)
|
||||
with the appropriate template.
|
||||
|
||||
# Acknowledgements
|
||||
|
||||
We acknowledge the work of [@manim-presentation] that paved the initial structure
|
||||
of Manim Slides with the manim-presentation Python package.
|
||||
|
||||
We also acknowledge Grant Sanderson for its termendous work on Manim, as well as
|
||||
We also acknowledge Grant Sanderson for his tremendous work on Manim, as
|
||||
well as the Manim Community contributors.
|
||||
|
||||
Finally, we also acknowledge contributions from the GitHub contributors on the
|
||||
|
1043
poetry.lock
generated
1043
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@ -43,22 +43,29 @@ packages = [
|
||||
]
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/jeertmans/manim-slides"
|
||||
version = "4.12.0"
|
||||
version = "4.14.0"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
click = "^8.1.3"
|
||||
click-default-group = "^1.2.2"
|
||||
lxml = "^4.9.2"
|
||||
manim = {version = "^0.17.0", optional = true}
|
||||
manimgl = {version = "^1.6.1", optional = true}
|
||||
numpy = "^1.19"
|
||||
opencv-python = "^4.6.0.66"
|
||||
pillow = "^9.5.0"
|
||||
pydantic = "^1.10.2"
|
||||
pyside6 = "^6.4.1"
|
||||
pyside6 = "^6.5.1.1"
|
||||
python = ">=3.8.1,<3.12"
|
||||
python-pptx = "^0.6.21"
|
||||
requests = "^2.28.1"
|
||||
rich = "^13.3.2"
|
||||
tqdm = "^4.64.1"
|
||||
|
||||
[tool.poetry.extras]
|
||||
manim = ["manim"]
|
||||
manimgl = ["manimgl"]
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
black = "^22.10.0"
|
||||
bump2version = "^1.0.1"
|
||||
|
Reference in New Issue
Block a user