Hello and welcome back to this final part of the video editing project. After this chapter, you will be good enough to continue to develop this application by yourself and hopefully, you can come out with a better idea of how to further develop this video editing application.
In this chapter I have created a thread for this video editing application which will separate the application into two part, the user interface part and the thread part. The user interface part will take care of the user’s click event and the user’s input and the threaded part will process the user input.
There is nothing new in this chapter besides separate the application into two part. The first part is the user interface part.
from tkinter import *
from tkinter import filedialog
import tkinter.ttk as tk
from tkinter import messagebox
from NewVid import NewVid
import webbrowser
win = Tk() # Create tk instance
win.title("NeW Vid") # Add a title
win.resizable(0, 0) # Disable resizing the GUI
win.configure(background='white') # change background color
mainframe = Frame(win) # create a frame
mainframe.pack()
eqFrame = Frame(win) # create eq frame
eqFrame.pack(side = TOP, fill=X)
animatedFrame = Frame(win) # create animated frame
animatedFrame.pack(side = TOP, fill=X)
trimFrame = Frame(win) # create trim frame
trimFrame.pack(side = TOP, fill=X)
buttonFrame = Frame(win) # create a button frame
buttonFrame.pack(side = BOTTOM, fill=X, pady = 6)
# Create a label and scale box for eq
contrast_variable = DoubleVar()
contrast = Scale(eqFrame, from_=float(-2.00), to=float(2.00), orient=HORIZONTAL, label="CONTRAST", digits=3, resolution=0.01, variable=contrast_variable)
contrast.set(1)
contrast.pack(side = LEFT)
brightness_variable = DoubleVar()
brightness = Scale(eqFrame, from_=float(-1.00), to=float(1.00), orient=HORIZONTAL, label="BRIGHTNESS", digits=3, resolution=0.01, variable=brightness_variable)
brightness.pack(side = LEFT)
saturation_variable = DoubleVar()
saturation = Scale(eqFrame, from_=float(0.00), to=float(3.00), orient=HORIZONTAL, label="SATURATION", digits=3, resolution=0.01, variable=saturation_variable)
saturation.set(1)
saturation.pack(side = LEFT)
gamma_variable = DoubleVar()
gamma = Scale(eqFrame, from_=float(0.10), to=float(10.00), orient=HORIZONTAL, label="GAMMA", digits=4, resolution=0.01, variable=gamma_variable)
gamma.set(1)
gamma.pack(side = LEFT)
loop_variable = DoubleVar()
loop = Scale(eqFrame, from_=float(0), to=float(10), orient=HORIZONTAL, label="REPEAT", digits=2, resolution=1, variable=loop_variable)
loop.pack(side = LEFT)
fr_variable = DoubleVar()
fr = Scale(eqFrame, from_=float(9), to=float(60), orient=HORIZONTAL, label="FPS", digits=2, resolution=1, variable=fr_variable)
fr.set(24)
fr.pack(side = LEFT)
#create animated gif
anime = Label(animatedFrame, text="Create Animated Image from Video ")
anime.pack(side = TOP)
anime.pack(side = LEFT)
from_ = Label(animatedFrame, text="Start From (hour : minute : second) ")
from_.pack(side = BOTTOM)
from_.pack(side = LEFT)
from_t_h_varable = StringVar()
from_t_h = Entry(animatedFrame, width=3, textvariable=from_t_h_varable)
from_t_h.pack(side=BOTTOM)
from_t_h.pack(side=LEFT)
from_m = Label(animatedFrame, text=" : ")
from_m.pack(side = BOTTOM)
from_m.pack(side = LEFT)
from_t_m_varable = StringVar()
from_t_m = Entry(animatedFrame, width=3,textvariable=from_t_m_varable)
from_t_m.pack(side=BOTTOM)
from_t_m.pack(side=LEFT)
from_s = Label(animatedFrame, text=" : ")
from_s.pack(side = BOTTOM)
from_s.pack(side = LEFT)
from_t_s_varable = StringVar()
from_t_s = Entry(animatedFrame, width=3,textvariable=from_t_s_varable)
from_t_s.pack(side=BOTTOM)
from_t_s.pack(side=LEFT)
to_ = Label(animatedFrame, text=" To (in second) ")
to_.pack(side = BOTTOM)
to_.pack(side = LEFT)
to_t_s_varable = StringVar()
to_t_s = Entry(animatedFrame, width=3,textvariable=to_t_s_varable)
to_t_s.pack(side=BOTTOM)
to_t_s.pack(side=LEFT)
#trim video
trim = Label(trimFrame, text="Trim Video ")
trim.pack(side = TOP)
trim.pack(side = LEFT)
trim_from_ = Label(trimFrame, text="Start From (hour : minute : second) ")
trim_from_.pack(side = BOTTOM)
trim_from_.pack(side = LEFT)
trim_from_t_h_varable = StringVar()
trim_from_t_h = Entry(trimFrame, width=3, textvariable=trim_from_t_h_varable)
trim_from_t_h.pack(side=BOTTOM)
trim_from_t_h.pack(side=LEFT)
trim_from_m = Label(trimFrame, text=" : ")
trim_from_m.pack(side = BOTTOM)
trim_from_m.pack(side = LEFT)
trim_from_t_m_varable = StringVar()
trim_from_t_m = Entry(trimFrame, width=3,textvariable=trim_from_t_m_varable)
trim_from_t_m.pack(side=BOTTOM)
trim_from_t_m.pack(side=LEFT)
trim_from_s = Label(trimFrame, text=" : ")
trim_from_s.pack(side = BOTTOM)
trim_from_s.pack(side = LEFT)
trim_from_t_s_varable = StringVar()
trim_from_t_s = Entry(trimFrame, width=3,textvariable=trim_from_t_s_varable)
trim_from_t_s.pack(side=BOTTOM)
trim_from_t_s.pack(side=LEFT)
trim_to_ = Label(trimFrame, text=" To (in second) ")
trim_to_.pack(side = BOTTOM)
trim_to_.pack(side = LEFT)
trim_to_t_h_varable = StringVar()
trim_to_t_h = Entry(trimFrame, width=3,textvariable=trim_to_t_h_varable)
trim_to_t_h.pack(side=BOTTOM)
trim_to_t_h.pack(side=LEFT)
trim_to_m = Label(trimFrame, text=" : ")
trim_to_m.pack(side = BOTTOM)
trim_to_m.pack(side = LEFT)
trim_to_t_m_varable = StringVar()
trim_to_t_m = Entry(trimFrame, width=3,textvariable=trim_to_t_m_varable)
trim_to_t_m.pack(side=BOTTOM)
trim_to_t_m.pack(side=LEFT)
trim_to_s = Label(trimFrame, text=" : ")
trim_to_s.pack(side = BOTTOM)
trim_to_s.pack(side = LEFT)
trim_to_t_s_varable = StringVar()
trim_to_t_s = Entry(trimFrame, width=3,textvariable=trim_to_t_s_varable)
trim_to_t_s.pack(side=BOTTOM)
trim_to_t_s.pack(side=LEFT)
# Create a combo box
vid_size = StringVar() # create a string variable
preferSize = tk.Combobox(mainframe, textvariable=vid_size)
preferSize['values'] = (1920, 1280, 854, 640) # video width in pixels
preferSize.current(0) # select item one
preferSize.pack(side = LEFT)
# Create a combo box
vid_format = StringVar() # create a string variable
preferFormat = tk.Combobox(mainframe, textvariable=vid_format)
preferFormat['values'] = ('.mp4', '.webm', '.avi', '.wmv', '.mpg', '.ogv') # video format
preferFormat.current(0) # select item one
preferFormat.pack(side = LEFT)
removeAudioVal = IntVar()
removeAudio = tk.Checkbutton(mainframe, text="Remove Audio", variable=removeAudioVal)
removeAudio.pack(side = LEFT, padx=3)
newAudio = IntVar()
aNewAudio = tk.Checkbutton(mainframe, text="New Audio", variable=newAudio)
aNewAudio.pack(side = LEFT, padx=2)
count = 0 # counter uses to create multiple videos
btn_text = StringVar() # button text
# Open a video file
def openVideo():
audiofilename = ''
fullfilename = filedialog.askopenfilename(initialdir="/", title="Select a file", filetypes=[("Video file", "*.mp4; *.avi ")]) # select a video file from the hard drive
if(newAudio.get() == 1):
audiofilename = filedialog.askopenfilename(initialdir="/", title="Select a file", filetypes=[("Audio file", "*.wav; *.ogg ")]) # select a new audio file from the hard drive
global count # access the global count variable
if(fullfilename != ''):
scale_vid = preferSize.get() # retrieve value from the comno box
new_size = str(scale_vid)
file_extension = fullfilename.split('.')[-1] # extract the video format from the original video
f = '_new_vid_' + new_size + '.' + file_extension # the new output file name
f2 = str(count)+f # second video
f_gif = str(count) + f + '.gif' # create animated gif
count += 1 # increase video counter for new video
# create animated image from video
animi_from_hour = from_t_h_varable.get()
animi_from_minute = from_t_m_varable.get()
animi_from_second = from_t_s_varable.get()
animi_to_second = to_t_s_varable.get()
# video editing part start here
noAudio = removeAudioVal.get() # get the checkbox state for audio
# trim video starting point and end point
trim_from_hour = trim_from_t_h_varable.get()
trim_from_minute = trim_from_t_m_varable.get()
trim_from_second = trim_from_t_s_varable.get()
trim_to_hour = trim_to_t_h_varable.get()
trim_to_minute = trim_to_t_m_varable.get()
trim_to_second = trim_to_t_s_varable.get()
f3 = f + vid_format.get() # The final video format
contrast_value = str(contrast_variable.get())
brightness_value = str(brightness_variable.get())
saturation_value = str(saturation_variable.get())
gamma_value = str(gamma_variable.get())
loop_value = str(loop_variable.get())
frame_rate_value = str(fr_variable.get())
try:
new_vide_thread = NewVid(contrast_value, brightness_value, saturation_value, gamma_value, loop_value, frame_rate_value, new_size, noAudio, file_extension, f, f2, f3, f_gif, audiofilename, fullfilename, animi_from_hour, animi_from_minute, animi_from_second, animi_to_second, trim_from_hour, trim_from_minute, trim_from_second, trim_to_hour, trim_to_minute, trim_to_second)
new_vide_thread.start()
new_vide_thread.join()
except:
messagebox.showinfo("Error", "You need to install FFmpeg before using this program!")
webbrowser.open('https://www.ffmpeg.org/')
else:
messagebox.showinfo("Error", "You need to select a video file!")
action_vid = tk.Button(buttonFrame, command=openVideo, text="Select Video")
action_vid.pack(fill=X)
win.mainloop()
The second part is the thread part,
import os
import subprocess
import threading
class NewVid(threading.Thread):
def __init__(self, contrast_value, brightness_value, saturation_value, gamma_value, loop_value, frame_rate_value, new_size, noAudio, file_extension, f, f2, f3, f_gif, audiofilename, fullfilename, animi_from_hour, animi_from_minute, animi_from_second, animi_to_second, trim_from_hour, trim_from_minute, trim_from_second, trim_to_hour, trim_to_minute, trim_to_second):
threading.Thread.__init__(self)
self.contrast_value = contrast_value
self.brightness_value = brightness_value
self.saturation_value = saturation_value
self.gamma_value = gamma_value
self.loop_value = loop_value
self.frame_rate_value = frame_rate_value
self.new_size =new_size
self.noAudio = noAudio
self.file_extension = file_extension
self.f = f
self.f2 = f2
self.f3 = f3
self.f_gif = f_gif
self.audiofilename = audiofilename
self.fullfilename = fullfilename
self.animi_from_hour = animi_from_hour
self.animi_from_minute = animi_from_hour
self.animi_from_second = animi_from_second
self.animi_to_second = animi_to_second
self.trim_from_hour = trim_from_hour
self.trim_from_minute = trim_from_minute
self.trim_from_second = trim_from_second
self.trim_to_hour = trim_to_hour
self.trim_to_minute = trim_to_minute
self.trim_to_second = trim_to_second
# Processing video file
def run(self):
dir_path = os.path.dirname(os.path.realpath(self.fullfilename))
self.trim_video = False # set the trim video flag to false
os.chdir(dir_path) # change the directory to the original file's directory
# if the time areas are not empty and they have a digit then only the animated gif will be created
if((self.animi_from_hour != '' and self.animi_from_hour.isdigit()) and (self.animi_from_minute != '' and self.animi_from_minute.isdigit()) and (self.animi_from_second != '' and self.animi_from_second.isdigit()) and (self.animi_to_second != '' and self.animi_to_second.isdigit())):
subprocess.call(['ffmpeg', '-i', self.fullfilename, '-vf', 'scale=' + self.new_size + ':-1', '-y', self.f]) # resize video
subprocess.call(['ffmpeg', '-i', self.f, '-vf', 'eq=contrast=' + self.contrast_value +':brightness='+ self.brightness_value +':saturation=' + self.saturation_value +':gamma=' + self.gamma_value, '-y', self.f2]) # adjust the saturation, gamma, contrast and brightness of video
subprocess.call(['ffmpeg', '-i', self.f2, '-ss', self.animi_from_hour + ':' + self.animi_from_minute + ':' + self.animi_from_second, '-t', self.animi_to_second, '-y', self.f_gif]) # creating animated gif from starting point to end point
os.remove(self.f)
os.remove(self.f2)
return 0
# video editing part start here
subprocess.call(['ffmpeg', '-stream_loop', (self.loop_value), '-i', self.fullfilename, '-vf', 'scale=' + self.new_size + ':-1', '-y', '-r', self.frame_rate_value, self.f]) # resize, speedup and loop the video with ffmpeg
subprocess.call(['ffmpeg', '-i', self.f, '-vf', 'eq=contrast=' + self.contrast_value +':brightness='+ self.brightness_value +':saturation=' + self.saturation_value +':gamma=' + self.gamma_value, '-y', self.f2]) # adjust the saturation, gamma, contrast and brightness of video
# if the time areas are not empty and they have a digit then trim the video
if((self.trim_from_hour != '' and self.trim_from_hour.isdigit()) and (self.trim_from_minute != '' and self.trim_from_minute.isdigit()) and (self.trim_from_second != '' and self.trim_from_second.isdigit()) and (self.trim_to_second != '' and self.trim_to_second.isdigit()) and (self.trim_to_minute != '' and self.trim_to_minute.isdigit()) and (self.trim_to_hour != '' and self.trim_to_hour.isdigit())):
subprocess.call(['ffmpeg', '-i', self.f2, '-ss', self.trim_from_hour + ':' + self.trim_from_minute + ':' + self.trim_from_second, '-t', self.trim_to_hour + ':' + self.trim_to_minute + ':' + self.trim_to_second, '-y', '-c:v', 'copy', '-c:a', 'copy', self.f]) # trim the video from start to end point
self.trim_video = True
if(self.noAudio == 1 and self.trim_video == True):
subprocess.call(['ffmpeg', '-i', self.f, '-c', 'copy', '-y', '-an', self.f2]) # remove audio from the original video
elif(self.noAudio == 1 and self.trim_video == False):
subprocess.call(['ffmpeg', '-i', self.f2, '-c', 'copy', '-y', '-an', self.f]) # remove audio from the original video
if(self.audiofilename != '' and self.noAudio == 1 and self.trim_video == False):
subprocess.call(['ffmpeg', '-i', self.f, '-i', self.audiofilename, '-shortest', '-c:v', 'copy', '-b:a', '256k', '-y', self.f2]) # add audio to the original video, trim either the audio or video depends on which one is longer
elif(self.audiofilename != '' and self.noAudio == 1 and self.trim_video == True):
subprocess.call(['ffmpeg', '-i', self.f2, '-i', self.audiofilename, '-shortest', '-c:v', 'copy', '-b:a', '256k', '-y', self.f]) # add audio to the original video, trim either the audio or video depends on which one is longer
if(self.f3.split('.')[-1] != self.f2.split('.')[-1] and self.trim_video == True and self.noAudio == 1 and self.audiofilename != ''):
subprocess.call(['ffmpeg', '-i', self.f, '-y', self.f3]) # converting the video with ffmpeg
os.remove(self.f2) # remove two videos
os.remove(self.f)
elif(self.f3.split('.')[-1] != self.f2.split('.')[-1] and self.trim_video == False and self.noAudio == 1 and self.audiofilename != ''):
subprocess.call(['ffmpeg', '-i', self.f2, '-y', self.f3]) # converting the video with ffmpeg
os.remove(self.f2) # remove two videos
os.remove(self.f)
elif(self.f3.split('.')[-1] != self.f2.split('.')[-1] and self.trim_video == False and self.noAudio != 1 and self.audiofilename == ''):
subprocess.call(['ffmpeg', '-i', self.f2, '-y', self.f3]) # converting the video with ffmpeg
os.remove(self.f2) # remove two videos
os.remove(self.f)
elif(self.f3.split('.')[-1] == self.f2.split('.')[-1] and self.trim_video == True and self.noAudio == 1 and self.audiofilename != ''):
os.remove(self.f2) # remove one video
elif(self.f3.split('.')[-1] == self.f2.split('.')[-1] and self.trim_video == True and self.noAudio != 1):
os.remove(self.f2) # remove one video
elif(self.f3.split('.')[-1] == self.f2.split('.')[-1] and self.trim_video == False and self.noAudio != 1):
os.remove(self.f) # remove one video
elif(self.f3.split('.')[-1] == self.f2.split('.')[-1] and self.trim_video == False and self.noAudio == 1):
os.remove(self.f2) # remove one video
else:
os.remove(self.f) # remove one video
self.trim_video = False # reset the trim video flag to false
Well, now is your turn to edit this application then use it to edit video. How about creating a progress bar which tells the user how much time he still needs to wait for the software to finish editing the video?
from Planet Python
via read more
No comments:
Post a Comment