Python Forum
How to insert text time - into video frames?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to insert text time - into video frames?
#1
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:
# 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
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Is there a Python solution to select unique frames from a video? rownong 1 546 Feb-02-2025, 09:56 AM
Last Post: Larz60+
  What is the fastest way to get all the frames from a video file? glorsh66 3 4,272 May-26-2023, 04:41 AM
Last Post: Gribouillis
  How to read rainfall time series and insert missing data points MadsM 4 3,226 Jan-06-2022, 10:39 AM
Last Post: amdi40
  Extracting all text from a video jehoshua 2 2,900 Nov-14-2021, 09:54 PM
Last Post: jehoshua
  Better way to append frames from a video to multiple lists? Balaganesh 0 2,362 May-13-2021, 07:37 AM
Last Post: Balaganesh
  More elegant way to remove time from text lines. Pedroski55 6 5,333 Apr-25-2021, 03:18 PM
Last Post: perfringo
  Split gps files based on time (text splitting) dervast 0 2,319 Nov-09-2020, 09:19 AM
Last Post: dervast
  how do i create average of 1000 frames per second from video with yolo Rupen_gurung 0 2,010 Jul-20-2019, 01:55 AM
Last Post: Rupen_gurung
  Insert text in Ubuntu Vladimir 2 3,399 Jan-29-2018, 02:26 PM
Last Post: Vladimir
  Insert using psycopg giving syntax error near "INSERT INTO" olgethorpe 4 18,228 Jul-21-2017, 07:39 PM
Last Post: nilamo

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020