moviepy
moviepy copied to clipboard
Getting `AttributeError: 'NoneType' object has no attribute 'get_frame'` when trying to save a `CompositeVideoClip`
I'm building a quick script to make some small 9:16 videos automatically from some pre-gathered clips.
However, when I try to add multiple TextClips like this stackoverflow post. This should just create the video, however I'm getting this traceback at the write_videofile()
:
Traceback (most recent call last):
File "/workspaces/AutoTube/src/main.py", line 19, in <module>
main()
File "/workspaces/AutoTube/src/main.py", line 12, in main
create_video(True)
File "/workspaces/AutoTube/src/autovideo/__init__.py", line 14, in create_video
vid = _create_fact_video()
File "/workspaces/AutoTube/src/autovideo/__init__.py", line 69, in _create_fact_video
final.write_videofile('./Output/fact_video.mp4')
File "<decorator-gen-55>", line 2, in write_videofile
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/decorators.py", line 54, in requires_duration
return f(clip, *a, **k)
File "<decorator-gen-54>", line 2, in write_videofile
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/decorators.py", line 135, in use_clip_fps_by_default
return f(clip, *new_a, **new_kw)
File "<decorator-gen-53>", line 2, in write_videofile
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/decorators.py", line 22, in convert_masks_to_RGB
return f(clip, *a, **k)
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/video/VideoClip.py", line 300, in write_videofile
ffmpeg_write_video(self, filename, fps, codec,
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/video/io/ffmpeg_writer.py", line 220, in ffmpeg_write_video
for t,frame in clip.iter_frames(logger=logger, with_times=True,
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/Clip.py", line 472, in iter_frames
frame = self.get_frame(t)
File "<decorator-gen-11>", line 2, in get_frame
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/decorators.py", line 89, in wrapper
return f(*new_a, **new_kw)
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/Clip.py", line 93, in get_frame
return self.make_frame(t)
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/video/compositing/CompositeVideoClip.py", line 111, in make_frame
f = c.blit_on(f, t)
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/video/VideoClip.py", line 527, in blit_on
img = self.get_frame(ct)
File "<decorator-gen-11>", line 2, in get_frame
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/decorators.py", line 89, in wrapper
return f(*new_a, **new_kw)
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/Clip.py", line 93, in get_frame
return self.make_frame(t)
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/Clip.py", line 136, in <lambda>
newclip = self.set_make_frame(lambda t: fun(self.get_frame, t))
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/video/VideoClip.py", line 490, in <lambda>
return self.fl(lambda gf, t: image_func(gf(t)), apply_to)
File "<decorator-gen-11>", line 2, in get_frame
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/decorators.py", line 89, in wrapper
return f(*new_a, **new_kw)
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/Clip.py", line 93, in get_frame
return self.make_frame(t)
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/Clip.py", line 136, in <lambda>
newclip = self.set_make_frame(lambda t: fun(self.get_frame, t))
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/Clip.py", line 187, in <lambda>
return self.fl(lambda gf, t: gf(t_func(t)), apply_to,
File "<decorator-gen-11>", line 2, in get_frame
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/decorators.py", line 89, in wrapper
return f(*new_a, **new_kw)
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/Clip.py", line 93, in get_frame
return self.make_frame(t)
File "/home/codespace/.python/current/lib/python3.10/site-packages/moviepy/video/io/VideoFileClip.py", line 113, in <lambda>
self.make_frame = lambda t: self.reader.get_frame(t)
AttributeError: 'NoneType' object has no attribute 'get_frame'
As you can see from the traceback, somewhere I'm getting a None
clip?
Here's the function (including my print debugs)
def _create_fact_video() -> str:
# First, create the clip
with _get_clip(f'./Assets/gameplay.mp4') as clip:
print('Randomized Clip, editing...')
fact = _get_random_fact()
print(f'Got random fact!\nFact for the video is \"{fact}\"')
# Create the tts file
print('Creating audio...')
tts_file = _get_tts(fact)
print(f'Audio created successfully at {tts_file}')
# Create a TextClip of the fact, for the duration of the tts file
print('Creating text...')
text = mp.TextClip(fact, fontsize=24, color='white', bg_color='black')
# First, the intro
intro_text = mp.TextClip('Interesting Fact of the Day', fontsize=24, color='white', bg_color='black')
# Next, the ad
ad_text = mp.TextClip('Ad', fontsize=24, color='white', bg_color='black')
print('Text created successfully')
print('Editing audio...')
# Get the duration of the mp3 file, at ./Output/output.mp3
audio = mp.AudioFileClip(tts_file)
# Get the ending ad at ./Assets/ad.mp3
ad = mp.AudioFileClip('./Assets/ad.mp3')
# Get the Intro at Assets/factOpening.mp3
intro = mp.AudioFileClip('./Assets/factOpening.mp3')
# Set each textclip duration to the corresponding audio
intro_text = intro_text.set_duration(intro.duration)
text = text.set_duration(audio.duration)
ad_text = ad_text.set_duration(ad.duration)
print('Audio accessed, editing...')
# Create the final audio
final_audio = mp.concatenate_audioclips([intro, audio, ad])
print('Audio edited successfully')
print('Cutting final video together...')
clip.set_audio(final_audio)
final = mp.CompositeVideoClip([clip, intro_text, text, ad_text])
final = final.set_audio(final_audio)
final = final.set_duration(audio.duration + intro.duration + ad.duration)
print('Video cut together successfully')
print('Writing video...')
# Save the video
final.write_videofile('./Output/fact_video.mp4')
print('Video written successfully at ./Output/fact_video.mp4')
return './Output/fact_video.mp4'
(Side note: It shouldn't be in the _get_clip()
function, however I'll provide that If I need to)
Is there anything I'm doing wrong?
thanks :)