concatGOPRO.py 5.3 KB

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