Repository: ManimCommunity/manim

Issue:
Add video_embed or --embed argument to ManimMagic
## Description of proposed feature
Add an `embed` flag to the `ManimMagic` so that the user can control whether or not videos are embded.

Currently `video_embed = "google.colab" in str(get_ipython())` is hardcoded to be enabled on Google's CoLab, but there are other places this can be useful, for example, when generating documentation using Sphinx or [JupyterBook](https://jupyterbook.org).

## How can the new feature be used?

<!-- If possible, illustrate how this new feature could be used. -->

From the example:

```{ipython}
%%manim --embed -v WARNING --disable_caching -qm BannerExample

config.media_width = "75%"

class BannerExample(Scene):
    def construct(self):
        self.camera.background_color = "#ece6e2"
        banner_large = ManimBanner(dark_theme=False).scale(0.7)
        self.play(banner_large.create())
        self.play(banner_large.expand())
```

This would embed the video in the notebook and output, allowing it to be displayed in other contexts.

## Additional comments
This is a rather trivial change. I will submit a PR shortly once I explore a bit to see what the best naming options are. 

## References

The following may be relevant/useful:

* [Adding videos in JupyterBook](https://mstruwig.com/posts/jupyterbook-video/)
* https://github.com/executablebooks/jupyter-book/issues/1249
* https://github.com/ManimCommunity/manim/pull/1312
* https://github.com/ManimCommunity/manim/issues/1243


Discussion:

Resolving patch:
diff --git a/manim/_config/utils.py b/manim/_config/utils.py
--- a/manim/_config/utils.py
+++ b/manim/_config/utils.py
@@ -253,6 +253,7 @@ class MyScene(Scene):
         "from_animation_number",
         "images_dir",
         "input_file",
+        "media_embed",
         "media_width",
         "webgl_renderer_path",
         "log_dir",
@@ -627,6 +628,12 @@ def digest_parser(self, parser: configparser.ConfigParser) -> ManimConfig:
         if val:
             self.ffmpeg_loglevel = val
 
+        try:
+            val = parser["jupyter"].getboolean("media_embed")
+        except ValueError:
+            val = None
+        setattr(self, "media_embed", val)
+
         val = parser["jupyter"].get("media_width")
         if val:
             setattr(self, "media_width", val)
@@ -971,6 +978,12 @@ def format(self, val: str) -> None:
         doc="Verbosity level of ffmpeg (no flag).",
     )
 
+    media_embed = property(
+        lambda self: self._d["media_embed"],
+        lambda self, val: self._d.__setitem__("media_embed", val),
+        doc="Embed videos in Jupyter notebook",
+    )
+
     media_width = property(
         lambda self: self._d["media_width"],
         lambda self, val: self._d.__setitem__("media_width", val),
diff --git a/manim/utils/ipython_magic.py b/manim/utils/ipython_magic.py
--- a/manim/utils/ipython_magic.py
+++ b/manim/utils/ipython_magic.py
@@ -78,6 +78,14 @@ def construct(self):
                 which is 25% of your current viewport width. To allow the output to become as large
                 as possible, set ``config.media_width = "100%"``.
 
+                The ``media_embed`` option will embed the image/video output in the notebook. This is
+                generally undesirable as it makes the notebooks very large, but is required on some
+                platforms (notably Google's CoLab, where it is automatically enabled unless suppressed
+                by ``config.embed = False``) and needed in cases when the notebook (or converted HTML
+                file) will be moved relative to the video locations. Use-cases include building
+                documentation with Sphinx and JupyterBook. See also the :mod:`manim directive for Sphinx
+                <manim.utils.docbuild.manim_directive>`.
+
             Examples
             --------
 
@@ -88,6 +96,7 @@ def construct(self):
                 %%manim -v WARNING --disable_caching -qm BannerExample
 
                 config.media_width = "75%"
+                config.media_embed = True
 
                 class BannerExample(Scene):
                     def construct(self):
@@ -112,6 +121,7 @@ def construct(self):
             if not len(args) or "-h" in args or "--help" in args or "--version" in args:
                 main(args, standalone_mode=False, prog_name="manim")
                 return
+
             modified_args = self.add_additional_args(args)
             args = main(modified_args, standalone_mode=False, prog_name="manim")
             with tempconfig(local_ns.get("config", {})):
@@ -163,20 +173,23 @@ def construct(self):
                 shutil.copy(local_path, tmpfile)
 
                 file_type = mimetypes.guess_type(config["output_file"])[0]
-                if file_type.startswith("image"):
-                    display(Image(filename=config["output_file"]))
-                    return
+                embed = config["media_embed"]
+                if embed is None:
+                    # videos need to be embedded when running in google colab.
+                    # do this automatically in case config.media_embed has not been
+                    # set explicitly.
+                    embed = "google.colab" in str(get_ipython())
 
-                # videos need to be embedded when running in google colab
-                video_embed = "google.colab" in str(get_ipython())
-
-                display(
-                    Video(
+                if file_type.startswith("image"):
+                    result = Image(filename=config["output_file"], embed=embed)
+                else:
+                    result = Video(
                         tmpfile,
                         html_attributes=f'controls autoplay loop style="max-width: {config["media_width"]};"',
-                        embed=video_embed,
-                    ),
-                )
+                        embed=embed,
+                    )
+
+                display(result)
 
         def add_additional_args(self, args: list[str]) -> list[str]:
             additional_args = ["--jupyter"]


Test patch: