TextClip 动画(例如,将带有移动字母的文本添加到视频中)不起作用,文档中的演示句子除外

TextClip animations (e.g. adding text with moving letters to a video) not working, except for the demo sentence in docs

我在本地使用 moviepy 和 运行 将文本效果应用于视频,仅更改文本本身,它不适用于我输入的任何类型的文本。例如,如果我将 Cool Effect 替换为 Quick Effect,视频将显示 Q ff

同样,The quick brown fox jumped over the lazy dogs 变为 f

此代码示例的来源:https://zulko.github.io/moviepy/examples/moving_letters.htmlmoviepy 的作者。

import numpy as np

from moviepy.editor import *
from moviepy.video.tools.segmenting import findObjects

# WE CREATE THE TEXT THAT IS GOING TO MOVE, WE CENTER IT.

screensize = (720,460)
txtClip = TextClip('Cool effect',color='white', font="Amiri-Bold",
                   kerning = 5, fontsize=100)
cvc = CompositeVideoClip( [txtClip.set_pos('center')],
                        size=screensize)

# THE NEXT FOUR FUNCTIONS DEFINE FOUR WAYS OF MOVING THE LETTERS


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

def vortex(screenpos,i,nletters):
    d = lambda t : 1.0/(0.3+t**8) #damping
    a = i*np.pi/ nletters # angle of the movement
    v = rotMatrix(a).dot([-1,0])
    if i%2 : v[1] = -v[1]
    return lambda t: screenpos+400*d(t)*rotMatrix(0.5*d(t)*a).dot(v)
    
def cascade(screenpos,i,nletters):
    v = np.array([0,-1])
    d = lambda t : 1 if t<0 else abs(np.sinc(t)/(1+t**4))
    return lambda t: screenpos+v*400*d(t-0.15*i)

def arrive(screenpos,i,nletters):
    v = np.array([-1,0])
    d = lambda t : max(0, 3-3*t)
    return lambda t: screenpos-400*v*d(t-0.2*i)
    
def vortexout(screenpos,i,nletters):
    d = lambda t : max(0,t) #damping
    a = i*np.pi/ nletters # angle of the movement
    v = rotMatrix(a).dot([-1,0])
    if i%2 : v[1] = -v[1]
    return lambda t: screenpos+400*d(t-0.1*i)*rotMatrix(-0.2*d(t)*a).dot(v)



# WE USE THE PLUGIN findObjects TO LOCATE AND SEPARATE EACH LETTER

letters = findObjects(cvc) # a list of ImageClips


# WE ANIMATE THE LETTERS

def moveLetters(letters, funcpos):
    return [ letter.set_pos(funcpos(letter.screenpos,i,len(letters)))
              for i,letter in enumerate(letters)]

clips = [ CompositeVideoClip( moveLetters(letters,funcpos),
                              size = screensize).subclip(0,5)
          for funcpos in [vortex, cascade, arrive, vortexout] ]

# WE CONCATENATE EVERYTHING AND WRITE TO A FILE

final_clip = concatenate_videoclips(clips)
final_clip.write_videofile('../../coolTextEffects.avi',fps=25,codec='mpeg4')

我仔细研究了这个片段,但看不出“文本”本身有什么变化。可能与 letters 变量和 findObjects 有关,后者定位 TextClip 中的每个字母并循环遍历它们。

但我想更多地了解 moviepy 以及为什么这 4 种效果通常不起作用。我浏览了 github 和 youtube 的数百个项目,想找到能证明这些的人,但没有找到更好的例子。

如果您解决了这个问题,我可能会发布一个 public github 包/存储库,以便更轻松地将这些应用到视频中。 moviepy 的文档几乎完全省略了 TextClip 功能。

enter link description here

==更新==

根据@Rotem 的建议,我尝试修改 findObjects(clip, rem_thr) rem_thr 参数。它默认为 500,这意味着检测到的小于 500 的对象将被忽略。将其更改为任何其他阈值(500、250、50、10、1)都不能解决问题:

500 (test text arrive wiggly) findObjects found 18 letters from string of length 23
250 (test text arrive wiggly) findObjects found 20 letters from string of length 23
50 (test text arrive wiggly) findObjects found 22 letters from string of length 23
10 (test text arrive wiggly) findObjects found 22 letters from string of length 23
1 (test text arrive wiggly) findObjects found 22 letters from string of length 23

(我意识到字符串中只有 20 个字母,但我检查了字符数,包括空格。所以 22 匹配小写字母加点数 is。20 是所需的数字。因此使用 rem_thr 进行调整很重要,但每种字体大小都有不同的最佳检测大小。这很棘手,但需要更好的包装函数来管理。)

最大程度地提高字母的对比度是有帮助的:

caption = TextClip("some text",
    color='white',
    bg_color="black",
    kerning=5,
    fontsize=33)

没有指定bg_color,不管rem_thr,它只找到一个字母。

bg_color 设置为黑色有助于它找到字母。也许我需要使用块状粗字体才能工作,黑底白字,然后在将其应用到视频之前删除背景。

但是这个演示肯定很难可靠地使用。

letters = findObjects(cvc) 替换为:letters = findObjects(cvc, 50).

方法 findObjects 获得第二个可选参数:rem_thr=500.
参数说明:

rem_thr : all objects found with size < rem_Thr will be considered false positives and will be removed

当使用 'Quick Effect' 而不是 'Cool effect' 时,大多数对象的大小都小于 500。
rem_thr 值减少到 50 即可解决问题。