GameSentenceMiner 2.14.7__py3-none-any.whl → 2.14.9__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 (66) hide show
  1. GameSentenceMiner/config_gui.py +19 -10
  2. GameSentenceMiner/gsm.py +68 -8
  3. GameSentenceMiner/locales/en_us.json +4 -0
  4. GameSentenceMiner/locales/ja_jp.json +4 -0
  5. GameSentenceMiner/locales/zh_cn.json +4 -0
  6. GameSentenceMiner/obs.py +12 -8
  7. {gamesentenceminer-2.14.7.dist-info → gamesentenceminer-2.14.9.dist-info}/METADATA +1 -2
  8. gamesentenceminer-2.14.9.dist-info/RECORD +24 -0
  9. GameSentenceMiner/ai/__init__.py +0 -0
  10. GameSentenceMiner/ai/ai_prompting.py +0 -473
  11. GameSentenceMiner/ocr/__init__.py +0 -0
  12. GameSentenceMiner/ocr/gsm_ocr_config.py +0 -174
  13. GameSentenceMiner/ocr/ocrconfig.py +0 -129
  14. GameSentenceMiner/ocr/owocr_area_selector.py +0 -629
  15. GameSentenceMiner/ocr/owocr_helper.py +0 -638
  16. GameSentenceMiner/ocr/ss_picker.py +0 -140
  17. GameSentenceMiner/owocr/owocr/__init__.py +0 -1
  18. GameSentenceMiner/owocr/owocr/__main__.py +0 -9
  19. GameSentenceMiner/owocr/owocr/config.py +0 -148
  20. GameSentenceMiner/owocr/owocr/lens_betterproto.py +0 -1238
  21. GameSentenceMiner/owocr/owocr/ocr.py +0 -1691
  22. GameSentenceMiner/owocr/owocr/run.py +0 -1817
  23. GameSentenceMiner/owocr/owocr/screen_coordinate_picker.py +0 -109
  24. GameSentenceMiner/tools/__init__.py +0 -0
  25. GameSentenceMiner/tools/audio_offset_selector.py +0 -215
  26. GameSentenceMiner/tools/ss_selector.py +0 -135
  27. GameSentenceMiner/tools/window_transparency.py +0 -214
  28. GameSentenceMiner/util/__init__.py +0 -0
  29. GameSentenceMiner/util/communication/__init__.py +0 -22
  30. GameSentenceMiner/util/communication/send.py +0 -7
  31. GameSentenceMiner/util/communication/websocket.py +0 -94
  32. GameSentenceMiner/util/configuration.py +0 -1198
  33. GameSentenceMiner/util/db.py +0 -408
  34. GameSentenceMiner/util/downloader/Untitled_json.py +0 -472
  35. GameSentenceMiner/util/downloader/__init__.py +0 -0
  36. GameSentenceMiner/util/downloader/download_tools.py +0 -194
  37. GameSentenceMiner/util/downloader/oneocr_dl.py +0 -250
  38. GameSentenceMiner/util/electron_config.py +0 -259
  39. GameSentenceMiner/util/ffmpeg.py +0 -571
  40. GameSentenceMiner/util/get_overlay_coords.py +0 -366
  41. GameSentenceMiner/util/gsm_utils.py +0 -323
  42. GameSentenceMiner/util/model.py +0 -206
  43. GameSentenceMiner/util/notification.py +0 -147
  44. GameSentenceMiner/util/text_log.py +0 -214
  45. GameSentenceMiner/web/__init__.py +0 -0
  46. GameSentenceMiner/web/service.py +0 -132
  47. GameSentenceMiner/web/static/__init__.py +0 -0
  48. GameSentenceMiner/web/static/apple-touch-icon.png +0 -0
  49. GameSentenceMiner/web/static/favicon-96x96.png +0 -0
  50. GameSentenceMiner/web/static/favicon.ico +0 -0
  51. GameSentenceMiner/web/static/favicon.svg +0 -3
  52. GameSentenceMiner/web/static/site.webmanifest +0 -21
  53. GameSentenceMiner/web/static/style.css +0 -292
  54. GameSentenceMiner/web/static/web-app-manifest-192x192.png +0 -0
  55. GameSentenceMiner/web/static/web-app-manifest-512x512.png +0 -0
  56. GameSentenceMiner/web/templates/__init__.py +0 -0
  57. GameSentenceMiner/web/templates/index.html +0 -50
  58. GameSentenceMiner/web/templates/text_replacements.html +0 -238
  59. GameSentenceMiner/web/templates/utility.html +0 -483
  60. GameSentenceMiner/web/texthooking_page.py +0 -584
  61. GameSentenceMiner/wip/__init___.py +0 -0
  62. gamesentenceminer-2.14.7.dist-info/RECORD +0 -77
  63. {gamesentenceminer-2.14.7.dist-info → gamesentenceminer-2.14.9.dist-info}/WHEEL +0 -0
  64. {gamesentenceminer-2.14.7.dist-info → gamesentenceminer-2.14.9.dist-info}/entry_points.txt +0 -0
  65. {gamesentenceminer-2.14.7.dist-info → gamesentenceminer-2.14.9.dist-info}/licenses/LICENSE +0 -0
  66. {gamesentenceminer-2.14.7.dist-info → gamesentenceminer-2.14.9.dist-info}/top_level.txt +0 -0
@@ -1,472 +0,0 @@
1
- scenes="""{
2
- "DesktopAudioDevice1": {
3
- "prev_ver": 520093697,
4
- "name": "Desktop Audio",
5
- "uuid": "8587cf13-6937-4e51-a1df-ed1ebb87d537",
6
- "id": "wasapi_output_capture",
7
- "versioned_id": "wasapi_output_capture",
8
- "settings": {
9
- "device_id": "default"
10
- },
11
- "mixers": 255,
12
- "sync": 0,
13
- "flags": 0,
14
- "volume": 1.0,
15
- "balance": 0.5,
16
- "enabled": true,
17
- "muted": true,
18
- "push-to-mute": false,
19
- "push-to-mute-delay": 0,
20
- "push-to-talk": false,
21
- "push-to-talk-delay": 0,
22
- "hotkeys": {
23
- "libobs.mute": [],
24
- "libobs.unmute": [],
25
- "libobs.push-to-mute": [],
26
- "libobs.push-to-talk": []
27
- },
28
- "deinterlace_mode": 0,
29
- "deinterlace_field_order": 0,
30
- "monitoring_type": 0,
31
- "private_settings": {}
32
- },
33
- "AuxAudioDevice1": {
34
- "prev_ver": 520093697,
35
- "name": "Mic/Aux",
36
- "uuid": "cbadac0a-b67a-46c9-9ff5-e649bff42549",
37
- "id": "wasapi_input_capture",
38
- "versioned_id": "wasapi_input_capture",
39
- "settings": {
40
- "device_id": "default"
41
- },
42
- "mixers": 255,
43
- "sync": 0,
44
- "flags": 0,
45
- "volume": 1.0,
46
- "balance": 0.5,
47
- "enabled": true,
48
- "muted": true,
49
- "push-to-mute": false,
50
- "push-to-mute-delay": 0,
51
- "push-to-talk": false,
52
- "push-to-talk-delay": 0,
53
- "hotkeys": {
54
- "libobs.mute": [],
55
- "libobs.unmute": [],
56
- "libobs.push-to-mute": [],
57
- "libobs.push-to-talk": []
58
- },
59
- "deinterlace_mode": 0,
60
- "deinterlace_field_order": 0,
61
- "monitoring_type": 0,
62
- "private_settings": {}
63
- },
64
- "current_scene": "Yuzu",
65
- "current_program_scene": "Yuzu",
66
- "scene_order": [
67
- {
68
- "name": "Example Game Capture"
69
- },
70
- {
71
- "name": "Example Window Capture"
72
- },
73
- {
74
- "name": "Yuzu"
75
- }
76
- ],
77
- "name": "Untitled",
78
- "sources": [
79
- {
80
- "prev_ver": 520093697,
81
- "name": "Game Capture",
82
- "uuid": "3060072f-58ed-4c34-8bdc-a1e66507e99f",
83
- "id": "game_capture",
84
- "versioned_id": "game_capture",
85
- "settings": {
86
- "capture_audio": true
87
- },
88
- "mixers": 255,
89
- "sync": 0,
90
- "flags": 0,
91
- "volume": 1.0,
92
- "balance": 0.5,
93
- "enabled": true,
94
- "muted": false,
95
- "push-to-mute": false,
96
- "push-to-mute-delay": 0,
97
- "push-to-talk": false,
98
- "push-to-talk-delay": 0,
99
- "hotkeys": {
100
- "libobs.mute": [],
101
- "libobs.unmute": [],
102
- "libobs.push-to-mute": [],
103
- "libobs.push-to-talk": [],
104
- "hotkey_start": [],
105
- "hotkey_stop": []
106
- },
107
- "deinterlace_mode": 0,
108
- "deinterlace_field_order": 0,
109
- "monitoring_type": 0,
110
- "private_settings": {}
111
- },
112
- {
113
- "prev_ver": 520093697,
114
- "name": "Example Game Capture",
115
- "uuid": "13da3321-7d49-4a97-b4c5-b1f0912c6440",
116
- "id": "scene",
117
- "versioned_id": "scene",
118
- "settings": {
119
- "id_counter": 1,
120
- "custom_size": false,
121
- "items": [
122
- {
123
- "name": "Game Capture",
124
- "source_uuid": "3060072f-58ed-4c34-8bdc-a1e66507e99f",
125
- "visible": true,
126
- "locked": false,
127
- "rot": 0.0,
128
- "scale_ref": {
129
- "x": 1920.0,
130
- "y": 1080.0
131
- },
132
- "align": 5,
133
- "bounds_type": 0,
134
- "bounds_align": 0,
135
- "bounds_crop": false,
136
- "crop_left": 0,
137
- "crop_top": 0,
138
- "crop_right": 0,
139
- "crop_bottom": 0,
140
- "id": 1,
141
- "group_item_backup": false,
142
- "pos": {
143
- "x": 0.0,
144
- "y": 0.0
145
- },
146
- "pos_rel": {
147
- "x": -1.7777777910232544,
148
- "y": -1.0
149
- },
150
- "scale": {
151
- "x": 1.0,
152
- "y": 1.0
153
- },
154
- "scale_rel": {
155
- "x": 1.0,
156
- "y": 1.0
157
- },
158
- "bounds": {
159
- "x": 0.0,
160
- "y": 0.0
161
- },
162
- "bounds_rel": {
163
- "x": 0.0,
164
- "y": 0.0
165
- },
166
- "scale_filter": "disable",
167
- "blend_method": "default",
168
- "blend_type": "normal",
169
- "show_transition": {
170
- "duration": 0
171
- },
172
- "hide_transition": {
173
- "duration": 0
174
- },
175
- "private_settings": {}
176
- }
177
- ]
178
- },
179
- "mixers": 0,
180
- "sync": 0,
181
- "flags": 0,
182
- "volume": 1.0,
183
- "balance": 0.5,
184
- "enabled": true,
185
- "muted": false,
186
- "push-to-mute": false,
187
- "push-to-mute-delay": 0,
188
- "push-to-talk": false,
189
- "push-to-talk-delay": 0,
190
- "hotkeys": {
191
- "OBSBasic.SelectScene": [],
192
- "libobs.show_scene_item.1": [],
193
- "libobs.hide_scene_item.1": []
194
- },
195
- "deinterlace_mode": 0,
196
- "deinterlace_field_order": 0,
197
- "monitoring_type": 0,
198
- "private_settings": {}
199
- },
200
- {
201
- "prev_ver": 520093697,
202
- "name": "Example Window Capture",
203
- "uuid": "313ace86-d326-4bc4-bb70-69a64cd3b995",
204
- "id": "scene",
205
- "versioned_id": "scene",
206
- "settings": {
207
- "id_counter": 2,
208
- "custom_size": false,
209
- "items": [
210
- {
211
- "name": "Window Capture",
212
- "source_uuid": "35e6ccb1-1559-4f0a-a26f-f3d4faa4acb4",
213
- "visible": true,
214
- "locked": false,
215
- "rot": 0.0,
216
- "scale_ref": {
217
- "x": 1920.0,
218
- "y": 1080.0
219
- },
220
- "align": 5,
221
- "bounds_type": 0,
222
- "bounds_align": 0,
223
- "bounds_crop": false,
224
- "crop_left": 0,
225
- "crop_top": 0,
226
- "crop_right": 0,
227
- "crop_bottom": 0,
228
- "id": 2,
229
- "group_item_backup": false,
230
- "pos": {
231
- "x": 0.0,
232
- "y": 0.0
233
- },
234
- "pos_rel": {
235
- "x": -1.7777777910232544,
236
- "y": -1.0
237
- },
238
- "scale": {
239
- "x": 1.0,
240
- "y": 1.0
241
- },
242
- "scale_rel": {
243
- "x": 1.0,
244
- "y": 1.0
245
- },
246
- "bounds": {
247
- "x": 0.0,
248
- "y": 0.0
249
- },
250
- "bounds_rel": {
251
- "x": 0.0,
252
- "y": 0.0
253
- },
254
- "scale_filter": "disable",
255
- "blend_method": "default",
256
- "blend_type": "normal",
257
- "show_transition": {
258
- "duration": 0
259
- },
260
- "hide_transition": {
261
- "duration": 0
262
- },
263
- "private_settings": {}
264
- }
265
- ]
266
- },
267
- "mixers": 0,
268
- "sync": 0,
269
- "flags": 0,
270
- "volume": 1.0,
271
- "balance": 0.5,
272
- "enabled": true,
273
- "muted": false,
274
- "push-to-mute": false,
275
- "push-to-mute-delay": 0,
276
- "push-to-talk": false,
277
- "push-to-talk-delay": 0,
278
- "hotkeys": {
279
- "OBSBasic.SelectScene": [],
280
- "libobs.show_scene_item.2": [],
281
- "libobs.hide_scene_item.2": []
282
- },
283
- "deinterlace_mode": 0,
284
- "deinterlace_field_order": 0,
285
- "monitoring_type": 0,
286
- "private_settings": {}
287
- },
288
- {
289
- "prev_ver": 520093697,
290
- "name": "Yuzu",
291
- "uuid": "68d18b0a-7b81-4dd6-8a29-5bd882f9b8d8",
292
- "id": "scene",
293
- "versioned_id": "scene",
294
- "settings": {
295
- "id_counter": 2,
296
- "custom_size": false,
297
- "items": [
298
- {
299
- "name": "Window Capture",
300
- "source_uuid": "35e6ccb1-1559-4f0a-a26f-f3d4faa4acb4",
301
- "visible": true,
302
- "locked": false,
303
- "rot": 0.0,
304
- "scale_ref": {
305
- "x": 1920.0,
306
- "y": 1080.0
307
- },
308
- "align": 5,
309
- "bounds_type": 0,
310
- "bounds_align": 0,
311
- "bounds_crop": false,
312
- "crop_left": 0,
313
- "crop_top": 0,
314
- "crop_right": 0,
315
- "crop_bottom": 0,
316
- "id": 2,
317
- "group_item_backup": false,
318
- "pos": {
319
- "x": 0.0,
320
- "y": 0.0
321
- },
322
- "pos_rel": {
323
- "x": -1.7777777910232544,
324
- "y": -1.0
325
- },
326
- "scale": {
327
- "x": 1.0,
328
- "y": 1.0
329
- },
330
- "scale_rel": {
331
- "x": 1.0,
332
- "y": 1.0
333
- },
334
- "bounds": {
335
- "x": 0.0,
336
- "y": 0.0
337
- },
338
- "bounds_rel": {
339
- "x": 0.0,
340
- "y": 0.0
341
- },
342
- "scale_filter": "disable",
343
- "blend_method": "default",
344
- "blend_type": "normal",
345
- "show_transition": {
346
- "duration": 0
347
- },
348
- "hide_transition": {
349
- "duration": 0
350
- },
351
- "private_settings": {}
352
- }
353
- ]
354
- },
355
- "mixers": 0,
356
- "sync": 0,
357
- "flags": 0,
358
- "volume": 1.0,
359
- "balance": 0.5,
360
- "enabled": true,
361
- "muted": false,
362
- "push-to-mute": false,
363
- "push-to-mute-delay": 0,
364
- "push-to-talk": false,
365
- "push-to-talk-delay": 0,
366
- "hotkeys": {
367
- "OBSBasic.SelectScene": [],
368
- "libobs.show_scene_item.2": [],
369
- "libobs.hide_scene_item.2": []
370
- },
371
- "deinterlace_mode": 0,
372
- "deinterlace_field_order": 0,
373
- "monitoring_type": 0,
374
- "private_settings": {}
375
- },
376
- {
377
- "prev_ver": 520093697,
378
- "name": "Window Capture",
379
- "uuid": "35e6ccb1-1559-4f0a-a26f-f3d4faa4acb4",
380
- "id": "window_capture",
381
- "versioned_id": "window_capture",
382
- "settings": {
383
- "capture_audio": true
384
- },
385
- "mixers": 255,
386
- "sync": 0,
387
- "flags": 0,
388
- "volume": 1.0,
389
- "balance": 0.5,
390
- "enabled": true,
391
- "muted": false,
392
- "push-to-mute": false,
393
- "push-to-mute-delay": 0,
394
- "push-to-talk": false,
395
- "push-to-talk-delay": 0,
396
- "hotkeys": {
397
- "libobs.mute": [],
398
- "libobs.unmute": [],
399
- "libobs.push-to-mute": [],
400
- "libobs.push-to-talk": []
401
- },
402
- "deinterlace_mode": 0,
403
- "deinterlace_field_order": 0,
404
- "monitoring_type": 0,
405
- "private_settings": {}
406
- }
407
- ],
408
- "groups": [],
409
- "quick_transitions": [
410
- {
411
- "name": "Cut",
412
- "duration": 300,
413
- "hotkeys": [],
414
- "id": 1,
415
- "fade_to_black": false
416
- },
417
- {
418
- "name": "Fade",
419
- "duration": 300,
420
- "hotkeys": [],
421
- "id": 2,
422
- "fade_to_black": false
423
- },
424
- {
425
- "name": "Fade",
426
- "duration": 300,
427
- "hotkeys": [],
428
- "id": 3,
429
- "fade_to_black": true
430
- }
431
- ],
432
- "transitions": [],
433
- "saved_projectors": [],
434
- "current_transition": "Fade",
435
- "transition_duration": 300,
436
- "preview_locked": false,
437
- "scaling_enabled": false,
438
- "scaling_level": 0,
439
- "scaling_off_x": 0.0,
440
- "scaling_off_y": 0.0,
441
- "virtual-camera": {
442
- "type2": 3
443
- },
444
- "modules": {
445
- "scripts-tool": [],
446
- "output-timer": {
447
- "streamTimerHours": 0,
448
- "streamTimerMinutes": 0,
449
- "streamTimerSeconds": 30,
450
- "recordTimerHours": 0,
451
- "recordTimerMinutes": 0,
452
- "recordTimerSeconds": 30,
453
- "autoStartStreamTimer": false,
454
- "autoStartRecordTimer": false,
455
- "pauseRecordTimer": true
456
- },
457
- "auto-scene-switcher": {
458
- "interval": 300,
459
- "non_matching_scene": "",
460
- "switch_if_not_matching": false,
461
- "active": false,
462
- "switches": []
463
- },
464
- "captions": {
465
- "source": "",
466
- "enabled": false,
467
- "lang_id": 1033,
468
- "provider": "mssapi"
469
- }
470
- },
471
- "version": 2
472
- }"""
File without changes
@@ -1,194 +0,0 @@
1
- import json
2
- import os
3
- import secrets
4
- import shutil
5
- import urllib.request
6
- import platform
7
- import zipfile
8
-
9
- from GameSentenceMiner.util.downloader.Untitled_json import scenes
10
- from GameSentenceMiner.util.configuration import get_app_directory, logger
11
- from GameSentenceMiner.util.ffmpeg import get_ffmpeg_path, get_ffprobe_path
12
- from GameSentenceMiner.obs import get_obs_path
13
-
14
- script_dir = os.path.dirname(os.path.abspath(__file__))
15
-
16
- def copy_obs_settings(src, dest):
17
-
18
- if os.path.exists(src):
19
- user_input = input(f"Existng OBS install located. Do you want to copy OBS settings from {src} to {dest}? (y/n): ").strip().lower() or "y"
20
- if user_input in ['y', 'yes', '1']:
21
- logger.info(f"Copying OBS settings from {src} to {dest}...")
22
- shutil.copytree(src, dest, dirs_exist_ok=True)
23
- logger.info("OBS settings copied successfully.")
24
- return True
25
- else:
26
- logger.info("Not copying settings!")
27
- return False
28
- logger.warning(f"OBS settings directory {src} does not exist. Skipping copy.")
29
- return False
30
-
31
-
32
- def download_obs_if_needed():
33
- obs_path = os.path.join(get_app_directory(), 'obs-studio')
34
- obs_exe_path = get_obs_path()
35
- if os.path.exists(obs_path) and os.path.exists(obs_exe_path):
36
- logger.debug(f"OBS already installed at {obs_path}.")
37
- return
38
-
39
- if os.path.exists(obs_path) and not os.path.exists(obs_exe_path):
40
- logger.info("OBS directory exists but executable is missing. Re-downloading OBS...")
41
- shutil.rmtree(obs_path)
42
-
43
- def get_windows_obs_url():
44
- machine = platform.machine().lower()
45
- if machine in ['arm64', 'aarch64']:
46
- return next(asset['browser_download_url'] for asset in latest_release['assets'] if
47
- asset['name'].endswith('Windows-arm64.zip'))
48
- return next(asset['browser_download_url'] for asset in latest_release['assets'] if
49
- asset['name'].endswith('Windows-x64.zip'))
50
-
51
- latest_release_url = "https://api.github.com/repos/obsproject/obs-studio/releases/latest"
52
- with urllib.request.urlopen(latest_release_url) as response:
53
- latest_release = json.load(response)
54
- obs_url = {
55
- "Windows": get_windows_obs_url(),
56
- "Linux": next(asset['browser_download_url'] for asset in latest_release['assets'] if
57
- asset['name'].endswith('Ubuntu-24.04-x86_64.deb')),
58
- "Darwin": next(asset['browser_download_url'] for asset in latest_release['assets'] if
59
- asset['name'].endswith('macOS-Intel.dmg'))
60
- }.get(platform.system(), None)
61
-
62
- if obs_url is None:
63
- logger.error("Unsupported OS. Please install OBS manually.")
64
- return
65
-
66
- download_dir = os.path.join(get_app_directory(), "downloads")
67
- os.makedirs(download_dir, exist_ok=True)
68
- obs_installer = os.path.join(download_dir, "OBS.zip")
69
-
70
- logger.info(f"Downloading OBS from {obs_url}...")
71
- urllib.request.urlretrieve(obs_url, obs_installer)
72
-
73
- os.makedirs(obs_path, exist_ok=True)
74
-
75
- if platform.system() == "Windows":
76
-
77
-
78
- logger.info(f"OBS downloaded. Extracting to {obs_path}...")
79
- with zipfile.ZipFile(obs_installer, 'r') as zip_ref:
80
- zip_ref.extractall(obs_path)
81
- open(os.path.join(obs_path, "portable_mode"), 'a').close()
82
- # websocket_config_path = os.path.join(obs_path, 'config', 'obs-studio')
83
- # if not copy_obs_settings(os.path.join(os.getenv('APPDATA'), 'obs-studio'), websocket_config_path):
84
- websocket_config_path = os.path.join(obs_path, 'config', 'obs-studio', 'plugin_config', 'obs-websocket')
85
- os.makedirs(websocket_config_path, exist_ok=True)
86
-
87
- websocket_config = {
88
- "alerts_enabled": False,
89
- "auth_required": False,
90
- "first_load": False,
91
- "server_enabled": True,
92
- "server_password": secrets.token_urlsafe(16),
93
- "server_port": 7274
94
- }
95
- with open(os.path.join(websocket_config_path, 'config.json'), 'w') as config_file:
96
- json.dump(websocket_config, config_file, indent=4)
97
- basic_ini_path = os.path.join(obs_path, 'config', 'obs-studio', 'basic', 'profiles', 'Untitled')
98
- os.makedirs(basic_ini_path, exist_ok=True)
99
- with open(os.path.join(basic_ini_path, 'basic.ini'), 'w') as basic_ini_file:
100
- basic_ini_file.write(
101
- "[SimpleOutput]\n"
102
- f"FilePath={os.path.expanduser('~')}/Videos/GSM\n"
103
- "RecRB=true\n"
104
- "RecRBTime=60\n"
105
- "RecRBSize=512\n"
106
- "RecRBPrefix=GSM\n"
107
- "RecAudioEncoder=opus\n"
108
- )
109
- scene_json_path = os.path.join(obs_path, 'config', 'obs-studio', 'basic', 'scenes')
110
- os.makedirs(scene_json_path, exist_ok=True)
111
- with open(os.path.join(scene_json_path, 'Untitled.json'), 'w') as scene_file:
112
- scene_file.write(scenes)
113
- logger.info(f"OBS extracted to {obs_path}.")
114
- else:
115
- logger.error(f"Please install OBS manually from {obs_installer}")
116
-
117
- def download_ffmpeg_if_needed():
118
- ffmpeg_dir = os.path.join(get_app_directory(), 'ffmpeg')
119
- ffmpeg_exe_path = get_ffmpeg_path()
120
- ffprobe_exe_path = get_ffprobe_path()
121
-
122
- if os.path.exists(ffmpeg_dir) and os.path.exists(ffmpeg_exe_path) and os.path.exists(ffprobe_exe_path):
123
- logger.debug(f"FFmpeg already installed at {ffmpeg_dir}.")
124
- return
125
-
126
- if os.path.exists(ffmpeg_dir) and (not os.path.exists(ffmpeg_exe_path) or not os.path.exists(ffprobe_exe_path)):
127
- logger.info("FFmpeg directory exists but executables are missing. Re-downloading FFmpeg...")
128
- shutil.rmtree(ffmpeg_dir)
129
-
130
- ffmpeg_url = {
131
- "Windows": "https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip",
132
- "Linux": "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz",
133
- "Darwin": "https://evermeet.cx/ffmpeg/ffmpeg.zip"
134
- }.get(platform.system(), None)
135
-
136
- if ffmpeg_url is None:
137
- logger.error("Unsupported OS. Please install FFmpeg manually.")
138
- return
139
-
140
- download_dir = os.path.join(get_app_directory(), "downloads")
141
- os.makedirs(download_dir, exist_ok=True)
142
- ffmpeg_archive = os.path.join(download_dir, "ffmpeg.zip")
143
-
144
- logger.info(f"Downloading FFmpeg from {ffmpeg_url}...")
145
- urllib.request.urlretrieve(ffmpeg_url, ffmpeg_archive)
146
- logger.info(f"FFmpeg downloaded. Extracting to {ffmpeg_dir}...")
147
-
148
- os.makedirs(ffmpeg_dir, exist_ok=True)
149
-
150
- with zipfile.ZipFile(ffmpeg_archive, 'r') as zip_ref:
151
- for member in zip_ref.namelist():
152
- filename = os.path.basename(member)
153
- if filename: # Skip directories
154
- source = zip_ref.open(member)
155
- target = open(os.path.join(ffmpeg_dir, filename), "wb")
156
- with source, target:
157
- shutil.copyfileobj(source, target)
158
- logger.info(f"FFmpeg extracted to {ffmpeg_dir}.")
159
-
160
- def download_ocenaudio_if_needed():
161
- ocenaudio_dir = os.path.join(get_app_directory(), 'ocenaudio')
162
- ocenaudio_exe_path = os.path.join(ocenaudio_dir, 'ocenaudio.exe')
163
- if os.path.exists(ocenaudio_dir) and os.path.exists(ocenaudio_exe_path):
164
- logger.info(f"Ocenaudio already installed at {ocenaudio_dir}.")
165
- return ocenaudio_exe_path
166
-
167
- if os.path.exists(ocenaudio_dir) and not os.path.exists(ocenaudio_exe_path):
168
- logger.info("Ocenaudio directory exists but executable is missing. Re-downloading Ocenaudio...")
169
- shutil.rmtree(ocenaudio_dir)
170
-
171
- ocenaudio_url = "https://www.ocenaudio.com/downloads/ocenaudio_windows64.zip"
172
-
173
- download_dir = os.path.join(get_app_directory(), "downloads")
174
- os.makedirs(download_dir, exist_ok=True)
175
- ocenaudio_archive = os.path.join(download_dir, "ocenaudio.zip")
176
-
177
- logger.info(f"Downloading Ocenaudio from {ocenaudio_url}...")
178
- urllib.request.urlretrieve(ocenaudio_url, ocenaudio_archive)
179
- logger.info(f"Ocenaudio downloaded. Extracting to {ocenaudio_dir}...")
180
-
181
- os.makedirs(ocenaudio_dir, exist_ok=True)
182
- with zipfile.ZipFile(ocenaudio_archive, 'r') as zip_ref:
183
- zip_ref.extractall(get_app_directory())
184
-
185
- logger.info(f"Ocenaudio extracted to {ocenaudio_dir}.")
186
- return ocenaudio_exe_path
187
-
188
- def main():
189
- download_obs_if_needed()
190
- download_ffmpeg_if_needed()
191
- download_ocenaudio_if_needed()
192
-
193
- if __name__ == "__main__":
194
- main()