subtitld 0.0.0.dev0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. subtitld/__init__.py +19 -0
  2. subtitld/__main__.py +240 -0
  3. subtitld/ftfy/char_classes.dat +0 -0
  4. subtitld/graphics/Montserrat-Black.ttf +0 -0
  5. subtitld/graphics/Montserrat-BlackItalic.ttf +0 -0
  6. subtitld/graphics/Montserrat-Bold.ttf +0 -0
  7. subtitld/graphics/Montserrat-BoldItalic.ttf +0 -0
  8. subtitld/graphics/Montserrat-ExtraBold.ttf +0 -0
  9. subtitld/graphics/Montserrat-ExtraBoldItalic.ttf +0 -0
  10. subtitld/graphics/Montserrat-ExtraLight.ttf +0 -0
  11. subtitld/graphics/Montserrat-ExtraLightItalic.ttf +0 -0
  12. subtitld/graphics/Montserrat-Italic.ttf +0 -0
  13. subtitld/graphics/Montserrat-Light.ttf +0 -0
  14. subtitld/graphics/Montserrat-LightItalic.ttf +0 -0
  15. subtitld/graphics/Montserrat-Medium.ttf +0 -0
  16. subtitld/graphics/Montserrat-MediumItalic.ttf +0 -0
  17. subtitld/graphics/Montserrat-Regular.ttf +0 -0
  18. subtitld/graphics/Montserrat-SemiBold.ttf +0 -0
  19. subtitld/graphics/Montserrat-SemiBoldItalic.ttf +0 -0
  20. subtitld/graphics/Montserrat-Thin.ttf +0 -0
  21. subtitld/graphics/Montserrat-ThinItalic.ttf +0 -0
  22. subtitld/graphics/Ubuntu-B.ttf +0 -0
  23. subtitld/graphics/Ubuntu-BI.ttf +0 -0
  24. subtitld/graphics/Ubuntu-C.ttf +0 -0
  25. subtitld/graphics/Ubuntu-L.ttf +0 -0
  26. subtitld/graphics/Ubuntu-LI.ttf +0 -0
  27. subtitld/graphics/Ubuntu-M.ttf +0 -0
  28. subtitld/graphics/Ubuntu-MI.ttf +0 -0
  29. subtitld/graphics/Ubuntu-R.ttf +0 -0
  30. subtitld/graphics/Ubuntu-RI.ttf +0 -0
  31. subtitld/graphics/Ubuntu-Th.ttf +0 -0
  32. subtitld/graphics/UbuntuMono-B.ttf +0 -0
  33. subtitld/graphics/UbuntuMono-BI.ttf +0 -0
  34. subtitld/graphics/UbuntuMono-R.ttf +0 -0
  35. subtitld/graphics/UbuntuMono-RI.ttf +0 -0
  36. subtitld/graphics/add_and_play.svg +4 -0
  37. subtitld/graphics/add_from_last.svg +4 -0
  38. subtitld/graphics/add_from_last_checked.svg +4 -0
  39. subtitld/graphics/add_subtitle_icon.svg +4 -0
  40. subtitld/graphics/add_subtitle_to_next_start.svg +4 -0
  41. subtitld/graphics/add_subtitle_to_next_start_checked.svg +4 -0
  42. subtitld/graphics/background_watermark.svg +9 -0
  43. subtitld/graphics/character_count_icon.svg +1 -0
  44. subtitld/graphics/checkbox_checked.svg +8 -0
  45. subtitld/graphics/checkbox_checked_hover.svg +8 -0
  46. subtitld/graphics/checkbox_disabled.svg +4 -0
  47. subtitld/graphics/checkbox_unchecked.svg +5 -0
  48. subtitld/graphics/checkbox_unchecked_hover.svg +5 -0
  49. subtitld/graphics/combobox_down_arrow.svg +4 -0
  50. subtitld/graphics/cps_icon.svg +1 -0
  51. subtitld/graphics/dialog_close_icon.svg +4 -0
  52. subtitld/graphics/dialog_close_icon_hover.svg +4 -0
  53. subtitld/graphics/dubbing_container_collapse_icon.svg +8 -0
  54. subtitld/graphics/dubbing_container_expand_icon.svg +4 -0
  55. subtitld/graphics/file.svg +4 -0
  56. subtitld/graphics/gap_add_icon.svg +4 -0
  57. subtitld/graphics/gap_remove_icon.svg +4 -0
  58. subtitld/graphics/grid_frames_icon.svg +4 -0
  59. subtitld/graphics/grid_frames_icon_checked.svg +4 -0
  60. subtitld/graphics/grid_frames_icon_disabled.svg +4 -0
  61. subtitld/graphics/grid_scenes_icon.svg +4 -0
  62. subtitld/graphics/grid_scenes_icon_checked.svg +4 -0
  63. subtitld/graphics/grid_scenes_icon_disabled.svg +4 -0
  64. subtitld/graphics/grid_seconds_icon.svg +4 -0
  65. subtitld/graphics/grid_seconds_icon_checked.svg +4 -0
  66. subtitld/graphics/grid_seconds_icon_disabled.svg +4 -0
  67. subtitld/graphics/last_end_to_current_position_icon.svg +4 -0
  68. subtitld/graphics/last_start_last_end_to_current_position_button.svg +9 -0
  69. subtitld/graphics/last_start_to_current_position_icon.svg +4 -0
  70. subtitld/graphics/left_panel_autosave.svg +4 -0
  71. subtitld/graphics/left_panel_dubbing.svg +4 -0
  72. subtitld/graphics/left_panel_export.svg +4 -0
  73. subtitld/graphics/left_panel_global.svg +4 -0
  74. subtitld/graphics/left_panel_import.svg +4 -0
  75. subtitld/graphics/left_panel_interface.svg +4 -0
  76. subtitld/graphics/left_panel_keyboard.svg +4 -0
  77. subtitld/graphics/left_panel_metadata.svg +4 -0
  78. subtitld/graphics/left_panel_navigation_background.svg +11 -0
  79. subtitld/graphics/left_panel_qualitycheck.svg +4 -0
  80. subtitld/graphics/left_panel_speakers.svg +4 -0
  81. subtitld/graphics/left_panel_subtitles.svg +1 -0
  82. subtitld/graphics/left_panel_transcription.svg +4 -0
  83. subtitld/graphics/left_panel_translation.svg +4 -0
  84. subtitld/graphics/merge_back_selected_subtitle_icon.svg +4 -0
  85. subtitld/graphics/merge_next_selected_subtitle_icon.svg +4 -0
  86. subtitld/graphics/move_backward_subtitle.svg +4 -0
  87. subtitld/graphics/move_end_back_subtitle.svg +4 -0
  88. subtitld/graphics/move_end_forward_subtitle.svg +4 -0
  89. subtitld/graphics/move_forward_subtitle.svg +4 -0
  90. subtitld/graphics/move_start_back_subtitle.svg +4 -0
  91. subtitld/graphics/move_start_forward_subtitle.svg +4 -0
  92. subtitld/graphics/music_voice_separation_music_icon.svg +4 -0
  93. subtitld/graphics/music_voice_separation_music_icon_disabled.svg +4 -0
  94. subtitld/graphics/music_voice_separation_voice_icon.svg +4 -0
  95. subtitld/graphics/music_voice_separation_voice_icon_disabled.svg +4 -0
  96. subtitld/graphics/new_line_icon.svg +1 -0
  97. subtitld/graphics/next_end_to_current_position_icon.svg +4 -0
  98. subtitld/graphics/next_start_next_end_to_current_position_button.svg +4 -0
  99. subtitld/graphics/next_start_to_current_position_icon.svg +4 -0
  100. subtitld/graphics/pause_icon.svg +12 -0
  101. subtitld/graphics/play_from_last_start_icon.svg +5 -0
  102. subtitld/graphics/play_from_next_start_icon.svg +7 -0
  103. subtitld/graphics/play_icon.svg +12 -0
  104. subtitld/graphics/play_icon_hover.svg +12 -0
  105. subtitld/graphics/play_icon_pressed.svg +12 -0
  106. subtitld/graphics/playback_repeat.svg +4 -0
  107. subtitld/graphics/playback_speed.svg +6 -0
  108. subtitld/graphics/playbackspeed_border.svg +5 -0
  109. subtitld/graphics/playbackspeed_border_checked.svg +5 -0
  110. subtitld/graphics/playbackspeed_border_hover.svg +5 -0
  111. subtitld/graphics/playercontrols_button_first.svg +5 -0
  112. subtitld/graphics/playercontrols_button_first_hover.svg +6 -0
  113. subtitld/graphics/playercontrols_button_first_pressed.svg +6 -0
  114. subtitld/graphics/playercontrols_button_last.svg +6 -0
  115. subtitld/graphics/playercontrols_button_last_hover.svg +6 -0
  116. subtitld/graphics/playercontrols_button_last_pressed.svg +6 -0
  117. subtitld/graphics/playercontrols_widget_center_bottom_line.svg +13 -0
  118. subtitld/graphics/playercontrols_widget_center_top_line.svg +17 -0
  119. subtitld/graphics/plus_icon.svg +4 -0
  120. subtitld/graphics/record_icon.svg +8 -0
  121. subtitld/graphics/record_icon_pressed.svg +5 -0
  122. subtitld/graphics/remove_selected_subtitle_icon.svg +6 -0
  123. subtitld/graphics/repeat_playback_border.svg +5 -0
  124. subtitld/graphics/repeat_playback_border_checked.svg +5 -0
  125. subtitld/graphics/repeat_playback_border_hover.svg +5 -0
  126. subtitld/graphics/save.svg +4 -0
  127. subtitld/graphics/send_text_to_last_subtitle_and_slice_button.svg +8 -0
  128. subtitld/graphics/send_text_to_last_subtitle_icon.svg +8 -0
  129. subtitld/graphics/send_text_to_next_subtitle_and_slice_button.svg +8 -0
  130. subtitld/graphics/send_text_to_next_subtitle_icon.svg +8 -0
  131. subtitld/graphics/slice_selected_subtitle_icon.svg +4 -0
  132. subtitld/graphics/snap_grid_icon.svg +4 -0
  133. subtitld/graphics/snap_grid_icon_checked.svg +4 -0
  134. subtitld/graphics/snap_grid_icon_disabled.svg +4 -0
  135. subtitld/graphics/snap_limits_icon.svg +4 -0
  136. subtitld/graphics/snap_limits_icon_checked.svg +4 -0
  137. subtitld/graphics/snap_limits_icon_disabled.svg +4 -0
  138. subtitld/graphics/snap_move_next.svg +4 -0
  139. subtitld/graphics/snap_move_next_checked.svg +4 -0
  140. subtitld/graphics/snap_move_next_disabled.svg +4 -0
  141. subtitld/graphics/snap_moving_icon.svg +4 -0
  142. subtitld/graphics/snap_moving_icon_checked.svg +4 -0
  143. subtitld/graphics/snap_moving_icon_disabled.svg +4 -0
  144. subtitld/graphics/speaker_list_item_change_color_icon.svg +4 -0
  145. subtitld/graphics/speaker_list_item_change_color_icon_hover.svg +4 -0
  146. subtitld/graphics/speaker_list_item_change_image_icon.svg +4 -0
  147. subtitld/graphics/speaker_list_item_change_image_icon_hover.svg +4 -0
  148. subtitld/graphics/speaker_list_item_export_icon.svg +4 -0
  149. subtitld/graphics/speaker_list_item_export_icon_hover.svg +4 -0
  150. subtitld/graphics/speaker_list_item_remove_icon.svg +4 -0
  151. subtitld/graphics/speaker_list_item_remove_icon_hover.svg +4 -0
  152. subtitld/graphics/speaker_list_item_rename_icon.svg +4 -0
  153. subtitld/graphics/speaker_list_item_rename_icon_hover.svg +4 -0
  154. subtitld/graphics/spinbox_arrow_down.svg +4 -0
  155. subtitld/graphics/spinbox_arrow_up.svg +4 -0
  156. subtitld/graphics/start_screen_top_shadow.svg +23 -0
  157. subtitld/graphics/stop_icon.svg +6 -0
  158. subtitld/graphics/stop_icon_hover.svg +6 -0
  159. subtitld/graphics/stop_icon_pressed.svg +6 -0
  160. subtitld/graphics/stylesheet.qss +1838 -0
  161. subtitld/graphics/subtitld.ico +0 -0
  162. subtitld/graphics/subtitld.png +0 -0
  163. subtitld/graphics/subtitles_panel_simplelist_properties_duration_timing_lock_closed_icon.svg +4 -0
  164. subtitld/graphics/subtitles_panel_simplelist_properties_duration_timing_lock_open_icon.svg +4 -0
  165. subtitld/graphics/subtitles_panel_simplelist_properties_duration_timing_lock_open_icon_hover.svg +4 -0
  166. subtitld/graphics/timeline_bottom_controls_background.svg +25 -0
  167. subtitld/graphics/timeline_cursor_back_frame.svg +4 -0
  168. subtitld/graphics/timeline_cursor_back_frame_hover.svg +4 -0
  169. subtitld/graphics/timeline_cursor_next_frame.svg +4 -0
  170. subtitld/graphics/timeline_cursor_next_frame_hover.svg +4 -0
  171. subtitld/graphics/timeline_show_speaker_color.svg +5 -0
  172. subtitld/graphics/timeline_show_speaker_color_checked.svg +5 -0
  173. subtitld/graphics/timeline_show_speaker_in_tracks.svg +4 -0
  174. subtitld/graphics/timeline_show_speaker_in_tracks_checked.svg +4 -0
  175. subtitld/graphics/timelinescrolling_follow_icon.svg +4 -0
  176. subtitld/graphics/timelinescrolling_follow_icon_checked.svg +4 -0
  177. subtitld/graphics/timelinescrolling_none_icon.svg +6 -0
  178. subtitld/graphics/timelinescrolling_none_icon_checked.svg +6 -0
  179. subtitld/graphics/timelinescrolling_page_icon.svg +4 -0
  180. subtitld/graphics/timelinescrolling_page_icon_checked.svg +4 -0
  181. subtitld/graphics/titleBar_left_container_border.svg +113 -0
  182. subtitld/graphics/unknown_speaker.svg +5 -0
  183. subtitld/graphics/vosk_transcription_download_model_icon.svg +4 -0
  184. subtitld/graphics/vosk_transcription_update_model_icon.svg +4 -0
  185. subtitld/graphics/word_count_icon.svg +1 -0
  186. subtitld/graphics/wpm_icon.svg +1 -0
  187. subtitld/graphics/zoom_in_icon.svg +4 -0
  188. subtitld/graphics/zoom_in_icon_disabled.svg +4 -0
  189. subtitld/graphics/zoom_out_icon.svg +4 -0
  190. subtitld/graphics/zoom_out_icon_disabled.svg +4 -0
  191. subtitld/interface/__init__.py +0 -0
  192. subtitld/interface/actionmanager.py +18 -0
  193. subtitld/interface/bottom_panel.py +43 -0
  194. subtitld/interface/left_panel.py +144 -0
  195. subtitld/interface/left_panel_autosave.py +149 -0
  196. subtitld/interface/left_panel_dubbing.py +469 -0
  197. subtitld/interface/left_panel_export.py +755 -0
  198. subtitld/interface/left_panel_global.py +358 -0
  199. subtitld/interface/left_panel_import.py +82 -0
  200. subtitld/interface/left_panel_interface.py +616 -0
  201. subtitld/interface/left_panel_keyboard.py +261 -0
  202. subtitld/interface/left_panel_metadata.py +74 -0
  203. subtitld/interface/left_panel_qualitycheck.py +262 -0
  204. subtitld/interface/left_panel_speakers.py +737 -0
  205. subtitld/interface/left_panel_subtitleslist.py +791 -0
  206. subtitld/interface/left_panel_transcription.py +763 -0
  207. subtitld/interface/left_panel_translation.py +294 -0
  208. subtitld/interface/playercontrols.py +2348 -0
  209. subtitld/interface/preview_panel.py +407 -0
  210. subtitld/interface/productionscreen.py +65 -0
  211. subtitld/interface/startscreen.py +273 -0
  212. subtitld/interface/timeline.py +1308 -0
  213. subtitld/interface/top_bar.py +329 -0
  214. subtitld/interface/translation.py +68 -0
  215. subtitld/interface/utils.py +286 -0
  216. subtitld/locale/en_US.json +301 -0
  217. subtitld/locale/pt_BR.json +269 -0
  218. subtitld/modules/__init__.py +0 -0
  219. subtitld/modules/audioengine.py +606 -0
  220. subtitld/modules/bounce.py +229 -0
  221. subtitld/modules/config.py +84 -0
  222. subtitld/modules/file_io.py +870 -0
  223. subtitld/modules/history.py +31 -0
  224. subtitld/modules/quality_check.py +53 -0
  225. subtitld/modules/session.py +270 -0
  226. subtitld/modules/shortcuts.py +84 -0
  227. subtitld/modules/subtitles.py +413 -0
  228. subtitld/modules/timecode.py +496 -0
  229. subtitld/modules/usf.py +366 -0
  230. subtitld/modules/utils.py +79 -0
  231. subtitld/modules/waveform.py +53 -0
  232. subtitld-0.0.0.dev0.dist-info/METADATA +97 -0
  233. subtitld-0.0.0.dev0.dist-info/RECORD +237 -0
  234. subtitld-0.0.0.dev0.dist-info/WHEEL +5 -0
  235. subtitld-0.0.0.dev0.dist-info/entry_points.txt +2 -0
  236. subtitld-0.0.0.dev0.dist-info/licenses/LICENSE +674 -0
  237. subtitld-0.0.0.dev0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,31 @@
1
+ """History module (Ctrl+Z)
2
+
3
+ """
4
+
5
+ import copy
6
+
7
+ from subtitld.modules import session
8
+
9
+ ALL_HISTORY = []
10
+ REDO_HISTORY = []
11
+
12
+
13
+ def history_append(subtitles):
14
+ """Append subtitles list to history"""
15
+ ALL_HISTORY.append(copy.deepcopy(subtitles))
16
+ REDO_HISTORY.clear()
17
+
18
+
19
+ def history_undo():
20
+ """Revert to last subtitle on the history list"""
21
+ if ALL_HISTORY:
22
+ REDO_HISTORY.append(copy.deepcopy(session.SUBTITLE['segments']))
23
+ session.SUBTITLE['segments'].clear()
24
+ session.SUBTITLE['segments'].extend(copy.deepcopy(ALL_HISTORY.pop()))
25
+
26
+
27
+ def history_redo():
28
+ """Redo subtitle on the history list"""
29
+ if REDO_HISTORY:
30
+ session.SUBTITLE['segments'].clear()
31
+ session.SUBTITLE['segments'].extend(copy.deepcopy(REDO_HISTORY.pop()))
@@ -0,0 +1,53 @@
1
+ """Module to check subtitles quality
2
+
3
+ """
4
+
5
+ from subtitld.modules import session
6
+
7
+
8
+ def check_subtitle(subtitle=[]):
9
+ """Function to check individual subtitle"""
10
+ approved = True
11
+ reasons = []
12
+ issues = []
13
+
14
+ settings = session.CONFIG.get('quality_check', {})
15
+
16
+ if subtitle and (subtitle['end'] - subtitle['start']):
17
+ if len(subtitle['text'].replace('\n', '')) / (subtitle['end'] - subtitle['start']) > settings.get('reading_speed_cps', 21):
18
+ approved = False
19
+ reasons.append('Reading speed: {ars} characters per second. It should be {rs} per second.'.format(rs=settings.get('reading_speed_cps', 21), ars=round(len(subtitle['text'].replace('\n', '')) / (subtitle['end'] - subtitle['start']), 2)))
20
+ issues.append('cps')
21
+ if len(subtitle['text'].replace('\n', '').split(' ')) / ((subtitle['end'] - subtitle['start']) / 60) > settings.get('reading_speed_wpm', 140):
22
+ approved = False
23
+ reasons.append('Reading speed: {ars} words per minute. It should be {rs} per minute.'.format(rs=settings.get('reading_speed_wpm', 140), ars=round(len(subtitle['text'].replace('\n', '').split(' ')) / ((subtitle['end'] - subtitle['start']) / 60))))
24
+ issues.append('wpm')
25
+ if (subtitle['end'] - subtitle['start']) < settings.get('minimum_duration', .7):
26
+ approved = False
27
+ reasons.append('The duration of this subtitle, {ad}, is less than the minimum of {d}.'.format(d=settings.get('minimum_duration', .7), ad=round((subtitle['end'] - subtitle['start']), 2)))
28
+ issues.append('duration')
29
+ if (subtitle['end'] - subtitle['start']) > settings.get('maximum_duration', 7):
30
+ approved = False
31
+ reasons.append('The duration of this subtitle, {ad}, is more than the maximum of {d}.'.format(d=settings.get('maximum_duration', 7), ad=round((subtitle['end'] - subtitle['start']), 2)))
32
+ issues.append('duration')
33
+ if len(subtitle['text'].split('\n')) > settings.get('maximum_lines', 2):
34
+ approved = False
35
+ reasons.append('There are {al} lines, more than the maximum of {l}.'.format(l=settings.get('maximum_lines', 2), al=round(len(subtitle['text'].split('\n')), 2)))
36
+ issues.append('number_of_lines')
37
+ for line in subtitle['text'].split('\n'):
38
+ if len(line) > settings.get('maximum_characters_per_line', 42):
39
+ approved = False
40
+ reasons.append('There are more than {c} characters per line ({ac}).'.format(c=settings.get('maximum_characters_per_line', 42), ac=len(line)))
41
+ issues.append('cpl')
42
+ break
43
+ if len(subtitle['text'].split('\n')) > 1:
44
+ if settings.get('prefer_compact', False):
45
+ if len(subtitle['text'].replace('\n', '')) < settings.get('maximum_characters_per_line', 42):
46
+ approved = False
47
+ reasons.append('The lines should be joined as there are less than {c} characters in total.'.format(c=settings.get('maximum_characters_per_line', 42)))
48
+ if settings.get('balance_ratio_enabled', False):
49
+ if len(min(subtitle['text'].split('\n'), key=len)) < len(max(subtitle['text'].split('\n'), key=len))*(settings.get('balance_ratio', 50)/100):
50
+ approved = False
51
+ reasons.append('The shortest line length is less than {p}% the largest.'.format(p=settings.get('balance_ratio', 50)))
52
+
53
+ return approved, reasons, issues
@@ -0,0 +1,270 @@
1
+ """All path definitions for Subtitld"""
2
+
3
+ import pathlib
4
+ import sys
5
+ import tempfile
6
+ import subprocess
7
+ import subtitld
8
+ import platformdirs
9
+
10
+ PATH_SUBTITLD = pathlib.Path(subtitld.__file__).parent
11
+ PATH_HOME = pathlib.Path.home()
12
+ PATH_LOCALE = PATH_SUBTITLD / 'locale'
13
+ PATH_SUBTITLD_GRAPHICS = PATH_SUBTITLD / 'graphics'
14
+ PATH_SUBTITLD_USER_CONFIG = pathlib.Path(platformdirs.user_config_dir('subtitld'))
15
+ PATH_SUBTITLD_USER_CACHE = pathlib.Path(platformdirs.user_cache_dir('subtitld'))
16
+ FFMPEG_EXECUTABLE = 'ffmpeg'
17
+ FFPROBE_EXECUTABLE = 'ffprobe'
18
+ STARTUPINFO = None
19
+
20
+ ACTUAL_OS = 'linux'
21
+
22
+ tempdir = tempfile.TemporaryDirectory()
23
+ PATH_TEMP = tempdir.name
24
+
25
+ if sys.platform == 'darwin':
26
+ ACTUAL_OS = 'macos'
27
+ if getattr(sys, "frozen", False):
28
+ FFMPEG_EXECUTABLE = str(pathlib.Path(PATH_SUBTITLD).parent / 'ffmpeg')
29
+ FFPROBE_EXECUTABLE = str(pathlib.Path(PATH_SUBTITLD).parent / 'ffprobe')
30
+ elif sys.platform == 'win32':
31
+ ACTUAL_OS = 'windows'
32
+
33
+ if getattr(sys, "frozen", False):
34
+ FFMPEG_EXECUTABLE = pathlib.Path(PATH_SUBTITLD).parent / 'ffmpeg.exe'
35
+ FFPROBE_EXECUTABLE = pathlib.Path(PATH_SUBTITLD).parent / 'ffprobe.exe'
36
+ else:
37
+ script_dir = pathlib.Path(sys.argv[0]).parent
38
+ FFMPEG_EXECUTABLE = script_dir / 'ffmpeg.exe'
39
+ FFPROBE_EXECUTABLE = script_dir / 'ffprobe.exe'
40
+ STARTUPINFO = subprocess.STARTUPINFO()
41
+ STARTUPINFO.dwFlags |= subprocess.STARTF_USESHOWWINDOW
42
+ STARTUPINFO.wShowWindow = subprocess.SW_HIDE
43
+ import multiprocessing
44
+ multiprocessing.freeze_support()
45
+ else:
46
+ # Linux (AppImage, Snap, Flatpak, pip install). When frozen by
47
+ # PyInstaller we ship ffmpeg/ffprobe next to the main executable;
48
+ # for regular installs we fall back to whatever the distro provides.
49
+ if getattr(sys, "frozen", False):
50
+ FFMPEG_EXECUTABLE = str(pathlib.Path(PATH_SUBTITLD).parent / 'ffmpeg')
51
+ FFPROBE_EXECUTABLE = str(pathlib.Path(PATH_SUBTITLD).parent / 'ffprobe')
52
+
53
+ if not PATH_SUBTITLD_USER_CONFIG.exists():
54
+ PATH_SUBTITLD_USER_CONFIG.mkdir(parents=True)
55
+
56
+ if not PATH_SUBTITLD_USER_CACHE.exists():
57
+ PATH_SUBTITLD_USER_CACHE.mkdir(parents=True)
58
+
59
+ PATH_SUBTITLD_DATA_BACKUP = PATH_SUBTITLD_USER_CACHE / 'backup'
60
+
61
+ if not PATH_SUBTITLD_DATA_BACKUP.exists():
62
+ PATH_SUBTITLD_DATA_BACKUP.mkdir(parents=True)
63
+
64
+ PATH_SUBTITLD_DATA_MODELS = PATH_SUBTITLD_USER_CACHE / 'models'
65
+
66
+ if not PATH_SUBTITLD_DATA_MODELS.exists():
67
+ PATH_SUBTITLD_DATA_MODELS.mkdir(parents=True)
68
+
69
+ PATH_SUBTITLD_DATA_AUDIOSEPARATION = PATH_SUBTITLD_USER_CACHE / 'audioseparation'
70
+
71
+ if not PATH_SUBTITLD_DATA_AUDIOSEPARATION.exists():
72
+ PATH_SUBTITLD_DATA_AUDIOSEPARATION.mkdir(parents=True)
73
+
74
+ PATH_SUBTITLD_USER_CONFIG_FILE = PATH_SUBTITLD_USER_CONFIG / 'subtitld.config'
75
+
76
+ # VERSION_NUMBER = '20.07.0.0'
77
+ # if os.path.isfile(os.path.join(PATH_SUBTITLD, 'current_version')):
78
+ # VERSION_NUMBER = open(os.path.join(PATH_SUBTITLD, 'current_version')).read().strip()
79
+
80
+ LIST_OF_SUPPORTED_VIDEO_EXTENSIONS = {
81
+ 'MP4': {'description': 'MPEG-4 Video format', 'extensions': ['mp4']},
82
+ 'MKV': {'description': 'Matroska Video format', 'extensions': ['mkv']},
83
+ 'MOV': {'description': 'Quicktime Video format', 'extensions': ['mov']},
84
+ 'MPG': {'description': 'MPEG Video format', 'extensions': ['mpg']},
85
+ 'WEBM': {'description': 'WebM Video format', 'extensions': ['webm']},
86
+ 'OGV': {'description': 'Ogg Video format', 'extensions': ['ogv']},
87
+ 'M4V': {'description': 'MPEG-4 Video format', 'extensions': ['m4v']},
88
+ }
89
+
90
+ LIST_OF_SUPPORTED_SUBTITLE_EXTENSIONS = {
91
+ 'SRT': {'description': 'SubRip Subtitle format', 'extensions': ['srt']},
92
+ 'DFXP': {'description': 'DFXP ITT Subtitle format', 'extensions': ['dfxp', 'itt']},
93
+ 'TTML': {'description': 'TTML Subtitle format', 'extensions': ['ttml']},
94
+ 'SAMI': {'description': 'SAMI Subtitle format', 'extensions': ['smi', 'sami']},
95
+ 'SCC': {'description': 'SCC Subtitle format', 'extensions': ['scc']},
96
+ 'VTT': {'description': 'VTT Subtitle format', 'extensions': ['webvtt', 'vtt']},
97
+ 'ASS': {'description': 'SubStation Alpha Subtitle format', 'extensions': ['ass', 'ssa']},
98
+ 'SBV': {'description': 'SBV Subtitle format', 'extensions': ['sbv']},
99
+ 'SUB': {'description': 'MicroDVD Subtitle format', 'extensions': ['sub']},
100
+ 'XML': {'description': 'XML Subtitle format', 'extensions': ['xml']},
101
+ 'USF': {'description': 'Universal Subtitle Format', 'extensions': ['usf']},
102
+ 'USFX': {'description': 'Universal Subtitle Format bundled with assets', 'extensions': ['usfx']},
103
+ 'JSON': {'description': 'JSON format', 'extensions': ['json']},
104
+ }
105
+
106
+ LIST_OF_SUPPORTED_IMPORT_EXTENSIONS = {
107
+ 'TXT': {'description': 'Simple TXT file', 'extensions': ['txt']},
108
+ 'DOCX': {'description': 'Microsoft Word document (docx)', 'extensions': ['docx']},
109
+ 'SRT': {'description': 'SubRip Subtitle format', 'extensions': ['srt']}
110
+ }
111
+
112
+ LIST_OF_SUPPORTED_EXPORT_EXTENSIONS = {
113
+ 'TXT': {'description': 'Simple TXT file', 'extensions': ['txt']},
114
+ 'KDENLIVE': {'description': 'Kdenlive format', 'extensions': ['kdenlive']}
115
+ }
116
+
117
+ LIST_OF_SUPPORTED_AUDIO_EXPORT_EXTENSIONS = {
118
+ 'WAV': {'description': 'WAV audio', 'extensions': ['wav']},
119
+ 'FLAC': {'description': 'FLAC lossless audio', 'extensions': ['flac']},
120
+ 'MP3': {'description': 'MP3 audio', 'extensions': ['mp3']},
121
+ 'MP4': {'description': 'MP4 video with dubbed audio', 'extensions': ['mp4']},
122
+ }
123
+
124
+ LANGUAGE_DICT_LIST = {
125
+ 'Afrikaans (South Africa)': 'af-za',
126
+ 'Amharic (Ethiopia)': 'am-et',
127
+ 'Arabic (United Arab Emirates)': 'ar-ae',
128
+ 'Arabic (Bahrain)': 'ar-bh',
129
+ 'Arabic (Algeria)': 'ar-dz',
130
+ 'Arabic (Egypt)': 'ar-eg',
131
+ 'Arabic (Israel)': 'ar-il',
132
+ 'Arabic (Iraq)': 'ar-iq',
133
+ 'Arabic (Jordan)': 'ar-jo',
134
+ 'Arabic (Kuwait)': 'ar-kw',
135
+ 'Arabic (Lebanon)': 'ar-lb',
136
+ 'Arabic (Morocco)': 'ar-ma',
137
+ 'Arabic (Oman)': 'ar-om',
138
+ 'Arabic (State of Palestine)': 'ar-ps',
139
+ 'Arabic (Qatar)': 'ar-qa',
140
+ 'Arabic (Saudi Arabia)': 'ar-sa',
141
+ 'Arabic (Tunisia)': 'ar-tn',
142
+ 'Azerbaijani (Azerbaijan)': 'az-az',
143
+ 'Bulgarian (Bulgaria)': 'bg-bg',
144
+ 'Bengali (Bangladesh)': 'bn-bd',
145
+ 'Bengali (India)': 'bn-in',
146
+ 'Catalan (Spain)': 'ca-es',
147
+ 'Chinese, Mandarin (Simplified, China)': 'cmn-hans-cn',
148
+ 'Chinese, Mandarin (Simplified, Hong Kong)': 'cmn-hans-hk',
149
+ 'Chinese, Mandarin (Traditional, Taiwan)': 'cmn-hant-tw',
150
+ 'Czech (Czech Republic)': 'cs-cz',
151
+ 'Danish (Denmark)': 'da-dk',
152
+ 'German (Germany)': 'de-de',
153
+ 'Greek (Greece)': 'el-gr',
154
+ 'English (Australia)': 'en-au',
155
+ 'English (Canada)': 'en-ca',
156
+ 'English (United Kingdom)': 'en-gb',
157
+ 'English (Ghana)': 'en-gh',
158
+ 'English (Ireland)': 'en-ie',
159
+ 'English (India)': 'en-in',
160
+ 'English (Kenya)': 'en-ke',
161
+ 'English (Nigeria)': 'en-ng',
162
+ 'English (New Zealand)': 'en-nz',
163
+ 'English (Philippines)': 'en-ph',
164
+ 'English (Singapore)': 'en-sg',
165
+ 'English (Tanzania)': 'en-tz',
166
+ 'English (United States)': 'en-us',
167
+ 'English (South Africa)': 'en-za',
168
+ 'Spanish (Argentina)': 'es-ar',
169
+ 'Spanish (Bolivia)': 'es-bo',
170
+ 'Spanish (Chile)': 'es-cl',
171
+ 'Spanish (Colombia)': 'es-co',
172
+ 'Spanish (Costa Rica)': 'es-cr',
173
+ 'Spanish (Dominican Republic)': 'es-do',
174
+ 'Spanish (Ecuador)': 'es-ec',
175
+ 'Spanish (Spain)': 'es-es',
176
+ 'Spanish (Guatemala)': 'es-gt',
177
+ 'Spanish (Honduras)': 'es-hn',
178
+ 'Spanish (Mexico)': 'es-mx',
179
+ 'Spanish (Nicaragua)': 'es-ni',
180
+ 'Spanish (Panama)': 'es-pa',
181
+ 'Spanish (Peru)': 'es-pe',
182
+ 'Spanish (Puerto Rico)': 'es-pr',
183
+ 'Spanish (Paraguay)': 'es-py',
184
+ 'Spanish (El Salvador)': 'es-sv',
185
+ 'Spanish (United States)': 'es-us',
186
+ 'Spanish (Uruguay)': 'es-uy',
187
+ 'Spanish (Venezuela)': 'es-ve',
188
+ 'Basque (Spain)': 'eu-es',
189
+ 'Persian (Iran)': 'fa-ir',
190
+ 'Finnish (Finland)': 'fi-fi',
191
+ 'Filipino (Philippines)': 'fil-ph',
192
+ 'French (Canada)': 'fr-ca',
193
+ 'French (France)': 'fr-fr',
194
+ 'Galician (Spain)': 'gl-es',
195
+ 'Gujarati (India)': 'gu-in',
196
+ 'Hebrew (Israel)': 'he-il',
197
+ 'Hindi (India)': 'hi-in',
198
+ 'Croatian (Croatia)': 'hr-hr',
199
+ 'Hungarian (Hungary)': 'hu-hu',
200
+ 'Armenian (Armenia)': 'hy-am',
201
+ 'Indonesian (Indonesia)': 'id-id',
202
+ 'Icelandic (Iceland)': 'is-is',
203
+ 'Italian (Italy)': 'it-it',
204
+ 'Japanese (Japan)': 'ja-jp',
205
+ 'Javanese (Indonesia)': 'jv-id',
206
+ 'Georgian (Georgia)': 'ka-ge',
207
+ 'Khmer (Cambodia)': 'km-kh',
208
+ 'Kannada (India)': 'kn-in',
209
+ 'Korean (South Korea)': 'ko-kr',
210
+ 'Lao (Laos)': 'lo-la',
211
+ 'Lithuanian (Lithuania)': 'lt-lt',
212
+ 'Latvian (Latvia)': 'lv-lv',
213
+ 'Malayalam (India)': 'ml-in',
214
+ 'Marathi (India)': 'mr-in',
215
+ 'Malay (Malaysia)': 'ms-my',
216
+ 'Norwegian Bokmal (Norway)': 'nb-no',
217
+ 'Nepali (Nepal)': 'ne-np',
218
+ 'Dutch (Netherlands)': 'nl-nl',
219
+ 'Polish (Poland)': 'pl-pl',
220
+ 'Portuguese (Brazil)': 'pt-br',
221
+ 'Portuguese (Portugal)': 'pt-pt',
222
+ 'Romanian (Romania)': 'ro-ro',
223
+ 'Russian (Russia)': 'ru-ru',
224
+ 'Sinhala (Sri Lanka)': 'si-lk',
225
+ 'Slovak (Slovakia)': 'sk-sk',
226
+ 'Slovenian (Slovenia)': 'sl-si',
227
+ 'Serbian (Serbia)': 'sr-rs',
228
+ 'Sundanese (Indonesia)': 'su-id',
229
+ 'Swedish (Sweden)': 'sv-se',
230
+ 'Swahili (Kenya)': 'sw-ke',
231
+ 'Swahili (Tanzania)': 'sw-tz',
232
+ 'Tamil (India)': 'ta-in',
233
+ 'Tamil (Sri Lanka)': 'ta-lk',
234
+ 'Tamil (Malaysia)': 'ta-my',
235
+ 'Tamil (Singapore)': 'ta-sg',
236
+ 'Telugu (India)': 'te-in',
237
+ 'Thai (Thailand)': 'th-th',
238
+ 'Turkish (Turkey)': 'tr-tr',
239
+ 'Ukrainian (Ukraine)': 'uk-ua',
240
+ 'Urdu (India)': 'ur-in',
241
+ 'Urdu (Pakistan)': 'ur-pk',
242
+ 'Vietnamese (Vietnam)': 'vi-vn',
243
+ 'Chinese, Cantonese (Traditional, Hong Kong)': 'yue-hant-hk',
244
+ 'Zulu (South Africa)': 'zu-za'
245
+ }
246
+
247
+ CONFIG = {}
248
+
249
+ SUBTITLE = {
250
+ 'segments': [],
251
+ }
252
+
253
+ SPEAKERS = {}
254
+
255
+ VIDEO = {}
256
+
257
+ FORMAT = {}
258
+
259
+ REPEAT_DURATION_BUFFER = []
260
+
261
+ UNSAVED = False
262
+ _unsaved_change_callbacks = []
263
+ def set_unsaved(value=True):
264
+ global UNSAVED
265
+ old_value = UNSAVED
266
+ UNSAVED = value
267
+ if old_value != value:
268
+ for callback in _unsaved_change_callbacks:
269
+ callback()
270
+
@@ -0,0 +1,84 @@
1
+ """Shortcuts module - Robust customizable shortcut system with decorators
2
+
3
+ """
4
+
5
+ from PySide6.QtGui import QAction
6
+
7
+
8
+ class ShortcutRegistry:
9
+ """Registry for managing shortcuts and their associated actions"""
10
+
11
+ def __init__(self):
12
+ self._shortcuts = {}
13
+
14
+ def register(self, command_id, description, default_keys, handler):
15
+ """Register a shortcut with its handler"""
16
+ self._shortcuts[command_id] = {
17
+ 'description': description,
18
+ 'default_keys': default_keys,
19
+ 'handler': handler
20
+ }
21
+
22
+ def shortcut(self, command_id, description, keys):
23
+ """Decorator to register a function as a shortcut handler
24
+
25
+ Usage:
26
+ @shortcut('my_command', 'My Command Description', ['Ctrl+K'])
27
+ def my_handler(self):
28
+ # handler code
29
+ """
30
+ def decorator(func):
31
+ self.register(command_id, description, keys, func)
32
+ return func
33
+ return decorator
34
+
35
+ def get_description(self, command_id):
36
+ return self._shortcuts.get(command_id, {}).get('description', '')
37
+
38
+ def get_default_keys(self, command_id):
39
+ return self._shortcuts.get(command_id, {}).get('default_keys', [])
40
+
41
+ def get_handler(self, command_id):
42
+ return self._shortcuts.get(command_id, {}).get('handler')
43
+
44
+ def get_all_commands(self):
45
+ return list(self._shortcuts.keys())
46
+
47
+
48
+ # Global registry
49
+ _registry = ShortcutRegistry()
50
+ shortcut = _registry.shortcut
51
+
52
+ # Legacy compatibility
53
+ shortcuts_dict = {}
54
+ default_shortcuts_dict = {}
55
+
56
+
57
+ def load(self, shortcut_commands):
58
+ """Load shortcuts commands on widgets"""
59
+ # Update legacy dicts
60
+ shortcuts_dict.update({cmd: _registry.get_description(cmd) for cmd in _registry.get_all_commands()})
61
+ default_shortcuts_dict.update({cmd: _registry.get_default_keys(cmd) for cmd in _registry.get_all_commands()})
62
+
63
+ for command_id in _registry.get_all_commands():
64
+ if command_id not in shortcut_commands:
65
+ shortcut_commands[command_id] = _registry.get_default_keys(command_id)
66
+
67
+ for command_id, keys in shortcut_commands.items():
68
+ handler = _registry.get_handler(command_id)
69
+ if handler:
70
+ action = QAction(_registry.get_description(command_id), self)
71
+ action.setShortcuts(keys)
72
+ action.triggered.connect(lambda checked=False, h=handler: h(self))
73
+ self.addAction(action)
74
+
75
+
76
+ def disable_actions(self):
77
+ for action in self.actions():
78
+ action.setEnabled(False)
79
+
80
+
81
+ def enable_actions(self):
82
+ for action in self.actions():
83
+ action.setEnabled(True)
84
+