Repository: ManimCommunity/manim

Issue:
CLI output does not point to the right file/folder when rendering in a non-mp4 format
## Description of bug / unexpected behavior
```
C:\Users\Daryl\manim-videos\manim-videos>manim --format gif circletest.py
Manim Community v0.6.0

[05/17/21 17:47:53] INFO     Animation 0 : Partial movie file written in {'C:\\Users\\Daryl\\m scene_file_writer.py:401
                             anim-videos\\manim-videos\\media\\videos\\circletest\\1080p60\\pa
                             rtial_movie_files\\CircleTest\\450974505_3098578322_3198892316.mp
                             4'}
[05/17/21 17:47:54] INFO                                                                       scene_file_writer.py:585
                             File ready at C:\Users\Daryl\manim-videos\manim-videos\media\vide
                             os\circletest\1080p60\CircleTest.mp4

                    INFO     Rendered CircleTest                                                           scene.py:217
                             Played 1 animations
```
The output points to `CircleTest.mp4` while it should actually be `CircleTest_ManimCE_v0.6.0.gif` (also the name is different, not sure if this is intended). `--format png` also points to the same wrong place when it should point to `media\images\circletest`. 

## Expected behavior
<!-- Add a clear and concise description of what you expected to happen. -->


## How to reproduce the issue
<!-- Provide a piece of code illustrating the undesired behavior. -->

<details><summary>Code for reproducing the problem</summary>

```py
from manim import *

class CircleTest(Scene):
    def construct(self):
        a = Circle()
        self.play(Create(a))
```

</details>


## Additional media files
<!-- Paste in the files manim produced on rendering the code above. -->

<details><summary>Images/GIFs</summary>

<!-- PASTE MEDIA HERE -->

</details>


## Logs
<details><summary>Terminal output</summary>
<!-- Add "-v DEBUG" when calling manim to generate more detailed logs -->

```
PASTE HERE OR PROVIDE LINK TO https://pastebin.com/ OR SIMILAR
```

<!-- Insert screenshots here (only when absolutely necessary, we prefer copy/pasted output!) -->

</details>


## System specifications

<details><summary>System Details</summary>

- OS (with version, e.g Windows 10 v2004 or macOS 10.15 (Catalina)):
- RAM:
- Python version (`python/py/python3 --version`):
- Installed modules (provide output from `pip list`):
```
PASTE HERE
```
</details>

<details><summary>LaTeX details</summary>

+ LaTeX distribution (e.g. TeX Live 2020):
+ Installed LaTeX packages:
<!-- output of `tlmgr list --only-installed` for TeX Live or a screenshot of the Packages page for MikTeX -->
</details>

<details><summary>FFMPEG</summary>

Output of `ffmpeg -version`:

```
PASTE HERE
```
</details>

## Additional comments
<!-- Add further context that you think might be relevant for this issue here. -->

Formatting to png does not give any output when run with caching enabled, and the scene has already been rendered to any file format
## Description of bug / unexpected behavior
Running
```
C:\Users\Daryl\manim-videos\manim-videos>manim --format png circletest.py
Manim Community v0.6.0

[05/17/21 17:54:39] INFO     Animation 0 : Using cached data (hash :                              cairo_renderer.py:100
                             450974505_3098578322_3198892316)
                    INFO                                                                       scene_file_writer.py:585
                             File ready at C:\Users\Daryl\manim-videos\manim-videos\media\vide
                             os\circletest\1080p60\CircleTest.mp4

                    INFO     Rendered CircleTest                                                           scene.py:217
                             Played 1 animations
```
after running the scene normally (and formatting to mp4) does not produce any images. Running
```
C:\Users\Daryl\manim-videos\manim-videos>manim --format png --disable_caching circletest.py
Manim Community v0.6.0

[05/17/21 17:55:07] INFO     Caching disabled.                                                     cairo_renderer.py:93
[05/17/21 17:55:11] INFO     Animation 0 : Partial movie file written in {'C:\\Users\\Daryl\\m scene_file_writer.py:401
                             anim-videos\\manim-videos\\media\\videos\\circletest\\1080p60\\pa
                             rtial_movie_files\\CircleTest\\uncached_00000.mp4'}
                    INFO                                                                       scene_file_writer.py:585
                             File ready at C:\Users\Daryl\manim-videos\manim-videos\media\vide
                             os\circletest\1080p60\CircleTest.mp4

                    INFO     Rendered CircleTest                                                           scene.py:217
                             Played 1 animations
```
correctly creates the images in the images folder.

## Expected behavior
<!-- Add a clear and concise description of what you expected to happen. -->


## How to reproduce the issue
<!-- Provide a piece of code illustrating the undesired behavior. -->

<details><summary>Code for reproducing the problem</summary>

```py
Paste your code here.
```

</details>


## Additional media files
<!-- Paste in the files manim produced on rendering the code above. -->

<details><summary>Images/GIFs</summary>

<!-- PASTE MEDIA HERE -->

</details>


## Logs
<details><summary>Terminal output</summary>
<!-- Add "-v DEBUG" when calling manim to generate more detailed logs -->

```
PASTE HERE OR PROVIDE LINK TO https://pastebin.com/ OR SIMILAR
```

<!-- Insert screenshots here (only when absolutely necessary, we prefer copy/pasted output!) -->

</details>


## System specifications

<details><summary>System Details</summary>

- OS (with version, e.g Windows 10 v2004 or macOS 10.15 (Catalina)):
- RAM:
- Python version (`python/py/python3 --version`):
- Installed modules (provide output from `pip list`):
```
PASTE HERE
```
</details>

<details><summary>LaTeX details</summary>

+ LaTeX distribution (e.g. TeX Live 2020):
+ Installed LaTeX packages:
<!-- output of `tlmgr list --only-installed` for TeX Live or a screenshot of the Packages page for MikTeX -->
</details>

<details><summary>FFMPEG</summary>

Output of `ffmpeg -version`:

```
PASTE HERE
```
</details>

## Additional comments
<!-- Add further context that you think might be relevant for this issue here. -->



Discussion:
I could start looking at this issue if nobody else is? What is the expected behaviour for --format "png"? I can see setting this format means that it does save frames as images in the 'media\images\circletest' but will still output an mp4 video based on the 'write_to_movie' flag.
I believe the expected behavior should just be to output PNGs. It doesn't make sense to also output an mp4, IMO.
I agree, but having a flag 'write_to_movie' seems redundant when there is --format mp4, and having both the option to write_to_movie and setting the format to png or gif makes it less clear what the user wants to do. Are there any objections to deprecating write_to_movie and using --format mp4 instead?

It seems that adding the version only to gif filenames was intentional as gifs can't have the manim version set as metadata [984](https://github.com/ManimCommunity/manim/pull/984)
I added a fix for this issue in #1595 as it was closely related to #1532

Resolving patch:
diff --git a/manim/scene/scene_file_writer.py b/manim/scene/scene_file_writer.py
--- a/manim/scene/scene_file_writer.py
+++ b/manim/scene/scene_file_writer.py
@@ -2,7 +2,6 @@
 
 __all__ = ["SceneFileWriter"]
 
-
 import datetime
 import os
 import shutil
@@ -22,7 +21,10 @@
     add_extension_if_not_present,
     add_version_before_extension,
     guarantee_existence,
+    is_gif_format,
+    is_png_format,
     modify_atime,
+    write_to_movie,
 )
 from ..utils.sounds import get_full_sound_file_path
 
@@ -86,7 +88,7 @@ def init_output_directories(self, scene_name):
             image_dir, add_extension_if_not_present(default_name, ".png")
         )
 
-        if config["write_to_movie"]:
+        if write_to_movie():
             movie_dir = guarantee_existence(
                 config.get_dir("video_dir", module_name=module_name)
             )
@@ -97,7 +99,7 @@ def init_output_directories(self, scene_name):
                     default_name, config["movie_file_extension"]
                 ),
             )
-            if config["format"] == "gif":
+            if is_gif_format():
                 self.gif_file_path = os.path.join(
                     movie_dir,
                     add_extension_if_not_present(default_name, GIF_FILE_EXTENSION),
@@ -119,7 +121,7 @@ def add_partial_movie_file(self, hash_animation):
         hash_animation : str
             Hash of the animation.
         """
-        if not hasattr(self, "partial_movie_directory"):
+        if not hasattr(self, "partial_movie_directory") or not write_to_movie():
             return
 
         # None has to be added to partial_movie_files to keep the right index with scene.num_plays.
@@ -252,7 +254,7 @@ def begin_animation(self, allow_write=False, file_path=None):
         allow_write : bool, optional
             Whether or not to write to a video file.
         """
-        if config["write_to_movie"] and allow_write:
+        if write_to_movie() and allow_write:
             self.open_movie_pipe(file_path=file_path)
 
     def end_animation(self, allow_write=False):
@@ -265,7 +267,7 @@ def end_animation(self, allow_write=False):
         allow_write : bool, optional
             Whether or not to write to a video file.
         """
-        if config["write_to_movie"] and allow_write:
+        if write_to_movie() and allow_write:
             self.close_movie_pipe()
 
     def write_frame(self, frame_or_renderer):
@@ -285,11 +287,13 @@ def write_frame(self, frame_or_renderer):
             )
         else:
             frame = frame_or_renderer
-            if config["write_to_movie"]:
+            if write_to_movie():
                 self.writing_process.stdin.write(frame.tobytes())
-            if config["format"] == "png":
-                path, extension = os.path.splitext(self.image_file_path)
-                Image.fromarray(frame).save(f"{path}{self.frame_count}{extension}")
+            if is_png_format():
+                target_dir, extension = os.path.splitext(self.image_file_path)
+                Image.fromarray(frame).save(
+                    f"{target_dir}{self.frame_count}{extension}"
+                )
                 self.frame_count += 1
 
     def save_final_image(self, image):
@@ -329,13 +333,14 @@ def idle_stream(self):
 
     def finish(self, partial_movie_files=None):
         """
-        Finishes writing to the FFMPEG buffer.
+        Finishes writing to the FFMPEG buffer or writing images
+        to output directory.
         Combines the partial movie files into the
         whole scene.
         If save_last_frame is True, saves the last
         frame in the default image directory.
         """
-        if config["write_to_movie"]:
+        if write_to_movie():
             if hasattr(self, "writing_process"):
                 self.writing_process.terminate()
             self.combine_movie_files(partial_movie_files=partial_movie_files)
@@ -343,6 +348,9 @@ def finish(self, partial_movie_files=None):
                 self.flush_cache_directory()
             else:
                 self.clean_cache()
+        elif is_png_format():
+            target_dir, _ = os.path.splitext(self.image_file_path)
+            logger.info("\n%i images ready at %s\n", self.frame_count, target_dir)
 
     def open_movie_pipe(self, file_path=None):
         """
@@ -416,7 +424,7 @@ def is_already_cached(self, hash_invocation):
         :class:`bool`
             Whether the file exists.
         """
-        if not hasattr(self, "partial_movie_directory"):
+        if not hasattr(self, "partial_movie_directory") or not write_to_movie():
             return False
         path = os.path.join(
             self.partial_movie_directory,
@@ -474,10 +482,10 @@ def combine_movie_files(self, partial_movie_files=None):
             "-nostdin",
         ]
 
-        if config["write_to_movie"] and not config["format"] == "gif":
+        if write_to_movie() and not is_gif_format():
             commands += ["-c", "copy", movie_file_path]
 
-        if config["format"] == "gif":
+        if is_gif_format():
             if not config["output_file"]:
                 self.gif_file_path = str(
                     add_version_before_extension(self.gif_file_path)
@@ -535,9 +543,9 @@ def combine_movie_files(self, partial_movie_files=None):
             os.remove(sound_file_path)
 
         self.print_file_ready_message(
-            self.gif_file_path if config["save_as_gif"] else movie_file_path
+            self.gif_file_path if is_gif_format() else movie_file_path
         )
-        if config["write_to_movie"]:
+        if write_to_movie():
             for file_path in partial_movie_files:
                 # We have to modify the accessed time so if we have to clean the cache we remove the one used the longest.
                 modify_atime(file_path)
diff --git a/manim/utils/file_ops.py b/manim/utils/file_ops.py
--- a/manim/utils/file_ops.py
+++ b/manim/utils/file_ops.py
@@ -6,9 +6,12 @@
     "seek_full_path_from_defaults",
     "modify_atime",
     "open_file",
+    "is_mp4_format",
+    "is_gif_format",
+    "is_png_format",
+    "write_to_movie",
 ]
 
-
 import os
 import platform
 import subprocess as sp
@@ -21,6 +24,61 @@
 from .. import console
 
 
+def is_mp4_format() -> bool:
+    """
+    Determines if output format is .mp4
+
+    Returns
+    -------
+    class:`bool`
+        ``True`` if format is set as mp4
+
+    """
+    return config["format"] == "mp4"
+
+
+def is_gif_format() -> bool:
+    """
+    Determines if output format is .gif
+
+    Returns
+    -------
+    class:`bool`
+        ``True`` if format is set as gif
+
+    """
+    return config["format"] == "gif"
+
+
+def is_png_format() -> bool:
+    """
+    Determines if output format is .png
+
+    Returns
+    -------
+    class:`bool`
+        ``True`` if format is set as png
+
+    """
+    return config["format"] == "png"
+
+
+def write_to_movie() -> bool:
+    """
+    Determines from config if the output is a video format such as mp4 or gif, if the --format is set as 'png'
+    then it will take precedence event if the write_to_movie flag is set
+
+    Returns
+    -------
+    class:`bool`
+        ``True`` if the output should be written in a movie format
+
+    """
+    if is_png_format():
+        return False
+    return config["write_to_movie"] or is_mp4_format() or is_gif_format()
+
+
 def add_extension_if_not_present(file_name, extension):
     if file_name.suffix != extension:
         return file_name.with_suffix(extension)
@@ -87,9 +145,9 @@ def open_media_file(file_writer):
 
     if config["save_last_frame"]:
         file_paths.append(file_writer.image_file_path)
-    if config["write_to_movie"] and not config["format"] == "gif":
+    if write_to_movie() and not is_gif_format():
         file_paths.append(file_writer.movie_file_path)
-    if config["format"] == "gif":
+    if write_to_movie() and is_gif_format():
         file_paths.append(file_writer.gif_file_path)
 
     for file_path in file_paths:


Test patch:
diff --git a/tests/test_scene_rendering/test_cli_flags.py b/tests/test_scene_rendering/test_cli_flags.py
--- a/tests/test_scene_rendering/test_cli_flags.py
+++ b/tests/test_scene_rendering/test_cli_flags.py
@@ -224,3 +224,142 @@ def test_dash_as_filename(tmp_path):
         tmp_path / "images" / "-" / "Test.png"
     ).exists()
     assert exists, result.output
+
+
+@pytest.mark.slow
+def test_gif_format_output(tmp_path, manim_cfg_file, simple_scenes_path):
+    """Test only gif created with manim version in file name when --format gif is set"""
+    scene_name = "SquareToCircle"
+    command = [
+        sys.executable,
+        "-m",
+        "manim",
+        "-ql",
+        "--media_dir",
+        str(tmp_path),
+        "--format",
+        "gif",
+        simple_scenes_path,
+        scene_name,
+    ]
+    out, err, exit_code = capture(command)
+    assert exit_code == 0, err
+
+    unexpected_mp4_path = (
+        tmp_path / "videos" / "simple_scenes" / "480p15" / "SquareToCircle.mp4"
+    )
+    assert not unexpected_mp4_path.exists(), "unexpected mp4 file found at " + str(
+        unexpected_mp4_path
+    )
+
+    expected_gif_path = (
+        tmp_path
+        / "videos"
+        / "simple_scenes"
+        / "480p15"
+        / add_version_before_extension("SquareToCircle.gif")
+    )
+    assert expected_gif_path.exists(), "gif file not found at " + str(expected_gif_path)
+
+
+@pytest.mark.slow
+def test_mp4_format_output(tmp_path, manim_cfg_file, simple_scenes_path):
+    """Test only mp4 created without manim version in file name when --format mp4 is set"""
+    scene_name = "SquareToCircle"
+    command = [
+        sys.executable,
+        "-m",
+        "manim",
+        "-ql",
+        "--media_dir",
+        str(tmp_path),
+        "--format",
+        "mp4",
+        simple_scenes_path,
+        scene_name,
+    ]
+    out, err, exit_code = capture(command)
+    assert exit_code == 0, err
+
+    unexpected_gif_path = (
+        tmp_path
+        / "videos"
+        / "simple_scenes"
+        / "480p15"
+        / add_version_before_extension("SquareToCircle.gif")
+    )
+    assert not unexpected_gif_path.exists(), "unexpected gif file found at " + str(
+        unexpected_gif_path
+    )
+
+    expected_mp4_path = (
+        tmp_path / "videos" / "simple_scenes" / "480p15" / "SquareToCircle.mp4"
+    )
+    assert expected_mp4_path.exists(), "expected mp4 file not found at " + str(
+        expected_mp4_path
+    )
+
+
+@pytest.mark.slow
+def test_videos_not_created_when_png_format_set(
+    tmp_path, manim_cfg_file, simple_scenes_path
+):
+    """Test mp4 and gifs are not created when --format png is set"""
+    scene_name = "SquareToCircle"
+    command = [
+        sys.executable,
+        "-m",
+        "manim",
+        "-ql",
+        "--media_dir",
+        str(tmp_path),
+        "--format",
+        "png",
+        simple_scenes_path,
+        scene_name,
+    ]
+    out, err, exit_code = capture(command)
+    assert exit_code == 0, err
+
+    unexpected_gif_path = (
+        tmp_path
+        / "videos"
+        / "simple_scenes"
+        / "480p15"
+        / add_version_before_extension("SquareToCircle.gif")
+    )
+    assert not unexpected_gif_path.exists(), "unexpected gif file found at " + str(
+        unexpected_gif_path
+    )
+
+    unexpected_mp4_path = (
+        tmp_path / "videos" / "simple_scenes" / "480p15" / "SquareToCircle.mp4"
+    )
+    assert not unexpected_mp4_path.exists(), "expected mp4 file not found at " + str(
+        unexpected_mp4_path
+    )
+
+
+@pytest.mark.slow
+def test_images_are_created_when_png_format_set(
+    tmp_path, manim_cfg_file, simple_scenes_path
+):
+    """Test images are created in media directory when --format png is set"""
+    scene_name = "SquareToCircle"
+    command = [
+        sys.executable,
+        "-m",
+        "manim",
+        "-ql",
+        "--media_dir",
+        str(tmp_path),
+        "--format",
+        "png",
+        simple_scenes_path,
+        scene_name,
+    ]
+    out, err, exit_code = capture(command)
+    assert exit_code == 0, err
+
+    expected_png_path = tmp_path / "images" / "simple_scenes" / "SquareToCircle0.png"
+    assert expected_png_path.exists(), "png file not found at " + str(expected_png_path)