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

AttributeError: 'NoneType' object has no attribute 'stdout' #1994

Closed
tobiasBora opened this issue Jun 21, 2023 · 3 comments · Fixed by #1995
Closed

AttributeError: 'NoneType' object has no attribute 'stdout' #1994

tobiasBora opened this issue Jun 21, 2023 · 3 comments · Fixed by #1995
Labels
bug Issues that report (apparent) bugs. images Related to ImageClip, or handling of images in general. video Related to VideoClip and related classes, or handling of video in general.

Comments

@tobiasBora
Copy link
Contributor

Expected Behavior

I expect this code to work:

from moviepy.editor import *

clip1 = VideoFileClip("classe_inversee.mp4")
clip2 = ImageClip("myRobExt-3EC8291240A626FE802A5A28DB2022A8-img-1.png", duration=clip1.duration).with_position(("center", "center"))
final_clip = CompositeVideoClip([clip1, clip2])
final_clip.write_videofile("out.mp4", fps=24)

Actual Behavior

I get this error on master:

MoviePy - Building video out.mp4.
MoviePy - Writing audio in outTEMP_MPY_wvf_snd.mp3
chunk:   0%|                                                                                                                                                                    | 0/367 [00:00<?, ?it/s, now=None]Traceback (most recent call last):
  File "/home/leo/Documents/Cours/2023_-_Candidatures_postes/2023_03_-_Bordeaux/Presentation_orale/robustExternalize/test.py", line 7, in <module>
    final_clip.write_videofile("out.mp4", fps=24)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/decorators.py", line 52, in requires_duration
    return func(clip, *args, **kwargs)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/decorators.py", line 143, in use_clip_fps_by_default
    return func(clip, *new_args, **new_kwargs)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/decorators.py", line 23, in convert_masks_to_RGB
    return func(clip, *args, **kwargs)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/decorators.py", line 94, in wrapper
    return func(*new_args, **new_kwargs)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/video/VideoClip.py", line 369, in write_videofile
    self.audio.write_audiofile(
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/decorators.py", line 52, in requires_duration
    return func(clip, *args, **kwargs)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/decorators.py", line 94, in wrapper
    return func(*new_args, **new_kwargs)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/audio/AudioClip.py", line 249, in write_audiofile
    return ffmpeg_audiowrite(
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/decorators.py", line 52, in requires_duration
    return func(clip, *args, **kwargs)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/audio/io/ffmpeg_audiowriter.py", line 205, in ffmpeg_audiowrite
    for chunk in clip.iter_chunks(
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/audio/AudioClip.py", line 109, in iter_chunks
    yield self.to_soundarray(
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/decorators.py", line 52, in requires_duration
    return func(clip, *args, **kwargs)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/audio/AudioClip.py", line 157, in to_soundarray
    snd_array = self.get_frame(tt)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/decorators.py", line 94, in wrapper
    return func(*new_args, **new_kwargs)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/Clip.py", line 82, in get_frame
    return self.make_frame(t)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/audio/AudioClip.py", line 361, in make_frame
    sounds = [
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/audio/AudioClip.py", line 362, in <listcomp>
    clip.get_frame(t - clip.start) * np.array([part]).T
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/decorators.py", line 94, in wrapper
    return func(*new_args, **new_kwargs)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/Clip.py", line 82, in get_frame
    return self.make_frame(t)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/audio/io/AudioFileClip.py", line 76, in <lambda>
    self.make_frame = lambda t: self.reader.get_frame(t)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/audio/io/readers.py", line 195, in get_frame
    self.buffer_around(fr_max)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/audio/io/readers.py", line 244, in buffer_around
    array = self.read_chunk(chunksize)
  File "/nix/store/vjgahh1d96mlpr4x7p2s5dcrs37d2s4a-python3-3.10.9-env/lib/python3.10/site-packages/moviepy/audio/io/readers.py", line 134, in read_chunk
    s = self.proc.stdout.read(self.nchannels * chunksize * self.nbytes)
AttributeError: 'NoneType' object has no attribute 'stdout'

Steps to Reproduce the Problem

First, get the latest version on master. If you want to get the same environment as mine and you have nix, you can just run:

$ nix develop --impure --expr 'let pkgs = (builtins.getFlake "github:NixOs/nixpkgs?rev=75a5ebf473cd60148ba9aec0d219f72e5cf52519").legacyPackages.x86_64-linux; in pkgs.mkShell { buildInputs = [ pkgs.ffmpeg (pkgs.python3.withPackages (ps: with ps; [ ipython (moviepy.overrideAttrs (old: {src = pkgs.fetchFromGitHub { owner = "Zulko"; repo = "moviepy"; rev = "b5bb086439cfd0960011a065f229eb7a7b4ebad5"; sha256 = "sha256-Y+rehn+fLR0id5jAmfOkYHj8mLMJgnMwld7wp5BxmuQ="; };})) ] )) ]; }'

to enter a shell with the expected dependencies.

Then, write in a file test.py:

from moviepy.editor import *

clip1 = VideoFileClip("classe_inversee.mp4")
clip2 = ImageClip("myRobExt-3EC8291240A626FE802A5A28DB2022A8-img-1.png", duration=clip1.duration).with_position(("center", "center"))
final_clip = CompositeVideoClip([clip1, clip2])
final_clip.write_videofile("out.mp4", fps=24)

create the 2 files using these two files (hopefully github will not alter them):

myRobExt-3EC8291240A626FE802A5A28DB2022A8-img-1

classe_inversee.mp4:

classe_inversee.mp4

and run

$ python3 test.py 

You should observe:

MoviePy - Building video out.mp4.
MoviePy - Writing audio in outTEMP_MPY_wvf_snd.mp3
chunk:   0%|                                                                                                                                                                    | 0/367 [00:00<?, ?it/s, now=None]Traceback (most recent call last):
  File "/home/leo/Documents/Cours/2023_-_Candidatures_postes/2023_03_-_Bordeaux/Presentation_orale/robustExternalize/test.py", line 7, in <module>
    final_clip.write_videofile("out.mp4", fps=24)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/decorators.py", line 52, in requires_duration
    return func(clip, *args, **kwargs)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/decorators.py", line 143, in use_clip_fps_by_default
    return func(clip, *new_args, **new_kwargs)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/decorators.py", line 23, in convert_masks_to_RGB
    return func(clip, *args, **kwargs)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/decorators.py", line 94, in wrapper
    return func(*new_args, **new_kwargs)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/video/VideoClip.py", line 369, in write_videofile
    self.audio.write_audiofile(
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/decorators.py", line 52, in requires_duration
    return func(clip, *args, **kwargs)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/decorators.py", line 94, in wrapper
    return func(*new_args, **new_kwargs)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/audio/AudioClip.py", line 249, in write_audiofile
    return ffmpeg_audiowrite(
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/decorators.py", line 52, in requires_duration
    return func(clip, *args, **kwargs)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/audio/io/ffmpeg_audiowriter.py", line 205, in ffmpeg_audiowrite
    for chunk in clip.iter_chunks(
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/audio/AudioClip.py", line 109, in iter_chunks
    yield self.to_soundarray(
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/decorators.py", line 52, in requires_duration
    return func(clip, *args, **kwargs)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/audio/AudioClip.py", line 157, in to_soundarray
    snd_array = self.get_frame(tt)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/decorators.py", line 94, in wrapper
    return func(*new_args, **new_kwargs)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/Clip.py", line 82, in get_frame
    return self.make_frame(t)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/audio/AudioClip.py", line 361, in make_frame
    sounds = [
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/audio/AudioClip.py", line 362, in <listcomp>
    clip.get_frame(t - clip.start) * np.array([part]).T
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/decorators.py", line 94, in wrapper
    return func(*new_args, **new_kwargs)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/Clip.py", line 82, in get_frame
    return self.make_frame(t)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/audio/io/AudioFileClip.py", line 76, in <lambda>
    self.make_frame = lambda t: self.reader.get_frame(t)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/audio/io/readers.py", line 195, in get_frame
    self.buffer_around(fr_max)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/audio/io/readers.py", line 244, in buffer_around
    array = self.read_chunk(chunksize)
  File "/nix/store/g6q4rn4zbjw4gp8gp6q3h3j3r2kaqcdn-python3-3.10.11-env/lib/python3.10/site-packages/moviepy/audio/io/readers.py", line 134, in read_chunk
    s = self.proc.stdout.read(self.nchannels * chunksize * self.nbytes)
AttributeError: 'NoneType' object has no attribute 'stdout'

Specifications

  • Python Version: 3.10.11
  • MoviePy Version: master 75a5ebf473cd60148ba9aec0d219f72e5cf52519
  • Platform Name: NixOs
  • Platform Version: unstable (2caf4ef5005ecc68141ecb4aac271079f7371c44)
@tobiasBora tobiasBora added the bug Issues that report (apparent) bugs. label Jun 21, 2023
@keikoro keikoro added video Related to VideoClip and related classes, or handling of video in general. images Related to ImageClip, or handling of images in general. labels Jun 21, 2023
@tobiasBora
Copy link
Contributor Author

tobiasBora commented Jun 21, 2023

So after a bit of investigation, it seems like the issue occurs only with some kinds of video (here a video exported via kdenlive), more precisely when moviepy tries to deal with the audio. The reason is that the file descriptor of self.proc (that contains a file descriptor to ffmpeg) is closed by calling this function:

def close(self):
"""Close the internal reader."""
if self.reader:
self.reader.close()
self.reader = None

that destroys the proc to ffmpeg. Commenting these lines actually solve the problem, but this is a dirty solution since the proc will never be closed.

Now, why is it closed? A traceback gives:

  File "moviepy/Clip.py", line 639, in __del__
    self.close()
  File "moviepy/moviepy/video/io/VideoFileClip.py", line 167, in close
    self.audio.close()
  File "moviepy/audio/io/AudioFileClip.py", line 83, in close
    raise NameError("don't close me") <--- I added this line to debug

So it seems like at some point the clip is destroyed automatically by the garbage collector, that calls:

moviepy/moviepy/Clip.py

Lines 637 to 638 in b5bb086

def __del__(self):
self.close()

but this arrives before the make_frame defined here is called (which internally needs proc):

self.make_frame = lambda t: self.reader.get_frame(t)

So proc does not exists when it is called later. I guess the garbage collector is not clever enough to determine that a function copy is still in use… This seems to be a well known issue however:

moviepy/moviepy/Clip.py

Lines 541 to 551 in b5bb086

def close(self):
"""Release any resources that are in use."""
# Implementation note for subclasses:
#
# * Memory-based resources can be left to the garbage-collector.
# * However, any open files should be closed, and subprocesses
# should be terminated.
# * Be wary that shallow copies are frequently used.
# Closing a Clip may affect its copies.
# * Therefore, should NOT be called by __del__().
pass

but I have no idea what is the clean way to solve it. Actually this line sayes that close should NOT be closed by __del__ (that makes sense now), and in the code, it is explicitely called by __del__ a few lines below. So I guess this should not be done?

@keikoro might have an idea?

@tobiasBora
Copy link
Contributor Author

Ok, a quick git blame pointed to a recent commit from 57c279a : @mgaitan , you confirm that it was not a good idea to call close in del (as suggested in the comment of close) and that it can therefore be undone?

tobiasBora added a commit to tobiasBora/moviepy that referenced this issue Jun 21, 2023
@tobiasBora
Copy link
Contributor Author

I just reverted the problematic modification of @mgaitan in this PR #1995

OsaAjani pushed a commit to OsaAjani/moviepy that referenced this issue Jun 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issues that report (apparent) bugs. images Related to ImageClip, or handling of images in general. video Related to VideoClip and related classes, or handling of video in general.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants