Skip to content
Open
Show file tree
Hide file tree
Changes from all 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, testing low-quality output requires first rendering 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 mode that saves only
the last frame. 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
93 changes: 63 additions & 30 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,44 @@ 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 records dry-run execution separately from artifact
selection. A dry run requests semantic scene evaluation without rasterizing
frames or using media and cache resources. In contrast, ``format = none`` only
suppresses the primary artifact; an OpenGL live preview with automatic output
still rasterizes and displays frames without writing a file. Both requests have
an effective output format of ``none``, so the session's ``dry_run`` field
preserves the intended execution behavior.

The current renderer loops do not yet enforce no-raster dry runs; the session
field preserves that request for Manager-owned execution. Resolution also
validates requests against the selected renderer's capabilities. For example,
Cairo rejects live preview, while OpenGL advertises support for it. A concrete
format records the live preview 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 @@ -283,10 +309,9 @@ 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.
The manager coordinates the scene lifecycle, while the renderer still owns
its camera, clock, play count, skip state, and file writer. The manager
currently exposes these through forwarding properties.

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

Expand All @@ -312,13 +337,19 @@ The first three call the corresponding customizable scene hooks:
hook is more relevant for situations where Manim is used within other
Python scripts).

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.
After these hooks have run, :meth:`.Manager.post_construct` checks whether the
resolved output can be finalized. An explicit video format for a scene without
play calls raises an error instead of silently changing the requested artifact.
Otherwise, the manager asks the renderer to finish the scene. For Cairo this
calls :meth:`.CairoRenderer.scene_finished`, which 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. Last-frame PNG output fast-forwards
animations and renders a single image. When automatic output selected a video
for a scene without play calls, the writer saves that image as a fallback PNG and
the manager logs a warning. 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 +1069,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