|
|
@@ -2,25 +2,26 @@ import os
|
|
|
import shutil
|
|
|
import sys
|
|
|
|
|
|
+# install PySimpleGUI if not installed
|
|
|
try:
|
|
|
import PySimpleGUI as sg
|
|
|
except ImportError:
|
|
|
print("Looks like you don't have PySimpleGUI installed, do you want me to install for you?\nyes/no")
|
|
|
yes_or_no = input()
|
|
|
- yes_set = {'yes', 'YES', 'Y', 'y', 'Yes'}
|
|
|
- if yes_or_no in yes_set:
|
|
|
+ if yes_or_no in ('yes', 'YES', 'Y', 'y', 'Yes'):
|
|
|
os.system('pip install pysimplegui')
|
|
|
+ import PySimpleGUI as sg
|
|
|
else:
|
|
|
raise ImportWarning('No PySimpleGUI package found')
|
|
|
|
|
|
|
|
|
-def get_video_list(dir: str):
|
|
|
+def get_video_list(folder: str):
|
|
|
all_videos = dict()
|
|
|
video_formats = {"mp4", "MP4"}
|
|
|
- all_files = os.listdir(dir)
|
|
|
+ all_files = os.listdir(folder)
|
|
|
for file_name in all_files:
|
|
|
try:
|
|
|
- isG = file_name[0]
|
|
|
+ is_g = file_name[0]
|
|
|
code_type = file_name[1]
|
|
|
ext_name = file_name[-3:]
|
|
|
# video_chapter = file_name[2:4]
|
|
|
@@ -28,7 +29,7 @@ def get_video_list(dir: str):
|
|
|
except IndexError:
|
|
|
continue
|
|
|
# GoPro files start with "G"
|
|
|
- if isG == 'G' and ext_name in video_formats:
|
|
|
+ if is_g == 'G' and ext_name in video_formats:
|
|
|
try:
|
|
|
all_videos[video_idx][0].append(file_name)
|
|
|
except KeyError:
|
|
|
@@ -43,42 +44,56 @@ def path_validation(source_dir, output_dir):
|
|
|
if not os.path.isdir(source_dir):
|
|
|
return False
|
|
|
if not os.path.isdir(output_dir):
|
|
|
- try:
|
|
|
- os.mkdir(output_dir)
|
|
|
- except:
|
|
|
- raise OSError("Faild to create the output folder.")
|
|
|
+ event = sg.popup_yes_no("The output folder doesn't exist, create it?")
|
|
|
+ if event == 'Yes':
|
|
|
+ try:
|
|
|
+ os.mkdir(output_dir)
|
|
|
+ except:
|
|
|
+ raise OSError("Faild to create the output folder.")
|
|
|
+ else:
|
|
|
+ return False
|
|
|
return True
|
|
|
|
|
|
|
|
|
-def do_the_job(source_dir, output_dir):
|
|
|
+def concat_videos(source_dir, output_dir):
|
|
|
if path_validation(source_dir, output_dir):
|
|
|
- os.chdir(input_dir)
|
|
|
+ os.chdir(output_dir)
|
|
|
videos = get_video_list(source_dir)
|
|
|
- chaptered_video_num = 0
|
|
|
- # print(videos)
|
|
|
+ sliced_video_num = 0
|
|
|
+ # Temp folder to store the .join file for FFmpeg
|
|
|
try:
|
|
|
os.mkdir("temp")
|
|
|
except FileExistsError:
|
|
|
pass
|
|
|
for name in videos.keys():
|
|
|
+ # if it is a sliced video
|
|
|
if len(videos[name][0]) > 1:
|
|
|
- chaptered_video_num += 1
|
|
|
- os.chdir(output_dir)
|
|
|
- os.chdir("temp")
|
|
|
+ sliced_video_num += 1
|
|
|
+ os.chdir(output_dir+"/temp")
|
|
|
+ # os.chdir("temp")
|
|
|
+ # create .join file which includes all chapters of the video
|
|
|
with open(f"{name}.join", 'w') as file:
|
|
|
chapters = videos[name][0]
|
|
|
for c in chapters:
|
|
|
file.write(f"file '{source_dir}/{c}'\n")
|
|
|
+ # Call FFmpeg to concatenate those videos
|
|
|
status = os.system(
|
|
|
f"ffmpeg -f concat -safe 0 -i {name}.join -c copy ../GX01{name}.mp4")
|
|
|
if status:
|
|
|
raise OSError("Something Goes Wrong With FFmpeg.")
|
|
|
+ # if it is a single video file, copy to the output folder
|
|
|
+ else:
|
|
|
+ print(videos)
|
|
|
+ shutil.copyfile(f'{source_dir}/{videos[name][0][0]}', output_dir+'/'+videos[name][0][0])
|
|
|
+ # clean temp folder
|
|
|
os.chdir(output_dir)
|
|
|
+ print(output_dir)
|
|
|
try:
|
|
|
shutil.rmtree('temp')
|
|
|
except FileNotFoundError:
|
|
|
+ print("Failed to clean temp folder")
|
|
|
pass
|
|
|
- sg.Window('Done', [[sg.T(f"Detected {len(videos.keys())} videos, {chaptered_video_num} are(is) sliced.")], [
|
|
|
+ sg.Window('Done', [[sg.T(f"Detected {len(videos.keys())} videos, {sliced_video_num} are(is) sliced.")], [
|
|
|
sg.Ok()]], disable_close=True).read(close=True)
|
|
|
else:
|
|
|
sg.popup_ok("Invalid Path")
|
|
|
@@ -86,38 +101,43 @@ def do_the_job(source_dir, output_dir):
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
+ # if using CLI mode
|
|
|
try:
|
|
|
_, source_dir, output_dir = sys.argv
|
|
|
- do_the_job(source_dir, output_dir)
|
|
|
+ concat_videos(source_dir, output_dir)
|
|
|
+ # start GUI
|
|
|
except ValueError:
|
|
|
sg.theme('SystemDefault') # please make your windows colorful
|
|
|
-
|
|
|
- # layout = [[sg.Text('Input Folder')],
|
|
|
- # [sg.Input(), sg.FolderBrowse()],
|
|
|
- # [sg.Text('Output Folder')],
|
|
|
- # [sg.Input(), sg.FolderBrowse()],
|
|
|
- # [sg.OK(), sg.Cancel()]]
|
|
|
- layout = [[sg.Text(' Input Folder', size=(10, 1)), sg.InputText(), sg.FolderBrowse()],
|
|
|
- [sg.Text('Output Folder', size=(10, 1)), sg.InputText(), sg.FolderBrowse()],
|
|
|
- [sg.Ok(), sg.Cancel()]]
|
|
|
-
|
|
|
- window = sg.Window('GoPro Video Concatenator', layout)
|
|
|
- event, values = window.read()
|
|
|
- if event == 'OK':
|
|
|
- input_dir, output_dir = values[0], values[1]
|
|
|
- if input_dir == output_dir:
|
|
|
- event = sg.popup_yes_no("Can't output to the same folder as input, please change the output folder.\n"
|
|
|
- "Press Yes to create an output folder")
|
|
|
- if event == "Yes":
|
|
|
- os.chdir(input_dir)
|
|
|
- try:
|
|
|
- os.mkdir('Output')
|
|
|
- except FileExistsError:
|
|
|
- pass
|
|
|
- output_dir += '/Output'
|
|
|
+ input_dir, output_dir = '', ''
|
|
|
+ while True:
|
|
|
+ layout = [[sg.Text(' Input Folder', size=(10, 1)), sg.InputText(input_dir), sg.FolderBrowse()],
|
|
|
+ [sg.Text('Output Folder', size=(10, 1)), sg.InputText(output_dir), sg.FolderBrowse()],
|
|
|
+ [sg.Ok()]]
|
|
|
+ window = sg.Window('GoPro Video Concatenation', layout)
|
|
|
+ event, values = window.read()
|
|
|
+ if event == 'Ok':
|
|
|
+ input_dir, output_dir = values[0], values[1]
|
|
|
+ if input_dir and output_dir:
|
|
|
+ print("pass")
|
|
|
+ if input_dir == output_dir:
|
|
|
+ event = sg.popup_yes_no("Can't output to the same folder as input, please change the output folder.\n"
|
|
|
+ "Or press Yes to create an output folder")
|
|
|
+ if event == "Yes":
|
|
|
+ os.chdir(input_dir)
|
|
|
+ try:
|
|
|
+ os.mkdir('Output')
|
|
|
+ except FileExistsError:
|
|
|
+ pass
|
|
|
+ output_dir += '/Output'
|
|
|
+ else:
|
|
|
+ window.close()
|
|
|
+ continue
|
|
|
+ concat_videos(input_dir, output_dir)
|
|
|
+ break
|
|
|
else:
|
|
|
+ sg.popup_ok("Please input paths")
|
|
|
window.close()
|
|
|
- do_the_job(input_dir, output_dir)
|
|
|
-
|
|
|
- elif event in (sg.WIN_CLOSED, 'Cancel'):
|
|
|
- window.close()
|
|
|
+
|
|
|
+ elif event == sg.WIN_CLOSED:
|
|
|
+ window.close()
|
|
|
+ break
|