3b1b / manim

Animation engine for explanatory math videos
MIT License
60.28k stars 5.7k forks source link

[libx264] "width not divisible by 2" #55

Closed bhbr closed 6 years ago

bhbr commented 6 years ago

When running the sample script with the option -pw (preview & write to file), this happens:

Bens-MacBook-Pro:manim Ben$ python2.7 extract_scene.py -pw example_scenes.py WarpSquare
Writing to /Users/Ben/Dropbox/3b1b_videos/animations/example_scenes/WarpSquareTemp.mp4
Animation 1: ApplyPointwiseFunctionSquareToSquare:   2%| | 1/45 [00:00<00:07,  6.06it/s][libx264 @ 0x7fa42c80ce00] width not divisible by 2 (853x480)
Error initializing output stream 0:0 -- Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height

Traceback (most recent call last):
  File "extract_scene.py", line 206, in main
    handle_scene(SceneClass(**scene_kwargs), **config)
  File "/Users/Ben/Developer/manim/scene/scene.py", line 52, in __init__
    self.construct(*self.construct_args)
  File "/Users/Ben/Developer/manim/./example_scenes.py", line 43, in construct
    square
  File "/Users/Ben/Developer/manim/scene/scene.py", line 399, in play
    self.add_frames(self.get_frame())
  File "/Users/Ben/Developer/manim/scene/scene.py", line 445, in add_frames
    self.writing_process.stdin.write(frame.tostring())
IOError: [Errno 32] Broken pipe

sh: play: command not found

There is no output file, only an empty WarpSquareTemp.mp4.

When fixing the width "by hand" in scene/scene.py:485 with:

if (width % 2 == 1):
    width += 1

ffmpeg produces a slanted video file, because now the dimensions and buffer size don't match up:

Bens-MacBook-Pro:manim Ben$ python2.7 extract_scene.py -pw example_scenes.py WriteStuff
Writing to /Users/Ben/Dropbox/3b1b_videos/animations/example_scenes/WriteStuffTemp.mp4
Animation 1: WriteTextMobject: 100%|████████| 30/30 [00:00<00:00, 38.94it/s]
[rawvideo @ 0x7f978c002600] Invalid buffer size, packet size 1582080 < expected frame_size 1639680
Error while decoding stream #0:0: Invalid argument

Traceback (most recent call last):
  File "extract_scene.py", line 206, in main
    handle_scene(SceneClass(**scene_kwargs), **config)
  File "extract_scene.py", line 109, in handle_scene
    scene.preview()
  File "/Users/Ben/Developer/manim/scene/scene.py", line 456, in preview
    TkSceneRoot(self)
  File "/Users/Ben/Developer/manim/scene/tk_scene.py", line 29, in __init__
    self.show_new_image(frame)
  File "/Users/Ben/Developer/manim/scene/tk_scene.py", line 38, in show_new_image
    photo = ImageTk.PhotoImage(image)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/PIL/ImageTk.py", line 117, in __init__
    self.__photo = tkinter.PhotoImage(**kw)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 3371, in __init__
    Image.__init__(self, 'photo', name, cnf, master, **kw)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 3308, in __init__
    raise RuntimeError, 'Too early to create image'
RuntimeError: Too early to create image

sh: play: command not found
Exception AttributeError: "'PhotoImage' object has no attribute '_PhotoImage__photo'" in <bound method PhotoImage.__del__ of <PIL.ImageTk.PhotoImage object at 0x111c95cd0>> ignored
nmschulte commented 6 years ago

Perhaps this is useful (using the scale video filter): https://stackoverflow.com/a/29582287/545839

bhbr commented 6 years ago

This helped me find a workaround! In constants.py:21, the 853 is a rounded-off 853.(3). Just round it up instead (854). I don't know how 3b1b himself gets his videos to render with the odd 853.

Life lesson: if "width not divisible by 2" gets no useful Google hits, try "height not divisible by 2".

Thy, nmschulte!