Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
HairlessVillager opened this issue Sep 24, 2023 · 13 comments
Assignees
Labels
issue:bug Something isn't working... For use in issues

Comments

@HairlessVillager
Copy link
Contributor

HairlessVillager commented Sep 24, 2023

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
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
Copy link
Contributor

Immanuel-Alvaro-Bhirawa commented Oct 7, 2023

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.

@MrDiver MrDiver added the issue:bug Something isn't working... For use in issues label Oct 8, 2023
@Immanuel-Alvaro-Bhirawa
Copy link
Contributor

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
Copy link
Contributor Author

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
Copy link
Contributor

Immanuel-Alvaro-Bhirawa commented Oct 9, 2023

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

@Immanuel-Alvaro-Bhirawa
Copy link
Contributor

Immanuel-Alvaro-Bhirawa commented Oct 10, 2023

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
Copy link
Contributor Author

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

('[\'<span fgcolor="#f92672">import</span><span fgcolor="#f8f8f2"> '
 '</span><span fgcolor="#f8f8f2">re</span>\', \'<span '
 'fgcolor="#f92672">import</span><span fgcolor="#f8f8f2"> </span><span '
 'fgcolor="#f8f8f2">scrapy</span>\', \'<span '
 'fgcolor="#f92672">from</span><span fgcolor="#f8f8f2"> </span><span '
 'fgcolor="#f8f8f2">moepediacollector</span><span '
 'fgcolor="#f8f8f2">.</span><span fgcolor="#f8f8f2">items</span><span '
 'fgcolor="#f8f8f2"> </span><span fgcolor="#f92672">import</span><span '
 'fgcolor="#f8f8f2"> </span><span '
 'fgcolor="#f8f8f2">MoepediacollectorItem</span>\', \'\', \'\', \'<span '
 'fgcolor="#66d9ef">def</span><span fgcolor="#f8f8f2"> </span><span '
 'fgcolor="#a6e22e">check_date_format</span><span '
 'fgcolor="#f8f8f2">(</span><span fgcolor="#f8f8f2">date</span><span '
 'fgcolor="#f8f8f2">)</span><span fgcolor="#f8f8f2">:</span>\', \'<span '
 'fgcolor="#f8f8f2">    </span><span '
 'fgcolor="#f8f8f2">date_pattern</span><span fgcolor="#f8f8f2"> </span><span '
 'fgcolor="#f92672">=</span><span fgcolor="#f8f8f2"> </span><span '
 'fgcolor="#e6db74">r</span><span fgcolor="#e6db74">\\\'</span><span '
 'fgcolor="#e6db74">^</span><span fgcolor="#e6db74">\\\\</span><span '
 'fgcolor="#e6db74">d</span><span fgcolor="#e6db74">{4}</span><span '
 'fgcolor="#e6db74">/([1-9]|1[0-2])$</span><span '
 'fgcolor="#e6db74">\\\'</span>\']')
[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
Copy link
Contributor

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

@Immanuel-Alvaro-Bhirawa
Copy link
Contributor

Immanuel-Alvaro-Bhirawa commented Oct 13, 2023

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
Copy link
Contributor Author

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
Copy link
Contributor

Immanuel-Alvaro-Bhirawa commented Oct 14, 2023

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
Copy link
Contributor Author

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
Copy link
Contributor

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
Copy link
Member

behackl commented Oct 26, 2023

Resolved via #3404.

@behackl behackl closed this as completed Oct 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
issue:bug Something isn't working... For use in issues
Projects
Status: 🆕 New
Development

No branches or pull requests

4 participants