0

In my trials to make animated text using Python moviepy package, I have found a possible bug for which I don't have a solution as of now.

Issue/Observation: if I animate text 'TrI' {notice the capital I}, it works with animated text of 'TrI'; if the 'I' is change to small caps 'i', then the 'ri' disappears and output text in animated video is only 'T'.

Reproducible Code given below (most of it is from official tutorials):

###############################################################################
################################# Summary #####################################

# Goal: MoviePy Bug Display
# Version: Python 3.10.9
# IDE: Thonny 4.0.1
# Date: 08th April 2023

# To place a background image

###############################################################################
###############################################################################

###############################################################################
########################### Importing Libraries ###############################

# In case some packages are not installed, this structure will neatly print it
try:
    import os
    import re
    import sys
    import glob
    import numpy as np
    from moviepy.editor import *
    from moviepy.video.tools.segmenting import findObjects
    
    temp_message = ('Imported libraries successfully')
    print(temp_message)
    del([temp_message])
except Import_Error:
    temp_message = ('Error: {0} in importing libraries. Exiting'.format(Import_Error))
    print(temp_message)
    del([temp_message])
    sys.exit()
# End of 'try:'

###############################################################################
###############################################################################

###############################################################################
############################## Hyper Parameters ###############################

OS_Separator = os.sep # This is OS specific, like Linux/Windows/etc,
# this makes code navigate folders across OS with same code

DefaultDirectory = os.getcwd()

OutputFilename = 'OutputBG.mp4'
OutputFilepath = DefaultDirectory + OS_Separator + OutputFilename

WidthPx = 1920
HeightPx = 1080

FontColor = 'lightgreen'
Font = "Arial"
TextAnimate = "Tri" # Change to "Tri", and the output video only has 'T', the 'ri disappears
# "Tri re ri re" also gives only 'T' as output
FontSize = 80

VideoFPS = 24

###############################################################################
###############################################################################

###############################################################################
################################ Animating Text ###############################

# screen size
screensize = (WidthPx, HeightPx)
 
# creating a text clip of chosen color, font and size
txtClip = TextClip(txt = TextAnimate, color = FontColor, font = Font,
                   kerning = 0, fontsize = FontSize)
 
# creating a composite video of given size
cvc = CompositeVideoClip( [txtClip.set_pos('center')], size = screensize)

# helper function
rotMatrix = lambda a: np.array( [[np.cos(a), np.sin(a)], [-np.sin(a), np.cos(a)]] )

# Creating an effect 1 method
def effect1(screenpos, index, nletters):
    # damping
    d = lambda t : 1.0/(0.3 + t**8)
    # angle of the movement
    a = index * np.pi / nletters
     
    # using helper function
    v = rotMatrix(a).dot([-1, 0])
     
    if index % 2 : v[1] = -v[1]
         
    # returning the function
    return lambda t: screenpos + 400 * d(t)*rotMatrix(0.5 * d(t)*a).dot(v)
# End of 'def effect1(screenpos, index, nletters):'

# Creating an effect 2 method
def effect2(screenpos, index, nletters):
    # numpy array
    v = np.array([0, -1])
     
    d = lambda t : 1 if t<0 else abs(np.sinc(t)/(1 + t**4))
     
    # returning the function
    return lambda t: screenpos + v * 400 * d(t-0.15 * index)
# End of 'def effect2(screenpos, index, nletters):'

# a list of ImageClips
letters = findObjects(cvc)

# method to move letters
def moveLetters(letters, funcpos):     
    return [ letter.set_pos(funcpos(letter.screenpos, index, len(letters)))
              for index, letter in enumerate(letters)]
# End of 'def moveLetters(letters, funcpos):'

# adding clips with specific effect
clips = [ CompositeVideoClip( moveLetters(letters, funcpos),
                              size = screensize).subclip(0, 5)
          for funcpos in [effect1, effect2] ]
 
# comping all the clips
final_clip = concatenate_videoclips(clips)
 
# setting fps of the final clip
final_clip.fps = VideoFPS

# Saving video clip
final_clip.subclip().write_videofile(OutputFilepath,fps=VideoFPS,codec='libx264')


###############################################################################
###############################################################################

Cheer

N V
  • 83
  • 2
  • 12

0 Answers0