TypeError: 'VideoFileClip' object is not subscriptable

Question:

I’m trying to make this application that will let you merge video clips together, however, when I try to merge two clips, I get this error: TypeError: 'VideoFileClip' object is not iterable. moreover, when I want to merge more than 2 clips, let’s say 3 clips, I get this error:
TypeError: 'VideoFileClip' object is not subscriptable. Any help will be appreciated.

Full error, when 2 video clips given:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:UsersTotenkopfAppDataLocalProgramsPythonPython38libtkinter__init__.py", line 1883, in __call__
    return self.func(*args)
  File "D:/Python Projects/Windows/VideoMerger/main.py", line 80, in merge_vid
    final_clip = concatenate_videoclips(clip1, clip2)
  File "D:Python ProjectsWindowsVideoMergervenvlibsite-packagesmoviepyvideocompositingconcatenate.py", line 71, in concatenate_videoclips
    tt = np.cumsum([0] + [c.duration for c in clips])
TypeError: 'VideoFileClip' object is not iterable

Full error when more than 2 clips given:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:UsersTotenkopfAppDataLocalProgramsPythonPython38libtkinter__init__.py", line 1883, in __call__
    return self.func(*args)
  File "D:/Python Projects/Windows/VideoMerger/main.py", line 87, in merge_vid
    final_clip = concatenate_videoclips(clip1, clip2, clip3)
  File "D:Python ProjectsWindowsVideoMergervenvlibsite-packagesmoviepyvideocompositingconcatenate.py", line 67, in concatenate_videoclips
    l = [[v, transition] for v in clips[:-1]]
TypeError: 'VideoFileClip' object is not subscriptable

Code:

def open_location():

global filename_splitted
filename = askopenfilename()
filename_ext = os.path.splitext(filename)
filename_splitted = str(filename_ext).split('/')[4].split(".")[0].split(',')[0].split("'")[0]
filename_ext_split = filename_ext[1][1:]

if len(filename) > 1 and filename_ext_split == "mp4":
    path_url.config(text=filename_splitted, fg="green")

else:
    messagebox.showwarning(title="oops", message="No video given!")
    path_url.config(text="Please specify a file (mp4)!", fg="red")

return filename_splitted


def merge_vid():

    number_of_videos = box.get()
    if number_of_videos <= "1":
        messagebox.showwarning(title="Warning", message="Please specify how many videos you want to merge.")

    elif number_of_videos == "2":
        clip1 = VideoFileClip(f"{open_location()}.mp4")
        clip2 = VideoFileClip(f"{open_location()}.mp4")
        final_clip = concatenate_videoclips(clip1, clip2)
        final_clip.write_videofile('Final.mp4', codec="libx264")

    elif number_of_videos == "3":
        clip1 = VideoFileClip(f"{open_location()}.mp4")
        clip2 = VideoFileClip(f"{open_location()}.mp4")
        clip3 = VideoFileClip(f"{open_location()}.mp4")
        final_clip = concatenate_videoclips(clip1, clip2, clip3)
        final_clip.write_videofile('Final.mp4', codec="libx264")

    elif number_of_videos == "4":
        clip1 = VideoFileClip(f"{open_location()}.mp4")
        clip2 = VideoFileClip(f"{open_location()}.mp4")
        clip3 = VideoFileClip(f"{open_location()}.mp4")
        clip4 = VideoFileClip(f"{open_location()}.mp4")
        final_clip = concatenate_videoclips(clip1, clip2, clip3, clip4)
        final_clip.write_videofile('Final.mp4', codec="libx264")

Here’s the entire code in case anyone want to try it:

import tkinter

from moviepy.editor import *
from tkinter import *
from tkinter import messagebox
from tkinter import ttk
from tkinter import filedialog
import threading
import requests
import os
from tkinter.filedialog import askopenfilename


# import subprocess

# Converting video file types.
# subprocess.call("ffmpeg -i Z1.mov -q:v 0 Z1mp4.mp4", shell=True)
# subprocess.call("ffmpeg -i Z2.mov -q:v 0 Z2mp4.mp4", shell=True)
# subprocess.call("ffmpeg -i Z2.mov -q:v 0 Z3mp4.mp4", shell=True)
def prog_bar():
    progressbar = Tk()
    progressbar.geometry("555x33+600+100")
    progressbar.title("Downloading ffmpeg, please wait...")
    pb = ttk.Progressbar(progressbar, orient='horizontal', mode='determinate')
    pb.pack(expand=True, fill=tkinter.BOTH, side=tkinter.TOP)
    pb.start(11)
    progressbar.after(60000, message2)
    progressbar.after(90000, progressbar.destroy)
    progressbar.mainloop()

def message2():
    messagebox.showinfo(title="Download Completed", message="Download completed. Please restart the app.")

def download_ffmpeg():
    r = requests.get("https://www.dropbox.com/s/ur8miwz54us8ruc/ffmpeg.exe?dl=1", allow_redirects=True)
    open('C:/ffmpeg.exe', 'wb').write(r.content)
if os.path.exists("C:/ffmpeg.exe"):
    os.environ["IMAGEIO_FFMPEG_EXE"] = r"C:ffmpeg.exe"

else:
    # threading.Thread(target=message1).start()
    threading.Thread(target=prog_bar).start()
    threading.Thread(target=download_ffmpeg).start()
    start_time = threading.Timer(33, message2)
    # start_time.start()
    # os.environ["IMAGEIO_FFMPEG_EXE"] = rf"{directory}ffmpeg"
    os.environ["IMAGEIO_FFMPEG_EXE"] = r"C:ffmpeg.exe"

def space():
    space = Label(text="", bg="black")
    space.pack()

def open_location():

    global filename_splitted
    filename = askopenfilename()
    filename_ext = os.path.splitext(filename)
    filename_splitted = str(filename_ext).split('/')[4].split(".")[0].split(',')[0].split("'")[0]
    filename_ext_split = filename_ext[1][1:]

    if len(filename) > 1 and filename_ext_split == "mp4":
        path_url.config(text=filename_splitted, fg="green")

    else:
        messagebox.showwarning(title="oops", message="No video given!")
        path_url.config(text="Please specify a file (mp4)!", fg="red")

    return filename_splitted


def merge_vid():

    number_of_videos = box.get()
    if number_of_videos <= "1":
        messagebox.showwarning(title="Warning", message="Please specify how many videos you want to merge.")

    elif number_of_videos == "2":
        clip1 = VideoFileClip(f"{open_location()}.mp4")
        clip2 = VideoFileClip(f"{open_location()}.mp4")
        final_clip = concatenate_videoclips(clip1, clip2)
        final_clip.write_videofile('Final.mp4', codec="libx264")

    elif number_of_videos == "3":
        clip1 = VideoFileClip(f"{open_location()}.mp4")
        clip2 = VideoFileClip(f"{open_location()}.mp4")
        clip3 = VideoFileClip(f"{open_location()}.mp4")
        final_clip = concatenate_videoclips(clip1, clip2, clip3)
        final_clip.write_videofile('Final.mp4', codec="libx264")

    elif number_of_videos == "4":
        clip1 = VideoFileClip(f"{open_location()}.mp4")
        clip2 = VideoFileClip(f"{open_location()}.mp4")
        clip3 = VideoFileClip(f"{open_location()}.mp4")
        clip4 = VideoFileClip(f"{open_location()}.mp4")
        final_clip = concatenate_videoclips(clip1, clip2, clip3, clip4)
        final_clip.write_videofile('Final.mp4', codec="libx264")



# def start_merge():
#         merge_vid()

def put_music():
    # audio = AudioFileClip("Music.mp3")
    # video1 = VideoFileClip("Final.mp4")
    # final = video1.set_audio(audio)
    # final.write_videofile("output.mp4")
    pass



root = Tk()

space()
space()

# root.iconbitmap("yt.ico")
root.title("Video Editor")
root.geometry("350x350")
root.columnconfigure(0, weight=1)
root.config(bg="black")

# space()
# path_btn = Button(root, width=11, height=2, bg="#CC1B25", fg="white", text="Select Video", command=open_location)
# path_btn.pack()

space()
space()
space()
label = Label(root, text="How many videos do you want to merge:", bg="black", fg="white", font=("jost", 9, "bold"))
label.pack()

EntryVar = StringVar()
box = Entry(root, width=7, textvariable=EntryVar)
box.pack()

space()

merge_btn = Button(root, width=27, height=3, bg="green", fg="white", text="Choose and Merge Videos", command=merge_vid)
merge_btn.pack()

space()
space()

# start_merge_btn = Button(root, width=27, height=3, bg="green", fg="white", text="Start Merge", command=start_merge)
# start_merge_btn.pack()

path_url = Label(root, text="", fg="red", bg="black", font=("jost", 9, "bold"))
path_url.pack()






root.mainloop()
Asked By: CodeManiac

||

Answers:

Please read the moviepy docs for function concatenate_videoclips(clips, ..), especially about positional parameter clips:

clips
A list of video clips which must all have their duration
attributes set.

Following this, you should pass a list like [clip1, clip2] when invoking this method like this:

clip1 = VideoFileClip(f"{open_location()}.mp4")
clip2 = VideoFileClip(f"{open_location()}.mp4")
final_clip = concatenate_videoclips( [clip1, clip2] )  # both clips inside a list

See also the video concatenation example in the guide Mixing clips — MoviePy 1.0.2 documentation.

Answered By: hc_dev
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.