ManimCommunity / manim

A community-maintained Python framework for creating mathematical animations.
https://www.manim.community
MIT License
21.01k stars 1.53k forks source link

`AddTextLetterByLetter()` with blank `MarkupText` renders broken partial movie #3378

Closed HairlessVillager closed 10 months ago

HairlessVillager commented 12 months ago

Description of bug / unexpected behavior

When use AddTextLetterByLetter() to render an animation for a blank MarkupText(e.g. MarkupText('<span bgcolor="#777777"></span>')), manim will render a broken video, which cannot be opened by Media Player in Windows or decoded by ffmpeg. In --preview, a FileNotFoundError will be thrown by manim. This bug will occur when another scene's movie has been rendered before.

Expected behavior

Just be like AddTextLetterByLetter(Text("")).

How to reproduce the issue

  1. Delete media/videos/problem_recurrence if exists.
  2. Run manim problem_recurrence.py TextCreateScene.
  3. Run manim problem_recurrence.py MarkupTextAddTextLetterByLetterScene.
  4. Try open media/videos/problem_recurrence/1080p60/partial_movie_files/MarkupTextAddTextLetterByLetterScene/1413466013_3861299098_223132457.mp4(hash maybe change) with Media Player, failed with some info: pPTjqZF.png
  5. Try encode it by ffmpeg -i 1413466013_3861299098_223132457.mp4 -r 1 %03d.png, failed with info Output file #0 does not contain any stream.
    Code for reproducing the problem
""" problem_recurrence.py
"""
from manim import *

class TextCreateScene(Scene):

    def construct(self):
        text = Text("some harmless text")
        self.play(Create(text))

class MarkupTextAddTextLetterByLetterScene(Scene):

    def construct(self):
        blank_markup_text = MarkupText('<span bgcolor="#777777"></span>')
        self.play(AddTextLetterByLetter(blank_markup_text))

Additional media files

No additional media file becasue it's broken.

Images/GIFs

Logs

Terminal output ``` (visualcode) E:\code\python\visualcode>manim problem_recurrence.py TextCreateScene -v DEBUG Manim Community v0.17.3 [09/24/23 18:34:20] DEBUG Hashing ... hashing.py:350 DEBUG Hashing done in 0.108516 s. hashing.py:362 DEBUG Hash generated : 1413466013_3703300622_223132457 hashing.py:365 DEBUG List of the first few animation hashes of the scene: cairo_renderer.py:87 ['1413466013_3703300622_223132457'] [09/24/23 18:34:22] INFO Animation 0 : Partial movie file written in scene_file_writer.py:527 'E:\code\python\visualcode\media\videos\problem_recurrence\ 1080p60\partial_movie_files\TextCreateScene\1413466013_3703 300622_223132457.mp4' INFO Combining to Movie file. scene_file_writer.py:617 DEBUG Partial movie files to combine (1 files): scene_file_writer.py:561 ['E:\\code\\python\\visualcode\\media\\videos\\problem_recu rrence\\1080p60\\partial_movie_files\\TextCreateScene\\1413 466013_3703300622_223132457.mp4'] INFO scene_file_writer.py:736 File ready at 'E:\code\python\visualcode\media\videos\problem_recurrence\ 1080p60\TextCreateScene.mp4' INFO Rendered TextCreateScene scene.py:241 Played 1 animations (visualcode) E:\code\python\visualcode>manim problem_recurrence.py MarkupTextAddTextLetterByLetterScene -v DEBUG Manim Community v0.17.3 [09/24/23 18:34:38] DEBUG Hashing ... hashing.py:350 DEBUG Hashing done in 0.007872 s. hashing.py:362 DEBUG Hash generated : 1413466013_3861299098_223132457 hashing.py:365 DEBUG List of the first few animation hashes of the scene: cairo_renderer.py:87 ['1413466013_3861299098_223132457'] INFO Animation 0 : Partial movie file written in scene_file_writer.py:527 'E:\code\python\visualcode\media\videos\problem_recurrence\ 1080p60\partial_movie_files\MarkupTextAddTextLetterByLetter Scene\1413466013_3861299098_223132457.mp4' INFO Combining to Movie file. scene_file_writer.py:617 DEBUG Partial movie files to combine (1 files): scene_file_writer.py:561 ['E:\\code\\python\\visualcode\\media\\videos\\problem_recu rrence\\1080p60\\partial_movie_files\\MarkupTextAddTextLett erByLetterScene\\1413466013_3861299098_223132457.mp4'] Output file #0 does not contain any stream INFO scene_file_writer.py:736 File ready at 'E:\code\python\visualcode\media\videos\problem_recurrence\ 1080p60\MarkupTextAddTextLetterByLetterScene.mp4' INFO Rendered MarkupTextAddTextLetterByLetterScene scene.py:241 Played 1 animations ```

System specifications

System Details - OS: Windows 10 22H2 19045.3448 - RAM: 16.0 GB - Python version: Python 3.8.18 - Installed modules (provide output from `pip list`): ``` Package Version -------------------- --------- asttokens 2.4.0 attrs 23.1.0 backcall 0.2.0 Brotli 1.1.0 build 0.10.0 CacheControl 0.13.1 certifi 2023.7.22 cffi 1.15.1 charset-normalizer 3.2.0 cleo 2.0.1 click 8.1.7 click-default-group 1.2.4 cloup 0.13.1 colorama 0.4.6 colour 0.1.5 contourpy 1.1.1 crashtest 0.4.1 cryptography 41.0.4 cycler 0.11.0 dataclasses 0.8 decorator 5.1.1 distlib 0.3.7 dulwich 0.21.6 executing 1.2.0 filelock 3.12.4 fonttools 4.42.1 future 0.18.3 glcontext 2.3.7 idna 3.4 importlib-metadata 6.8.0 importlib-resources 6.0.1 installer 0.7.0 ipython 8.12.2 isosurfaces 0.1.0 jaraco.classes 3.3.0 jedi 0.19.0 jsonschema 4.17.3 keyring 24.2.0 kiwisolver 1.4.5 manim 0.17.3 ManimPango 0.4.3 mapbox-earcut 1.0.0 markdown-it-py 3.0.0 matplotlib 3.7.3 matplotlib-inline 0.1.6 mdurl 0.1.0 moderngl 5.8.2 moderngl-window 2.4.1 more-itertools 10.1.0 mpmath 1.3.0 msgpack 1.0.5 multipledispatch 0.6.0 networkx 2.8.8 numpy 1.24.4 packaging 23.1 parso 0.8.3 pexpect 4.8.0 pickleshare 0.7.5 Pillow 9.5.0 pip 23.2.1 pkginfo 1.9.6 pkgutil_resolve_name 1.3.10 platformdirs 3.10.0 poetry 1.6.1 poetry-core 1.7.0 poetry-plugin-export 1.5.0 pooch 1.7.0 prompt-toolkit 3.0.39 ptyprocess 0.7.0 pure-eval 0.2.2 pycairo 1.24.0 pycparser 2.21 pydub 0.25.1 pyglet 1.5.27 Pygments 2.15.1 PyOpenGL 3.1.7 pyOpenSSL 23.2.0 pyparsing 3.1.1 pyperclip 1.8.2 pyproject_hooks 1.0.0 pyrr 0.10.3 pyrsistent 0.19.3 PySocks 1.7.1 python-dateutil 2.8.2 pywin32-ctypes 0.2.2 PyYAML 6.0.1 rapidfuzz 2.15.1 requests 2.31.0 requests-toolbelt 1.0.0 rich 13.5.3 scipy 1.10.1 screeninfo 0.8.1 setuptools 68.0.0 shellingham 1.5.3 six 1.16.0 skia-pathops 0.7.4 srt 3.5.2 stack-data 0.6.2 svgelements 1.9.6 sympy 1.12 tomli 2.0.1 tomlkit 0.12.1 tqdm 4.66.1 traitlets 5.10.0 trove-classifiers 2023.9.19 typing_extensions 4.8.0 urllib3 2.0.5 validators 0.22.0 virtualenv 20.24.4 watchdog 2.2.1 wcwidth 0.2.6 wheel 0.38.4 win-inet-pton 1.1.0 zipp 3.17.0 ```
LaTeX details + LaTeX distribution: Version 3.141592653 (TeX Live 2022) + Installed LaTeX packages: default, see [Installed LaTeX packages.txt](https://github.com/ManimCommunity/manim/files/12708286/Installed.LaTeX.packages.txt)
FFMPEG Output of `ffmpeg -version`: ``` ffmpeg version 4.3.1 Copyright (c) 2000-2020 the FFmpeg developers built with gcc 10.2.1 (GCC) 20200726 configuration: --disable-static --enable-shared --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libsrt --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libgsm --enable-librav1e --disable-w32threads --enable-libmfx --enable-ffnvcodec --enable-cuda-llvm --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt --enable-amf libavutil 56. 51.100 / 56. 51.100 libavcodec 58. 91.100 / 58. 91.100 libavformat 58. 45.100 / 58. 45.100 libavdevice 58. 10.100 / 58. 10.100 libavfilter 7. 85.100 / 7. 85.100 libswscale 5. 7.100 / 5. 7.100 libswresample 3. 7.100 / 3. 7.100 libpostproc 55. 7.100 / 55. 7.100 ```

Additional comments

visualcode is a conda environment.

Output of `conda list` ``` (visualcode) E:\code\python\visualcode>conda list # packages in environment at D:\Anaconda\anaconda3\envs\visualcode: # # Name Version Build Channel asttokens 2.4.0 pypi_0 pypi attrs 23.1.0 pyh71513ae_1 conda-forge backcall 0.2.0 pypi_0 pypi brotli-python 1.1.0 py38hd3f51b4_0 conda-forge bzip2 1.0.8 h8ffe710_4 conda-forge ca-certificates 2023.08.22 haa95532_0 cachecontrol 0.13.1 pyhd8ed1ab_0 conda-forge cachecontrol-with-filecache 0.13.1 pyhd8ed1ab_0 conda-forge cairo 1.16.0 h412253b_1017 conda-forge certifi 2023.7.22 py38haa95532_0 cffi 1.15.1 py38h57701bc_3 conda-forge charset-normalizer 3.2.0 pyhd8ed1ab_0 conda-forge cleo 2.0.1 pyhd8ed1ab_0 conda-forge click 8.1.7 win_pyh7428d3b_0 conda-forge click-default-group 1.2.4 pyhd8ed1ab_0 conda-forge cloup 0.13.1 pyhd8ed1ab_0 conda-forge colorama 0.4.6 pyhd8ed1ab_0 conda-forge colour 0.1.5 pypi_0 pypi contourpy 1.1.1 pypi_0 pypi crashtest 0.4.1 pyhd8ed1ab_0 conda-forge cryptography 41.0.4 py38h95f5157_0 conda-forge cycler 0.11.0 pypi_0 pypi dataclasses 0.8 pyhc8e2a94_3 conda-forge decorator 5.1.1 pyhd8ed1ab_0 conda-forge distlib 0.3.7 pyhd8ed1ab_0 conda-forge dulwich 0.21.6 py38h91455d4_0 conda-forge executing 1.2.0 pypi_0 pypi expat 2.5.0 h63175ca_1 conda-forge ffmpeg 4.3.1 ha925a31_0 conda-forge filelock 3.12.4 pyhd8ed1ab_0 conda-forge font-ttf-dejavu-sans-mono 2.37 hab24e00_0 conda-forge font-ttf-inconsolata 3.000 h77eed37_0 conda-forge font-ttf-source-code-pro 2.038 h77eed37_0 conda-forge font-ttf-ubuntu 0.83 hab24e00_0 conda-forge fontconfig 2.14.2 hbde0cde_0 conda-forge fonts-conda-ecosystem 1 0 conda-forge fonts-conda-forge 1 0 conda-forge fonttools 4.42.1 pypi_0 pypi freetype 2.12.1 hdaf720e_2 conda-forge fribidi 1.0.10 h8d14728_0 conda-forge future 0.18.3 pyhd8ed1ab_0 conda-forge gettext 0.21.1 h5728263_0 conda-forge glcontext 2.4.0 pypi_0 pypi glib 2.78.0 h12be248_0 conda-forge glib-tools 2.78.0 h12be248_0 conda-forge graphite2 1.3.13 1000 conda-forge harfbuzz 8.2.1 h7ab893a_0 conda-forge icu 73.2 h63175ca_0 conda-forge idna 3.4 pyhd8ed1ab_0 conda-forge importlib-metadata 6.8.0 pyha770c72_0 conda-forge importlib-resources 6.1.0 pypi_0 pypi importlib_metadata 6.8.0 hd8ed1ab_0 conda-forge importlib_resources 6.0.1 pyhd8ed1ab_0 conda-forge intel-openmp 2023.2.0 h57928b3_49502 conda-forge ipython 8.12.2 pypi_0 pypi isosurfaces 0.1.0 pyhd8ed1ab_0 conda-forge jaraco.classes 3.3.0 pyhd8ed1ab_0 conda-forge jedi 0.19.0 pypi_0 pypi jsonschema 4.17.3 pyhd8ed1ab_0 conda-forge keyring 24.2.0 py38haa244fe_0 conda-forge kiwisolver 1.4.5 pypi_0 pypi lcms2 2.15 h3e3b177_1 conda-forge lerc 4.0.0 h63175ca_0 conda-forge libblas 3.9.0 18_win64_mkl conda-forge libcblas 3.9.0 18_win64_mkl conda-forge libdeflate 1.18 hcfcfb64_0 conda-forge libexpat 2.5.0 h63175ca_1 conda-forge libffi 3.4.4 hd77b12b_0 libglib 2.78.0 he8f3873_0 conda-forge libhwloc 2.9.2 default_haede6df_1009 conda-forge libiconv 1.17 h8ffe710_0 conda-forge libjpeg-turbo 2.1.5.1 hcfcfb64_1 conda-forge liblapack 3.9.0 18_win64_mkl conda-forge libpng 1.6.39 h19919ed_0 conda-forge libtiff 4.5.1 h6c8260b_1 conda-forge libwebp-base 1.3.2 hcfcfb64_0 conda-forge libxcb 1.15 hcd874cb_0 conda-forge libxml2 2.11.5 hc3477c8_1 conda-forge libzlib 1.2.13 hcfcfb64_5 conda-forge m2w64-gcc-libgfortran 5.3.0 6 conda-forge m2w64-gcc-libs 5.3.0 7 conda-forge m2w64-gcc-libs-core 5.3.0 7 conda-forge m2w64-gmp 6.1.0 2 conda-forge m2w64-libwinpthread-git 5.0.0.4634.697f757 2 conda-forge manim 0.17.3 pyhd8ed1ab_0 conda-forge manimpango 0.4.3 py38hd9736c4_0 conda-forge mapbox-earcut 1.0.1 pypi_0 pypi mapbox_earcut 1.0.0 py38hb1fd069_5 conda-forge markdown-it-py 3.0.0 pyhd8ed1ab_0 conda-forge matplotlib 3.7.3 pypi_0 pypi matplotlib-inline 0.1.6 pypi_0 pypi mdurl 0.1.2 pypi_0 pypi mkl 2022.1.0 h6a75c08_874 conda-forge moderngl 5.8.2 py38h5846ac1_0 conda-forge moderngl-window 2.4.4 pypi_0 pypi more-itertools 10.1.0 pyhd8ed1ab_0 conda-forge mpmath 1.3.0 pypi_0 pypi msgpack-python 1.0.5 py38hb1fd069_0 conda-forge msys2-conda-epoch 20160418 1 conda-forge multipledispatch 1.0.0 pypi_0 pypi networkx 2.8.8 pyhd8ed1ab_0 conda-forge numpy 1.24.4 py38h1d91fd2_0 conda-forge openjpeg 2.5.0 ha2aaf27_2 conda-forge openssl 3.1.3 hcfcfb64_0 conda-forge packaging 23.1 pyhd8ed1ab_0 conda-forge pango 1.50.14 h07c897b_2 conda-forge parso 0.8.3 pypi_0 pypi pcre2 10.40 h17e33f8_0 conda-forge pexpect 4.8.0 pyh1a96a4e_2 conda-forge pickleshare 0.7.5 pypi_0 pypi pillow 9.5.0 py38ha7eb54a_1 conda-forge pip 23.2.1 py38haa95532_0 pixman 0.40.0 h8ffe710_0 conda-forge pkginfo 1.9.6 pyhd8ed1ab_0 conda-forge pkgutil-resolve-name 1.3.10 pyhd8ed1ab_1 conda-forge platformdirs 3.10.0 pyhd8ed1ab_0 conda-forge poetry 1.6.1 win_pyh7428d3b_0 conda-forge poetry-core 1.7.0 pyhd8ed1ab_0 conda-forge poetry-plugin-export 1.5.0 pyhd8ed1ab_0 conda-forge pooch 1.7.0 pyha770c72_3 conda-forge prompt-toolkit 3.0.39 pypi_0 pypi pthread-stubs 0.4 hcd874cb_1001 conda-forge pthreads-win32 2.9.1 hfa6e2cd_3 conda-forge ptyprocess 0.7.0 pyhd3deb0d_0 conda-forge pure-eval 0.2.2 pypi_0 pypi pycairo 1.24.0 py38h5818bea_0 conda-forge pycparser 2.21 pyhd8ed1ab_0 conda-forge pydub 0.25.1 pyhd8ed1ab_0 conda-forge pyglet 2.0.9 pypi_0 pypi pygments 2.15.1 py38haa95532_1 pyopengl 3.1.7 pypi_0 pypi pyopenssl 23.2.0 pyhd8ed1ab_1 conda-forge pyparsing 3.1.1 pypi_0 pypi pyperclip 1.8.2 pypi_0 pypi pyproject_hooks 1.0.0 pyhd8ed1ab_0 conda-forge pyrr 0.10.3 py_0 conda-forge pyrsistent 0.19.3 py38h91455d4_0 conda-forge pysocks 1.7.1 pyh0701188_6 conda-forge python 3.8.18 h1aa4202_0 python-build 0.10.0 pyhd8ed1ab_1 conda-forge python-dateutil 2.8.2 pypi_0 pypi python-installer 0.7.0 pyhd8ed1ab_0 conda-forge python_abi 3.8 2_cp38 conda-forge pywin32-ctypes 0.2.2 py38haa244fe_0 conda-forge pyyaml 6.0.1 py38h91455d4_0 conda-forge rapidfuzz 2.15.1 py38hd3f51b4_0 conda-forge requests 2.31.0 pyhd8ed1ab_0 conda-forge requests-toolbelt 1.0.0 pyhd8ed1ab_0 conda-forge rich 13.5.3 pyhd8ed1ab_0 conda-forge scipy 1.10.1 pypi_0 pypi screeninfo 0.8.1 py38haa244fe_1 conda-forge setuptools 68.0.0 py38haa95532_0 shellingham 1.5.3 pyhd8ed1ab_0 conda-forge six 1.16.0 pyh6c4a22f_0 conda-forge skia-pathops 0.8.0.post1 pypi_0 pypi sqlite 3.41.2 h2bbff1b_0 srt 3.5.2 py38haa244fe_5 conda-forge stack-data 0.6.2 pypi_0 pypi svgelements 1.9.6 pyhd8ed1ab_0 conda-forge sympy 1.12 pypi_0 pypi tbb 2021.10.0 h91493d7_0 conda-forge tk 8.6.12 h8ffe710_0 conda-forge tomli 2.0.1 pyhd8ed1ab_0 conda-forge tomlkit 0.12.1 pyha770c72_0 conda-forge tqdm 4.66.1 pyhd8ed1ab_0 conda-forge traitlets 5.10.0 pypi_0 pypi trove-classifiers 2023.9.19 pyhd8ed1ab_0 conda-forge typing-extensions 4.8.0 hd8ed1ab_0 conda-forge typing_extensions 4.8.0 pyha770c72_0 conda-forge ucrt 10.0.22621.0 h57928b3_0 conda-forge urllib3 2.0.5 pyhd8ed1ab_0 conda-forge validators 0.22.0 pypi_0 pypi vc 14.2 h21ff451_1 vc14_runtime 14.36.32532 hdcecf7f_17 conda-forge virtualenv 20.24.4 pyhd8ed1ab_0 conda-forge vs2015_runtime 14.36.32532 h05e6639_17 conda-forge watchdog 2.2.1 py38haa244fe_0 conda-forge wcwidth 0.2.6 pypi_0 pypi wheel 0.38.4 py38haa95532_0 win_inet_pton 1.1.0 pyhd8ed1ab_6 conda-forge xorg-libxau 1.0.11 hcd874cb_0 conda-forge xorg-libxdmcp 1.1.3 hcd874cb_0 conda-forge xz 5.2.6 h8d14728_0 conda-forge yaml 0.2.5 h8ffe710_2 conda-forge zipp 3.17.0 pyhd8ed1ab_0 conda-forge zlib 1.2.13 hcfcfb64_5 conda-forge zstd 1.5.5 h12be248_0 conda-forge ```
Immanuel-Alvaro-Bhirawa commented 11 months ago

Can I please be assigned to this issue? I have some ideas on how I will approach this issue.

  1. Implement an edge case where there are no string input (i.e., "")
  2. Implement an edge case where the function takes the input value of span elements and process it accordingly
  3. Integrate the AddTextLetterByLetter() function within the animation.py class so that it can render animations.

I believe these 3 reasons are what cause the bug to happen.

Immanuel-Alvaro-Bhirawa commented 11 months ago

Hi @HairlessVillager , what output are you looking for when you have an empty input? Are you looking for just a blank render? Or maybe something like "No Input" render?

HairlessVillager commented 11 months ago

Hi @HairlessVillager , what output are you looking for when you have an empty input? Are you looking for just a blank render? Or maybe something like "No Input" render?

Just a blank render. Thanks❤

Immanuel-Alvaro-Bhirawa commented 11 months ago

Alrightt Understood!! I'll try my best haha. Will be in touch with you soon.

Immanuel-Alvaro-Bhirawa commented 11 months ago

Hi HairlessVillager, I have a few comments in regards to the findings that I have made.

It seems that AddTextLetterByLetter will not generate an animation because it has been hard-set to have a minimum input of atleast 1 character. Due to the lack of characters in a blank input (""), AddTextLetterByLetter will not generate an animation / stream and thus encounter a FileNotFoundError that you have stated.

Thus I have a few propositions towards the solutions that you may use.

  1. I found that you can use a class called Create() to render a blank animation with the same input that you use for the AddTextLetterByLetter(). The animation will work almost the same with AddTextLetterByLetter if you use Create() to render Text() that has inputs such as Text("Hello World") for example. However, you can just use Create() to render a blank animation and then use TextLetterByLetter to render inputs that has words.

  2. I will try to create an case within TextLetterByLetter so that when it accepts a blank input i.e., Text(""), it will instead take Text("__________") as an input. Note this is just to simulate a blank input for now and I will change it later if I manage to get this done. Thus, through this way, TextLetterByLetter should render "__" when TextLetterByLetter is run with Text("").

I will try solution number 2 regardless, however, for the meantime, if you need to render a blank animation imperatively, you can use solution number 1 for the moment.

Cheers!

HairlessVillager commented 11 months ago

Hi Immanuel-Alvaro-Bhirawa,

I also think solution No.2 is better for my usage scenarios. In fact, when I first encountered this issue, I was trying to render a source code highlighted with markup. My manim original code is as follows:

""" example.py
"""
from pprint import pprint

from manim import *

from utils import highlight_lines

class ExampleScene(Scene):

    def construct(self):
        with open("example_code.py", encoding="utf-8") as f:
            code = f.read()
        lines = highlight_lines(code)
        lines = lines[:7]
        print(repr(lines))
        for line in lines[:]:
            line = MarkupText(line,
                            font="Consolas",
                            font_size=16)
            line.align_to(ORIGIN, direction=LEFT)
            self.play(AddTextLetterByLetter(line))
            self.wait(1)
            self.clear()
Output in cmd ``` (visualcode) E:\code\python\visualcode>manim example.py Manim Community v0.17.3 ('[\'import ' 're\', \'import scrapy\', \'from moepediacollector.items import MoepediacollectorItem\', \'\', \'\', \'def check_date_format(date):\', \' date_pattern = r\\\'^\\\\d{4}/([1-9]|1[0-2])$\\\'\']') [10/10/23 08:31:00] INFO Animation 0 : Using cached cairo_renderer.py:78 data (hash : 1413466013_3793956554_2231324 57) INFO Animation 1 : Using cached cairo_renderer.py:78 data (hash : 3496982726_3213241947_1765934 598) INFO Animation 2 : Using cached cairo_renderer.py:78 data (hash : 3496982726_2825366727_2231324 57) [10/10/23 08:31:01] INFO Animation 3 : Using cached cairo_renderer.py:78 data (hash : 3496982726_3359312264_2054646 393) INFO Animation 4 : Using cached cairo_renderer.py:78 data (hash : 3496982726_380168235_22313245 7) INFO Animation 5 : Using cached cairo_renderer.py:78 data (hash : 3496982726_3359312264_1759847 926) ┌───────────────────── Traceback (most recent call last) ─────────────────────┐ │ D:\Anaconda\anaconda3\envs\visualcode\lib\site-packages\manim\cli\render\co │ │ mmands.py:115 in render │ │ │ │ 112 │ │ │ try: │ │ 113 │ │ │ │ with tempconfig({}): │ │ 114 │ │ │ │ │ scene = SceneClass() │ │ > 115 │ │ │ │ │ scene.render() │ │ 116 │ │ │ except Exception: │ │ 117 │ │ │ │ error_console.print_exception() │ │ 118 │ │ │ │ sys.exit(1) │ │ │ │ D:\Anaconda\anaconda3\envs\visualcode\lib\site-packages\manim\scene\scene.p │ │ y:223 in render │ │ │ │ 220 │ │ """ │ │ 221 │ │ self.setup() │ │ 222 │ │ try: │ │ > 223 │ │ │ self.construct() │ │ 224 │ │ except EndSceneEarlyException: │ │ 225 │ │ │ pass │ │ 226 │ │ except RerunSceneException as e: │ │ │ │ E:\code\python\visualcode\example.py:19 in construct │ │ │ │ 16 │ │ │ line = MarkupText(line, │ │ 17 │ │ │ │ │ │ │ font="Consolas", │ │ 18 │ │ │ │ │ │ │ font_size=16) │ │ > 19 │ │ │ line.align_to(ORIGIN, direction=LEFT) │ │ 20 │ │ │ self.play(AddTextLetterByLetter(line)) │ │ 21 │ │ │ self.wait(1) │ │ 22 │ │ │ self.clear() │ │ │ │ D:\Anaconda\anaconda3\envs\visualcode\lib\site-packages\manim\mobject\mobje │ │ ct.py:2137 in align_to │ │ │ │ 2134 │ │ │ │ 2135 │ │ for dim in range(self.dim): │ │ 2136 │ │ │ if direction[dim] != 0: │ │ > 2137 │ │ │ │ self.set_coord(point[dim], dim, direction) │ │ 2138 │ │ return self │ │ 2139 │ │ │ 2140 │ # Family matters │ │ │ │ D:\Anaconda\anaconda3\envs\visualcode\lib\site-packages\manim\mobject\mobje │ │ ct.py:1599 in set_coord │ │ │ │ 1596 │ │ return self.rescale_to_fit(depth, 2, stretch=True, **kwargs) │ │ 1597 │ │ │ 1598 │ def set_coord(self, value, dim, direction=ORIGIN): │ │ > 1599 │ │ curr = self.get_coord(dim, direction) │ │ 1600 │ │ shift_vect = np.zeros(self.dim) │ │ 1601 │ │ shift_vect[dim] = value - curr │ │ 1602 │ │ self.shift(shift_vect) │ │ │ │ D:\Anaconda\anaconda3\envs\visualcode\lib\site-packages\manim\mobject\mobje │ │ ct.py:2019 in get_coord │ │ │ │ 2016 │ │ │ 2017 │ def get_coord(self, dim, direction=ORIGIN): │ │ 2018 │ │ """Meant to generalize ``get_x``, ``get_y`` and ``get_z``""" │ │ > 2019 │ │ return self.get_extremum_along_dim(dim=dim, key=direction[di │ │ 2020 │ │ │ 2021 │ def get_x(self, direction=ORIGIN) -> np.float64: │ │ 2022 │ │ """Returns x coordinate of the center of the :class:`~.Mobje │ │ │ │ D:\Anaconda\anaconda3\envs\visualcode\lib\site-packages\manim\mobject\mobje │ │ ct.py:1906 in get_extremum_along_dim │ │ │ │ 1903 │ def get_extremum_along_dim(self, points=None, dim=0, key=0): │ │ 1904 │ │ if points is None: │ │ 1905 │ │ │ points = self.get_points_defining_boundary() │ │ > 1906 │ │ values = points[:, dim] │ │ 1907 │ │ if key < 0: │ │ 1908 │ │ │ return np.min(values) │ │ 1909 │ │ elif key == 0: │ └─────────────────────────────────────────────────────────────────────────────┘ IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed ```

I just can't understand why the first few lines of code were rendered well, and once the blank line("" here) program was rendered, an error occurred. I've tried to use if line == "": line = "-" but it's ugly in the example.py.

Anyway, the above is just a little complaint from me. I should still use solution No.2.

Immanuel-Alvaro-Bhirawa commented 11 months ago

Alright, thank you for the additional information! I'll work on it and try to fix it.

Immanuel-Alvaro-Bhirawa commented 11 months ago

Hi @HairlessVillager , I have found a fix to the issue! It is located in the runtime error. As when the input is blank, there is technically 0 characters in the input (AddTextLetterByLetter tracks the characters from input to render a video), thus there was a runtime of 0 secs which produce the error of "Output file does not contain any stream". This basically means, video run time is 0 secs hence no file are created.

I have found a solution to problem that you are encountering for both the input data type Text and MarkupText. I do have a question however, for a blank render, how long do you want the video to be?

Cheers!

HairlessVillager commented 11 months ago

This is an interesting question. Because when the string length is 0, the video length should also be 0. I actually prefer to make the video length 0. If this cannot be achieved technically, let the video length be the length of rendering one character(like AddTextLetterByLetter(Text("a"))).

Perhaps you could add a strict option that, when strict is True, does not render the video, but instead throws an exception directly? I saw this design in Python's built-in functions before, and I'm not sure if it's in line with Manim's development habits.

Immanuel-Alvaro-Bhirawa commented 11 months ago

A question, do you explicitly want to add a new parameter strict to throw the exception? Because we can still add the exception without adding thew new parameter strict.

Otherwise, so do you want the output to be like this?

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ C:\Users\Imman\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCa │
│ che\local-packages\Python310\site-packages\manim\cli\render\commands.py:115 in render            │
│                                                                                                  │
│   112 │   │   │   try:                                                                           │
│   113 │   │   │   │   with tempconfig({}):                                                       │
│   114 │   │   │   │   │   scene = SceneClass()                                                   │
│ ❱ 115 │   │   │   │   │   scene.render()                                                         │
│   116 │   │   │   except Exception:                                                              │
│   117 │   │   │   │   error_console.print_exception()                                            │
│   118 │   │   │   │   sys.exit(1)                                                                │
│                                                                                                  │
│ C:\Users\Imman\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCa │
│ che\local-packages\Python310\site-packages\manim\scene\scene.py:223 in render                    │
│                                                                                                  │
│    220 │   │   """                                                                               │
│    221 │   │   self.setup()                                                                      │
│    222 │   │   try:                                                                              │
│ ❱  223 │   │   │   self.construct()                                                              │
│    224 │   │   except EndSceneEarlyException:                                                    │
│    225 │   │   │   pass                                                                          │
│    226 │   │   except RerunSceneException as e:                                                  │
│                                                                                                  │
│ C:\Users\Imman\Documents\ANU\COMP2120_Alex\ManimFork\manim\project\scene.py:66 in construct      │
│                                                                                                  │
│   63 │   def construct(self):                                                                    │
│   64 │   │   # blank_markup_text = Text("")                                                      │
│   65 │   │   blank_markup_text = MarkupText('<span bgcolor="#777777"></span>')                   │
│ ❱ 66 │   │   self.play(MyAddTextLetterByLetter(blank_markup_text))                               │
│   67                                                                                             │
│   68                                                                                             │
│   69                                                                                             │
│                                                                                                  │
│ C:\Users\Imman\Documents\ANU\COMP2120_Alex\ManimFork\manim\project\scene.py:33 in __init__       │
│                                                                                                  │
│   30 │   │                                                                                       │
│   31 │   │   if self.is_text_empty(text) or self.is_markup_text_empty(text):                     │
│   32 │   │   │   print("The text is empty")                                                      │
│ ❱ 33 │   │   │   raise ValueError("The input text is empty, and strict mode is enabled")         │
│   34 │   │   │   run_time = 0  # Set the run_time to 5 if the text is empty                      │
│   35 │   │   elif run_time is None:                                                              │
│   36 │   │   │   # The existing code for calculating run_time for non-empty text                 │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
ValueError: The input text is empty, and strict mode is enabled

This is what the output will be regardless of video length when an exception is thrown. Note the video length can be set to 0 but yes, if the video length is set to 0 and without an exception thrown, the AddTextLetterByLetter class still won't render a video as the video length is 0, thus no video file is created. If you want, the video length can be set to one and the output will render a one-second blank video.

I will adjust accordingly to your request. Cheers!

HairlessVillager commented 11 months ago

My idea is this: when the string length is 0, developers will naturally assume that the animation time is 0. Since this may cause an error, it is necessary to remind developers, such as the strict parameter.

Perhaps it would be better to use the default_time parameter instead of the strict parameter. The default_time is an optional parameter with a default value of None. When default_time is None, rendering a blank string will raise an exception. When default_time is a positive float, it is used as the length of the animation when rendering a blank string.

Thank you for your reminder!🥰

Immanuel-Alvaro-Bhirawa commented 11 months ago

Ah yeah I get what you mean! Hahaha yeah no worries should be an easy fix! When I'm done I'll send you the code then I'll do a Pull Request!

Thank you for the help so far! Has been fun haha ❤

behackl commented 10 months ago

Resolved via #3404.