Hello, I have script which can export clips of time ranges in video, slow it down and keep the original pitch. It is saved then. There are folders of number created into Output directory. Each number represents slow down factor. Now when I play the video which is like 20 times slower I need to see time because vlc just doesn't give me convinient information, I want to keep the time in the video. I cannot find out how to do this correctly. Can anyone here try to fix/finish the script? I mean only the text into video. I need to see the seconds in format like 14.05 (14.05s) or something like 14.053 etc.
I remember there was an error with the lambda function when I tried this.
I have this:
I remember there was an error with the lambda function when I tried this.
I have this:
# REQUIRES: moviepy a pydub
# TATO VYBERE NĚKOLIK SEGMENTŮ Z VIDEA, ZPOMALÍ JE,
# ZACHOVÁ TÓN, PŘIDÁ TEXT SEKUND (float)
import os
from moviepy.editor import VideoFileClip, concatenate_videoclips, vfx, AudioFileClip, TextClip, CompositeVideoClip
from pydub import AudioSegment
from moviepy.video.tools.drawing import color_split
# Directories - se absolute
home_dir = os.path.expanduser("~")
default_path = "/Samba"
input_dir = os.path.join("/media/mydisk/home/user/Videos", default_path)
file = 'for minutes video.mp4'
input_path = os.path.join(input_dir, file)
user_choice = input("Do you want to use current folder (.) od default one? Type '.' for current or 'default' ...: ")
if user_choice == '.':
input_dir = os.path.abspath('.')
input_path = os.path.join(input_dir, file)
# Slow down factors
slowdowns = [2,4,8,10,15,20,25,30]
# Output folders creation
output_dirs = [os.path.join(input_dir, f"Output/{factor}") for factor in slowdowns]
for dir in output_dirs:
os.makedirs(dir, exist_ok=True)
# change audio pitch - no change speed
def audio_pitchup_ffmpeg(input_audio_path, output_audio_path, factor):
command = f'ffmpeg -i "{input_audio_path}" -filter_complex "rubberband=pitch={factor}" "{output_audio_path}"'
os.system(command)
# convert time to s.
def convert_to_seconds(time_str):
parts = time_str.split(':')
minutes = int(parts[0])
seconds = float(parts[1])
return minutes * 60 + seconds
# times to be exported
time_ranges = [
# ("0:50.40", "0:56.00")
# ("0:56.00", "0:56.02")
("1:27.00", "2:27.00") # to export this part
# ("1:27.00", "4:37")
]
# insert text
def add_time_text(get_frame, t):
# Vytvoření textového klipu s časem
time_str = f"t={t:.2f} sec"
txt_clip = TextClip(time_str, fontsize=22, color='white', bg_color='black', size=(200, 50))
txt_clip = txt_clip.set_position(('left', 'top')).set_duration(0.1)
# create videoclip with text
return CompositeVideoClip([get_frame(t), txt_clip])
# one file process
video_path = input_path
if os.path.isfile(video_path) and video_path.endswith(".mp4"):
video_clip = VideoFileClip(video_path)
# export parts
temp_clips = []
for start_time, end_time in time_ranges:
start_seconds = convert_to_seconds(start_time)
end_seconds = convert_to_seconds(end_time)
temp_clip = video_clip.subclip(start_seconds, end_seconds)
temp_clips.append(temp_clip)
# join all
temp_joined_path = os.path.join(input_dir, "temp_joined.avi")
joined_clip = concatenate_videoclips(temp_clips)
joined_clip.write_videofile(temp_joined_path, codec="libx264", audio_codec="aac")
# Uzavření všech klipů
for clip in temp_clips:
clip.close()
video_clip.close()
joined_clip.close()
# slow down and correct pitch in audio tracks
for i, factor in enumerate(slowdowns):
output_path = os.path.join(output_dirs[i], file)
edited_clip = VideoFileClip(temp_joined_path)
# text addition
edited_clip = edited_clip.fl(lambda gf, t: add_time_text(gf, t))
# extraction and editation
temp_audio_path = os.path.join(input_dir, "temp_audio.wav")
edited_clip.audio.write_audiofile(temp_audio_path, codec='pcm_s16le')
new_audio_path = os.path.join(input_dir, "new_temp_audio.wav")
audio_pitchup_ffmpeg(temp_audio_path, new_audio_path, factor)
new_audio_clip = AudioFileClip(new_audio_path)
# create new video with edited audio track
edited_clip = edited_clip.set_audio(new_audio_clip)
temp_video_name = os.path.join(input_dir, "temp-final-video.m4a")
edited_clip.write_videofile(
temp_video_name,
codec="libx264",
audio_codec="aac",
temp_audiofile=os.path.join(input_dir, 'temp-audio-1.m4a'),
remove_temp=True,
threads=4,
preset='ultrafast'
)
# close temporals
edited_clip.close()
new_audio_clip.close()
# reopen to slow-down
edited_clip = VideoFileClip(temp_video_name)
edited_clip = edited_clip.fx(vfx.speedx, 1.0 / factor)
edited_clip.set_duration(edited_clip.duration)
print(f"Processing {file} with slowdown factor {factor}. Saving to {output_path}")
edited_clip.write_videofile(
output_path,
codec="libx264",
audio_codec="aac",
temp_audiofile=os.path.join(input_dir,'temp-audio-2.m4a'),
remove_temp=True,
threads=4,
preset='ultrafast'
)
# close all
edited_clip.close()
# remove all
if os.path.exists(temp_audio_path):
os.remove(temp_audio_path)
if os.path.exists(new_audio_path):
os.remove(new_audio_path)
if os.path.exists(temp_video_name):
os.remove(temp_video_name)
# remove temporals
if os.path.exists(temp_joined_path):
os.remove(temp_joined_path)
else:
print(f"{file} ---> File .mp4 not found")
print("Job done.")When I tried the code I got similar error:Moviepy - Building video /media/toshiba/home/user/Videa/TUTORIALS/temp_joined.avi.
MoviePy - Writing audio in temp_joinedTEMP_MPY_wvf_snd.mp4
MoviePy - Done.
Moviepy - Writing video /media/toshiba/home/user/Videa/TUTORIALS/temp_joined.avi
Moviepy - Done !
Moviepy - video ready /media/toshiba/home/user/Videa/TUTORIALS/temp_joined.avi
Traceback (most recent call last):
File "get-segments-slow-down-time-lower-sound-quality.py", line 92, in <module>
edited_clip = edited_clip.fl(lambda gf, t: add_time_text(gf, t))
File "/home/user/.venv/lib/python3.8/site-packages/moviepy/Clip.py", line 136, in fl
newclip = self.set_make_frame(lambda t: fun(self.get_frame, t))
File "<decorator-gen-61>", line 2, in set_make_frame
File "/home/user/.venv/lib/python3.8/site-packages/moviepy/decorators.py", line 14, in outplace
f(newclip, *a, **k)
File "/home/user/.venv/lib/python3.8/site-packages/moviepy/video/VideoClip.py", line 644, in set_make_frame
self.size = self.get_frame(0).shape[:2][::-1]
File "<decorator-gen-11>", line 2, in get_frame
File "/home/user/.venv/lib/python3.8/site-packages/moviepy/decorators.py", line 89, in wrapper
return f(*new_a, **new_kw)
File "/home/user/.venv/lib/python3.8/site-packages/moviepy/Clip.py", line 93, in get_frame
return self.make_frame(t)
File "/home/user/.venv/lib/python3.8/site-packages/moviepy/Clip.py", line 136, in <lambda>
newclip = self.set_make_frame(lambda t: fun(self.get_frame, t))
File "get-segments-slow-down-time-lower-sound-quality.py", line 92, in <lambda>
edited_clip = edited_clip.fl(lambda gf, t: add_time_text(gf, t))
File "get-segments-slow-down-time-lower-sound-quality.py", line 60, in add_time_text
return CompositeVideoClip([get_frame(t), txt_clip])
File "/home/user/.venv/lib/python3.8/site-packages/moviepy/video/compositing/CompositeVideoClip.py", line 79, in __init__
self.bg = ColorClip(size, color=self.bg_color)
File "/home/user/.venv/lib/python3.8/site-packages/moviepy/video/VideoClip.py", line 1012, in __init__
w, h = size
TypeError: cannot unpack non-iterable int object
