Skip to content
Open
Show file tree
Hide file tree
Changes from 11 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
8 changes: 4 additions & 4 deletions docs/source/contributing/testing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -292,10 +292,10 @@ Note the fixtures here:
You have to generate a ``.json`` file first to be able to test your video. To
do that, use ``helpers.save_control_data_from_video``.

For instance, a test that will check if the l flag works properly will first
require rendering a video using the -l flag from a scene. Then we will test
(in this case, SquareToCircle), that lives in
``test_scene_rendering/simple_scene.py``. Change directories to ``tests/``,
For instance, a test that checks low-quality rendering first requires rendering

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, "...a test that checks low-quality rendering will first require rendering..." would work better here just to avoid the possible interpretation that the low-quality test is the first test of multiple to come.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed -- I've pushed an easier to read reworded version!

a video from a scene with the ``-ql`` flag. The example below tests
``SquareToCircle``, which lives in ``test_scene_rendering/simple_scene.py``.
Change directories to ``tests/``,
create a file (e.g. ``create\_data.py``) that you will remove as soon as
you're done. Then run:

Expand Down
5 changes: 3 additions & 2 deletions docs/source/faq/general.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,9 @@ ones that are documented for the base classes {class}`.VMobject` and
Yes: simply pass the CLI flag `-t` (or its long form `--transparent`).
Note that the default video file format does not support transparency,
which is why Manim will output a `.mov` instead of a `.mp4` when
rendering with a transparent background. Other movie file formats
that support transparency can be obtained by passing
rendering with a transparent background. Explicitly requesting
`--format=mp4` together with transparency is rejected. Other movie file
formats that support transparency can be obtained by passing
`--format=webm` or `--format=gif`.

---
Expand Down
56 changes: 30 additions & 26 deletions docs/source/guides/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,20 @@ An example of using the above form is:
This asks Manim to search for a Scene class called :code:`SceneOne` inside the
file ``file.py`` and render it with medium quality (specified by the ``-qm`` flag).

Another frequently used flag is ``-p`` ("preview"), which makes manim
open the rendered video after it's done rendering.
Another frequently used flag is ``-p`` ("preview"), which makes Manim
open the rendered artifact after rendering. This behavior is the same for all
renderers.

.. note:: The ``-p`` flag does not change any properties of the global
``config`` dict. The ``-p`` flag is only a command-line convenience.
Renderers may also support a live preview while the scene is evaluated. The
OpenGL renderer provides this with ``-l`` (or ``--live-preview``):

.. code-block:: bash

manim --renderer=opengl -l <file.py> SceneName

With ``--format=auto``, live preview does not write a media file, keeping the
interactive workflow fast. Pass a concrete format, such as ``--format=mp4``,
to record the scene while displaying the live preview.

Advanced examples
=================
Expand All @@ -53,6 +62,10 @@ instead of the whole video, you can execute

manim -sqh <file.py> SceneName

The equivalent ``--format=png`` spelling uses the same fast final-state-only
evaluation. Use ``--format=png-sequence`` when every rendered frame should be
written as a numbered PNG instead.

The following example specifies the output file name (with the :code:`-o`
flag), renders only the first ten animations (:code:`-n` flag) with a white
background (:code:`-c` flag), and saves the animation as a ``.gif`` instead of as a
Expand Down Expand Up @@ -161,7 +174,7 @@ and serve the same purpose. Take, for example, the following config file.
[CLI]
# my config file
output_file = myscene
save_as_gif = True
format = gif
background_color = WHITE

Config files are parsed with the standard python library ``configparser``. In
Expand All @@ -171,7 +184,7 @@ Now, executing the following command

.. code-block:: bash

manim -o myscene -i -c WHITE <file.py> SceneName
manim -o myscene --format=gif -c WHITE <file.py> SceneName

is equivalent to executing the following command, provided that ``manim.cfg``
is in the same directory as <file.py>,
Expand Down Expand Up @@ -253,7 +266,7 @@ For example, take the following user-wide config file
# user-wide
[CLI]
output_file = myscene
save_as_gif = True
format = gif
background_color = WHITE

and the following folder-wide file
Expand All @@ -262,7 +275,7 @@ and the following folder-wide file

# folder-wide
[CLI]
save_as_gif = False
format = auto

Then, executing :code:`manim <file.py> SceneName` will be equivalent to not
using any config files and executing
Expand Down Expand Up @@ -344,26 +357,17 @@ highest precedence is:
5. any programmatic changes made after the config system is set.


A list of all config options
****************************
Inspecting available config options
***********************************

.. code::
Run ``manim cfg show`` to inspect the currently resolved configuration and
``manim render --help`` for the authoritative list of render CLI options. The
attributes available for programmatic configuration are documented on
:class:`.ManimConfig`.

['aspect_ratio', 'assets_dir', 'background_color', 'background_opacity',
'bottom', 'custom_folders', 'disable_caching', 'dry_run',
'encoder_queue_size', 'ffmpeg_loglevel', 'flush_cache', 'frame_height', 'frame_rate',
'frame_size', 'frame_width', 'frame_x_radius', 'frame_y_radius',
'from_animation_number', `fullscreen`, 'images_dir', 'input_file', 'left_side',
'log_dir', 'log_to_file', 'max_files_cached', 'max_inflight_encoders',
'media_dir', 'media_width', 'movie_file_extension', 'notify_outdated_version',
'output_file', 'partial_movie_dir',
'pixel_height', 'pixel_width', 'plugins', 'preview',
'progress_bar', 'quality', 'right_side', 'save_as_gif', 'save_last_frame',
'save_pngs', 'scene_names', 'show_in_file_browser', 'sound', 'tex_dir',
'tex_template', 'tex_template_file', 'text_dir', 'top', 'transparent',
'upto_animation_number', 'use_opengl_renderer', 'verbosity', 'video_dir',
'window_position', 'window_monitor', 'window_size', 'write_all', 'write_to_movie',
'enable_wireframe', 'force_window']
Some CLI conveniences intentionally map to a canonical configuration value. In
particular, ``-s`` / ``--save_last_frame`` sets ``format = png``; configuration
files should use the canonical ``format`` option directly.


Accessing CLI command options
Expand Down
82 changes: 55 additions & 27 deletions docs/source/guides/deep_dive.rst
Original file line number Diff line number Diff line change
Expand Up @@ -119,19 +119,19 @@ Preliminaries
Importing the library
^^^^^^^^^^^^^^^^^^^^^

Independent of how exactly you are telling your system
to render the scene, i.e., whether you run ``manim -qm -p file_name.py ToyExample``, or
whether you are rendering the scene directly from the Python script via a snippet
like
You can ask Manim to render in several ways. For example, you can run
``manim -qm -p file_name.py ToyExample`` or render directly from a Python script
with a snippet like

::

with tempconfig({"quality": "medium_quality", "preview": True}):
scene = ToyExample()
scene.render()

or whether you are rendering the code in a Jupyter notebook, you are still telling your
python interpreter to import the library. The usual pattern used to do this is
Whether you are rendering this way or from a Jupyter notebook, you are still
telling your Python interpreter to import the library. The usual pattern used to
do this is

::

Expand Down Expand Up @@ -243,7 +243,7 @@ then calls the scene's render method in the
**Jupyter notebooks.** In Jupyter notebooks, the communication with the library
is handled by the ``%%manim`` magic command, which is implemented in the
``manim.utils.ipython_magic`` module. There is
:meth:`some documentation <.ManimMagic.manim>` available for the magic command,
:meth:`some documentation <.ManimMagic.manim>` available for the magic command.
The implementation instantiates the requested scene and calls its render method;
the scene attaches a manager lazily through that entry point.

Expand All @@ -263,18 +263,38 @@ depend on any configuration options set in ``config``. Then the scene inspects t
``config.renderer``, and based on its value, either instantiates a ``CairoRenderer`` or an
``OpenGLRenderer`` object and assigns it to its ``renderer`` attribute.

The scene then asks its renderer to initialize the scene by calling
After selecting the renderer, the scene resolves the mutable configuration into
one immutable render-session specification. In abbreviated form, initialization
continues as follows:

::

self.renderer.init_scene(self)

Inspecting both the default Cairo renderer and the OpenGL renderer shows that the ``init_scene``
method effectively makes the renderer instantiate a :class:`.SceneFileWriter` object, which
basically is Manim's interface to ``libav`` (FFMPEG) and actually writes the movie file. The Cairo
renderer (see the implementation `here <https://github.com/ManimCommunity/manim/blob/main/manim/renderer/cairo_renderer.py>`__) does not require any further initialization. The OpenGL renderer
does some additional setup to enable the realtime rendering preview window, which we do not go
into detail further here.
self.session_spec = resolve_render_session(
config,
self.renderer.capabilities,
renderer_name=type(self.renderer).__name__,
)
self.renderer.init_scene(self, self.session_spec)

The session specification separates primary artifact intent (an ``OutputSpec``)
from presentation requests such as opening the completed artifact or displaying
a live preview. It also preserves whether dry-run execution was requested. A dry
run and an artifact-less render both have an effective output format of ``none``,
but the reason remains available without rereading mutable global configuration.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe something like "but a dry run is treated as if it were a normal render session with a provided output format." instead?

It doesn't feel useful to the reader to know what the system doesn't do.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed -- attempted to make the intent behind dry_run a bit clearer.

Resolution also validates requests against the selected renderer's capabilities.
For example, Cairo rejects live preview, while OpenGL advertises support for it.
With ``format = auto``, requesting live preview selects no file output; a
concrete format records the render as well.

Inspecting the initialization methods of both renderers shows that they
instantiate a :class:`.SceneFileWriter`. The writer must receive the already
resolved ``OutputSpec``. It remains Manim's interface to ``libav`` for
encoding media. The Cairo renderer (see the implementation `here
<https://github.com/ManimCommunity/manim/blob/main/manim/renderer/cairo_renderer.py>`__)
does not require further renderer-specific initialization. OpenGL creates a
window only when the resolved presentation specification requests a live preview.
The ``-p`` / ``--preview`` option does not create this window; it opens the
completed artifact after rendering.

After the renderer has been instantiated and initialized its file writer, the scene
populates further initial attributes (notable mention: the ``mobjects`` attribute
Expand All @@ -284,9 +304,11 @@ attribute is initially ``None`` unless the caller attaches a manager explicitly.
.. warning::

:class:`.Manager` is an incremental coordination boundary. At this stage the
renderer still owns its camera, clock, play count, skip state, and file writer;
the manager exposes forwarding views of them. The scene and renderer therefore
still have substantial interplay that later refactors aim to remove.
scene captures the immutable session specification before renderer
initialization, while the renderer still owns its camera, clock, play count,
skip state, and file writer. The manager exposes the session and forwarding
views of renderer state. The scene and renderer therefore still have
substantial interplay that later refactors aim to remove.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what to do about this one, it's very hard to read so I don't understand the paragraph well enough to rephrase it 😅

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

simplified!


The rest of this article is concerned with the last line in our toy example script::

Expand Down Expand Up @@ -314,11 +336,15 @@ The first three call the corresponding customizable scene hooks:

After these hooks have run, :meth:`.Manager.post_construct` asks the renderer to
finish the scene. For Cairo this calls :meth:`.CairoRenderer.scene_finished`,
which checks whether animations have been played and tells the
:class:`.SceneFileWriter` to finish the output. For video output, the file writer
waits for partial movie files that are still being encoded and combines them into
the final movie. If no animations have been played, Manim assumes that a static
image should be output.
which checks the resolved output intent and tells the :class:`.SceneFileWriter`
to finish any time-based output. For video output, the file writer waits for
partial movie files that are still being encoded and combines them into the
final movie. Single-PNG output skips any remaining animation frames and renders
a single image. A video request for a scene without any play calls produces a
useful still image instead of an empty movie. The writer records the completed
artifact as ``final_file_path``. After finalization, the manager uses the
presentation specification to open the artifact or reveal it in the file
browser.

**Back in our toy example,** the call to :meth:`.Scene.render` creates a manager,
then :meth:`.Manager.render` triggers :meth:`.Scene.setup` (which only consists of
Expand Down Expand Up @@ -1038,9 +1064,11 @@ calls the scene's cleanup method :meth:`.Scene.tear_down`, followed by
scene, and the renderer in turn asks its scene file writer to wrap things up by
calling :meth:`.SceneFileWriter.finish`. The file writer first waits for all
remaining encoding jobs, then combines the completed partial movie files into the
final product. If rendering aborts during a play instead, the manager asks the file
writer to abort its encoding jobs; the incomplete current partial movie file is
removed so that it cannot be mistaken for a valid cached result on a later render.
final product and records its path. If rendering aborts during a play instead, the
manager asks the file writer to abort its encoding jobs; the incomplete current
partial movie file is removed so that it cannot be mistaken for a valid cached
result on a later render. Once output is finalized, the manager carries out any
post-render presentation request from the immutable session specification.

And there you go! This is a more or less detailed description of how Manim works
under the hood. While we did not discuss every single line of code in detail
Expand Down
6 changes: 3 additions & 3 deletions docs/source/installation/docker.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ For our image ``manimcommunity/manim``, there are the following tags:

.. note::

When using Manim's CLI within a Docker container, some flags like
``-p`` (preview file) and ``-f`` (show output file in the file browser)
are not supported.
When using Manim's CLI within a Docker container, options that launch host
applications, such as ``-p`` and ``--show_in_file_browser``, are not
supported. Live preview also requires explicit display forwarding.

.. note::

Expand Down
Loading
Loading