concatGOPRO.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import os
  2. import shutil
  3. import sys
  4. # install PySimpleGUI if not installed
  5. try:
  6. import PySimpleGUI as sg
  7. except ImportError:
  8. print("Looks like you don't have PySimpleGUI installed, do you want me to install for you?\nyes/no")
  9. yes_or_no = input()
  10. if yes_or_no in ('yes', 'YES', 'Y', 'y', 'Yes'):
  11. os.system('pip install pysimplegui')
  12. import PySimpleGUI as sg
  13. else:
  14. raise ImportWarning('No PySimpleGUI package found')
  15. def get_video_list(folder: str):
  16. all_videos = dict()
  17. video_formats = {"mp4", "MP4"}
  18. all_files = os.listdir(folder)
  19. for file_name in all_files:
  20. try:
  21. is_g = file_name[0]
  22. code_type = file_name[1]
  23. ext_name = file_name[-3:]
  24. video_idx = file_name[4:8]
  25. except IndexError:
  26. continue
  27. # GoPro files start with "G"
  28. if is_g == 'G' and ext_name in video_formats:
  29. try:
  30. all_videos[video_idx][0].append(file_name)
  31. except KeyError:
  32. all_videos[video_idx] = [[file_name], code_type]
  33. # sort the chapters
  34. for video in all_videos.keys():
  35. all_videos[video][0] = sorted(all_videos[video][0])
  36. return all_videos
  37. def path_validation(source_dir, output_dir):
  38. if not os.path.isdir(source_dir):
  39. return False
  40. if not os.path.isdir(output_dir):
  41. event = sg.popup_yes_no("The output folder doesn't exist, create it?")
  42. if event == 'Yes':
  43. try:
  44. os.mkdir(output_dir)
  45. except:
  46. raise OSError("Faild to create the output folder.")
  47. else:
  48. return False
  49. return True
  50. def concat_videos(source_dir, output_dir):
  51. if path_validation(source_dir, output_dir):
  52. os.chdir(output_dir)
  53. videos = get_video_list(source_dir)
  54. sliced_video_num = 0
  55. # Temp folder to store the .join file for FFmpeg
  56. try:
  57. os.mkdir("temp")
  58. except FileExistsError:
  59. pass
  60. for name in videos.keys():
  61. # if it is a sliced video
  62. if len(videos[name][0]) > 1:
  63. sliced_video_num += 1
  64. os.chdir(output_dir+"/temp")
  65. # create .join file which includes all chapters of the video
  66. with open(f"{name}.join", 'w') as file:
  67. chapters = videos[name][0]
  68. for c in chapters:
  69. file.write(f"file '{source_dir}/{c}'\n")
  70. # Call FFmpeg to concatenate those videos
  71. status = os.system(
  72. f"ffmpeg -f concat -safe 0 -i {name}.join -c copy ../GX01{name}.mp4")
  73. if status:
  74. raise OSError("Something Goes Wrong With FFmpeg.")
  75. # if it is a single video file, copy to the output folder
  76. else:
  77. print(videos)
  78. shutil.copyfile(
  79. f'{source_dir}/{videos[name][0][0]}', output_dir+'/'+videos[name][0][0])
  80. # clean temp folder
  81. os.chdir(output_dir)
  82. print(output_dir)
  83. try:
  84. shutil.rmtree('temp')
  85. except FileNotFoundError:
  86. print("Failed to clean temp folder")
  87. pass
  88. sg.Window('Done', [[sg.T(f"Detected {len(videos.keys())} videos, {sliced_video_num} are(is) sliced.")], [
  89. sg.Ok()]], disable_close=True).read(close=True)
  90. else:
  91. sg.popup_ok("Invalid Path")
  92. raise FileNotFoundError("Invalid Path")
  93. if __name__ == "__main__":
  94. # if using CLI mode
  95. try:
  96. _, source_dir, output_dir = sys.argv
  97. concat_videos(source_dir, output_dir)
  98. # start GUI
  99. except ValueError:
  100. sg.theme('SystemDefault') # please make your windows colorful
  101. # input_dir, output_dir = '', ''
  102. layout = [[sg.Text(' Input Folder', size=(10, 1)), sg.InputText(), sg.FolderBrowse()],
  103. [sg.Text('Output Folder', size=(10, 1)), sg.InputText(), sg.FolderBrowse()],
  104. [sg.Ok()]]
  105. window = sg.Window('GoPro Video Concatenation', layout)
  106. while True:
  107. event, values = window.read()
  108. if event == 'Ok':
  109. input_dir, output_dir = values[0], values[1]
  110. # check if it is empty string
  111. if input_dir and output_dir and path_validation(input_dir, output_dir):
  112. if input_dir == output_dir:
  113. event = sg.popup_yes_no("Can't output to the same folder as input, please change the output folder."
  114. "Or press Yes to create an output folder")
  115. if event == "Yes":
  116. os.chdir(input_dir)
  117. try:
  118. os.mkdir('Output')
  119. except FileExistsError:
  120. pass
  121. output_dir += '/Output'
  122. else:
  123. continue
  124. concat_videos(input_dir, output_dir)
  125. window.close() # job done
  126. else:
  127. sg.popup_ok("Please input valid paths")
  128. elif event == sg.WIN_CLOSED:
  129. window.close()
  130. break