Search code examples
pythoniterable-unpackingmoviepy

How to insert all occurances in list[] into CompositeVideoClip


I have a video where I want to insert a dynamic amount of TextClip(s). I have a while loop that handles the logic for actually creating the different TextClips and giving them individual durations & start_times (this works). I do however have a problem with actually "compiling" the video itself with inserting these texts.

Code for creating a TextClip (that works).

text = mpy.TextClip(str(contents),
    color='white', size=[1700, 395], method='caption').set_duration(
                   int(list[i - 1])).set_start(currentTime).set_position(("center", 85)) 

print(str(i) + " written")
textList.append(text)

Code to "compile" the video. (that doesn't work)

final_clip = CompositeVideoClip([clip, len(textList)])
final_clip.write_videofile("files/final/TEST.mp4")

I tried several approaches but now I'm stuck and can't figure out a way to continue. Before I get a lot of "answers" telling me to do a while loop on the compiling, let me just say that the actual compiling takes about 5 minutes and I have 100-500 different texts I need implemented in the final video which would take days. Instead I want to add them one by one and then do 1 big final compile which I know it will take slightly longer than 5 minutes, but still a lot quicker than 2-3 days.

For those of you that may not have used moviepy before I will post a snippet of "my code" that actually works, not in the way I need it to though.

final_clip = CompositeVideoClip([clip, textList[0], textList[1], textList[2]])
final_clip.write_videofile("files/final/TEST.mp4")

This works exactly as intended (adding 3 texts), However I dont/can't know how many texts there will be in each video beforehand so I need to somehow insert a dynamic amount of textList[] into the function.

Kind regards,


Solution

  • Unsure what the arguments after clip, do (you could clarify), but if the problem's solved by inserting a variable number of textList[i] args, the solution's simple:

    CompositeVideoClip([clip, *textList])
    

    The star unpacks the list (or any iterable); ex: arg=4,5 -- def f(a,b): return a+b -- f(*arg)==9. If you have many textLists, you can manage them via a nested list or a dictionary:

    textListDict = {'1':textList1, '2':textList2, ...}
    textListNest = [textList1, textList2, ...] # probably preferable - using for below
    
    # now iterate:
    for textList in textListNest:
        final_clip = CompositeVideoClip([clip, *textList])
    


    Unpacking demo:

    def show_then_join(a, b, c):
        print("a={}, b={}, c={}".format(a,b,c))
        print(''.join("{}{}{}".format(a,b,c)))
    
    some_list = [1, 2, 'dog']
    show_then_sum(*some_list) # only one arg is passed in, but is unpacked into three
    # >> a=1, b=2, c=dog
    # >> 12dog