GameSentenceMiner 2.1.2.post1__py3-none-any.whl → 2.2.0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: GameSentenceMiner
3
- Version: 2.1.2.post1
3
+ Version: 2.2.0
4
4
  Summary: A tool for mining sentences from games.
5
5
  Author-email: Beangate <bpwhelan95@gmail.com>
6
6
  License: MIT License
@@ -12,7 +12,6 @@ Classifier: Operating System :: OS Independent
12
12
  Requires-Python: >=3.11
13
13
  Description-Content-Type: text/markdown
14
14
  Requires-Dist: requests~=2.32.3
15
- Requires-Dist: anki~=24.6.3
16
15
  Requires-Dist: watchdog~=5.0.2
17
16
  Requires-Dist: DateTime~=5.5
18
17
  Requires-Dist: pyperclip~=1.9.0
@@ -25,14 +24,11 @@ Requires-Dist: obs-websocket-py~=1.0
25
24
  Requires-Dist: plyer~=2.1.0
26
25
  Requires-Dist: keyboard~=0.13.5
27
26
  Requires-Dist: websockets~=13.0.1
28
- Requires-Dist: obsws_python~=1.7.0
29
- Requires-Dist: numpy~=2.0.2
30
27
  Requires-Dist: stable-ts~=2.17.5
31
- Requires-Dist: openai-whisper
32
28
  Requires-Dist: silero-vad~=5.1.2
33
29
  Requires-Dist: ttkbootstrap~=1.10.1
34
30
  Requires-Dist: dataclasses_json~=0.6.7
35
- Requires-Dist: pyinstaller
31
+ Requires-Dist: numpy
36
32
  Requires-Dist: pystray
37
33
  Requires-Dist: pywin32
38
34
 
@@ -0,0 +1,24 @@
1
+ src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ src/anki.py,sha256=wf1_iUVHrEnzNtK2uL8FJBtAwihiwO_WkmgvqLExf5Q,9089
3
+ src/config_gui.py,sha256=oY397FO5WYHluPNOtfed3Eakw3TMpVStCaoEU60jw00,48963
4
+ src/configuration.py,sha256=QVVe8_Pkiyxahgbabf0dpBeY1oIktypvOzBvlwyLEhI,14035
5
+ src/ffmpeg.py,sha256=9WtP_ajm-nGWPRbuPMJAdnybsKyuAq8Uc_npK4NqGJE,10633
6
+ src/gametext.py,sha256=3HN1imfcmecfGstqDjfKBZJL02tJfrZsZBTphXLVGh8,4010
7
+ src/gsm.py,sha256=ip4NuMHwAgK_lC9-Y1fUGXYj_SAf-laNPY_nSsmLRYQ,16246
8
+ src/model.py,sha256=oh8VVT8T1UKekbmP6MGNgQ8jIuQ_7Rg4GPzDCn2kJo8,1999
9
+ src/notification.py,sha256=sWgIIXhaB9WV1K_oQGf5-IR6q3dakae_QS-RuIvbcEs,1939
10
+ src/obs.py,sha256=6XIsIRntr63cdpfNS2CanUWr3KyMHoQ8PxfKLZzSkVY,6495
11
+ src/package_updater.py,sha256=Yel-KWBHr5kgIJpHM1A1w5tcx_gDqrLrK0pqXRhinlI,1472
12
+ src/util.py,sha256=eTMD5oqsDwem5C7GUG6-x3AQ884a1WLaJ1VVJgeHmA4,4491
13
+ src/downloader/Untitled_json.py,sha256=RUUl2bbbCpUDUUS0fP0tdvf5FngZ7ILdA_J5TFYAXUQ,15272
14
+ src/downloader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ src/downloader/download_tools.py,sha256=m1UV8EvWJdNn2cz11BCUI2mth46RhbVdVHXYYC318V8,6378
16
+ src/vad/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ src/vad/silero_trim.py,sha256=rcHzSNjAm_liiKBWsdywpIC1oUrM00I7kxmomXCQ-Io,1521
18
+ src/vad/vosk_helper.py,sha256=4oaI7uesINu1sO7PA0-M4qSOmiEneRRN4Ae8ztmYCBE,5798
19
+ src/vad/whisper_helper.py,sha256=N8-FZMIjLb5CiFeyY8pz050v7RguU39B6tnvsPTbSmc,3383
20
+ GameSentenceMiner-2.2.0.dist-info/METADATA,sha256=LZH1a7NVyGPQTuHhed4yTGLtYV0K2nw6OV2epwDRa2Q,13408
21
+ GameSentenceMiner-2.2.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
22
+ GameSentenceMiner-2.2.0.dist-info/entry_points.txt,sha256=hzWrryQzGBdqbVqzUIBbVZvvh7MBTUYvWiIs95QrfHE,51
23
+ GameSentenceMiner-2.2.0.dist-info/top_level.txt,sha256=74rtVfumQlgAPzR5_2CgYN24MB0XARCg0t-gzk6gTrM,4
24
+ GameSentenceMiner-2.2.0.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ gamesentenceminer = src.gsm:main
@@ -0,0 +1 @@
1
+ src
@@ -6,15 +6,12 @@ import urllib.request
6
6
 
7
7
  import requests as req
8
8
 
9
- from . import util
10
- from . import ffmpeg
11
- from . import notification
12
- from . import obs
13
-
14
- from .configuration import *
15
- from .configuration import get_config
16
- from .gametext import get_last_two_sentences
17
- from .obs import get_current_game
9
+ from src import obs, util, notification, ffmpeg
10
+
11
+ from src.configuration import *
12
+ from src.configuration import get_config
13
+ from src.gametext import get_last_two_sentences
14
+ from src.obs import get_current_game
18
15
 
19
16
  audio_in_anki = None
20
17
  screenshot_in_anki = None
@@ -3,10 +3,9 @@ from tkinter import filedialog, messagebox, simpledialog
3
3
 
4
4
  import ttkbootstrap as ttk
5
5
 
6
- from .package_updater import check_for_updates, get_latest_version, update, get_current_version
7
- from . import configuration
8
- from . import obs
9
- from .configuration import *
6
+ from src.package_updater import check_for_updates, get_latest_version, update, get_current_version
7
+ from src import obs, configuration
8
+ from src.configuration import *
10
9
 
11
10
  settings_saved = False
12
11
  on_save = []
@@ -46,9 +46,9 @@ class General:
46
46
  @dataclass_json
47
47
  @dataclass
48
48
  class Paths:
49
- folder_to_watch: str = expanduser("~/Videos/OBS")
50
- audio_destination: str = expanduser("~/Videos/OBS/Audio/")
51
- screenshot_destination: str = expanduser("~/Videos/OBS/SS/")
49
+ folder_to_watch: str = expanduser("~/Videos/GSM")
50
+ audio_destination: str = expanduser("~/Videos/GSM/Audio/")
51
+ screenshot_destination: str = expanduser("~/Videos/GSM/SS/")
52
52
  remove_video: bool = True
53
53
  remove_audio: bool = False
54
54
  remove_screenshot: bool = False
@@ -369,7 +369,7 @@ console_handler = logging.StreamHandler()
369
369
  console_handler.setLevel(logging.INFO)
370
370
 
371
371
  # Create rotating file handler with level DEBUG
372
- file_handler = RotatingFileHandler(get_log_path(), maxBytes=10_000_000, backupCount=2, encoding='utf-8')
372
+ file_handler = RotatingFileHandler(get_log_path(), maxBytes=10 * 1024 * 1024, backupCount=0, encoding='utf-8')
373
373
  file_handler.setLevel(logging.DEBUG)
374
374
 
375
375
  # Create a formatter
@@ -0,0 +1,472 @@
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
+ }"""
@@ -0,0 +1,149 @@
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 src.downloader.Untitled_json import scenes
10
+ from src.configuration import get_app_directory, logger
11
+
12
+ script_dir = os.path.dirname(os.path.abspath(__file__))
13
+
14
+ def copy_obs_settings(src, dest):
15
+
16
+ if os.path.exists(src):
17
+ 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"
18
+ if user_input in ['y', 'yes', '1']:
19
+ logger.info(f"Copying OBS settings from {src} to {dest}...")
20
+ shutil.copytree(src, dest, dirs_exist_ok=True)
21
+ logger.info("OBS settings copied successfully.")
22
+ return True
23
+ else:
24
+ logger.info("Not copying settings!")
25
+ return False
26
+ logger.warning(f"OBS settings directory {src} does not exist. Skipping copy.")
27
+ return False
28
+
29
+
30
+ def download_obs_if_needed():
31
+ obs_path = os.path.join(get_app_directory(), 'obs-studio')
32
+ if os.path.exists(obs_path):
33
+ logger.debug(f"OBS already installed at {obs_path}.")
34
+ return
35
+
36
+ os.makedirs(obs_path, exist_ok=True)
37
+ latest_release_url = "https://api.github.com/repos/obsproject/obs-studio/releases/latest"
38
+ with urllib.request.urlopen(latest_release_url) as response:
39
+ latest_release = json.load(response)
40
+ obs_url = {
41
+ "Windows": next(asset['browser_download_url'] for asset in latest_release['assets'] if
42
+ asset['name'].endswith('Windows.zip')),
43
+ "Linux": next(asset['browser_download_url'] for asset in latest_release['assets'] if
44
+ asset['name'].endswith('Ubuntu-24.04-x86_64.deb')),
45
+ "Darwin": next(asset['browser_download_url'] for asset in latest_release['assets'] if
46
+ asset['name'].endswith('macOS-Intel.dmg'))
47
+ }.get(platform.system(), None)
48
+
49
+ if obs_url is None:
50
+ logger.error("Unsupported OS. Please install OBS manually.")
51
+ return
52
+
53
+ download_dir = os.path.join(get_app_directory(), "downloads")
54
+ os.makedirs(download_dir, exist_ok=True)
55
+ obs_installer = os.path.join(download_dir, "OBS.zip")
56
+
57
+ if os.path.exists(obs_installer):
58
+ logger.debug("OBS installer already exists. Skipping download.")
59
+ else:
60
+ logger.info(f"Downloading OBS from {obs_url}...")
61
+ urllib.request.urlretrieve(obs_url, obs_installer)
62
+
63
+ if platform.system() == "Windows":
64
+
65
+
66
+ logger.info(f"OBS downloaded. Extracting to {obs_path}...")
67
+ with zipfile.ZipFile(obs_installer, 'r') as zip_ref:
68
+ zip_ref.extractall(obs_path)
69
+ open(os.path.join(obs_path, "portable_mode"), 'a').close()
70
+ websocket_config_path = os.path.join(obs_path, 'config', 'obs-studio')
71
+ if not copy_obs_settings(os.path.join(os.getenv('APPDATA'), 'obs-studio'), websocket_config_path):
72
+ websocket_config_path = os.path.join(obs_path, 'config', 'obs-studio', 'plugin_config', 'obs-websocket')
73
+ os.makedirs(websocket_config_path, exist_ok=True)
74
+
75
+ websocket_config = {
76
+ "alerts_enabled": False,
77
+ "auth_required": False,
78
+ "first_load": False,
79
+ "server_enabled": True,
80
+ "server_password": secrets.token_urlsafe(16),
81
+ "server_port": 7274
82
+ }
83
+ with open(os.path.join(websocket_config_path, 'config.json'), 'w') as config_file:
84
+ json.dump(websocket_config, config_file, indent=4)
85
+ basic_ini_path = os.path.join(obs_path, 'config', 'obs-studio', 'basic', 'profiles', 'Untitled')
86
+ os.makedirs(basic_ini_path, exist_ok=True)
87
+ with open(os.path.join(basic_ini_path, 'basic.ini'), 'w') as basic_ini_file:
88
+ basic_ini_file.write(
89
+ "[SimpleOutput]\n"
90
+ f"FilePath={os.path.expanduser('~')}/Videos/GSM\n"
91
+ "RecRB=true\n"
92
+ "RecRBTime=60\n"
93
+ "RecRBSize=512\n"
94
+ "RecRBPrefix=GSM\n"
95
+ "RecAudioEncoder=opus\n"
96
+ )
97
+ scene_json_path = os.path.join(obs_path, 'config', 'obs-studio', 'basic', 'scenes')
98
+ os.makedirs(scene_json_path, exist_ok=True)
99
+ with open(os.path.join(scene_json_path, 'Untitled.json'), 'w') as scene_file:
100
+ scene_file.write(scenes)
101
+ logger.info(f"OBS extracted to {obs_path}.")
102
+ else:
103
+ logger.error(f"Please install OBS manually from {obs_installer}")
104
+
105
+ def download_ffmpeg_if_needed():
106
+ ffmpeg_path = os.path.join(get_app_directory(), 'ffmpeg')
107
+
108
+ if os.path.exists(ffmpeg_path):
109
+ logger.debug(f"FFmpeg already installed at {ffmpeg_path}.")
110
+ return
111
+
112
+ os.makedirs(ffmpeg_path, exist_ok=True)
113
+
114
+ ffmpeg_url = {
115
+ "Windows": "https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip",
116
+ "Linux": "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz",
117
+ "Darwin": "https://evermeet.cx/ffmpeg/ffmpeg.zip"
118
+ }.get(platform.system(), None)
119
+
120
+ if ffmpeg_url is None:
121
+ logger.error("Unsupported OS. Please install FFmpeg manually.")
122
+ return
123
+
124
+ download_dir = os.path.join(get_app_directory(), "downloads")
125
+ os.makedirs(download_dir, exist_ok=True)
126
+ ffmpeg_archive = os.path.join(download_dir, "ffmpeg.zip")
127
+
128
+ if os.path.exists(ffmpeg_archive):
129
+ logger.debug("FFmpeg archive already exists. Skipping download.")
130
+ else:
131
+ logger.info(f"Downloading FFmpeg from {ffmpeg_url}...")
132
+ urllib.request.urlretrieve(ffmpeg_url, ffmpeg_archive)
133
+ logger.info(f"FFmpeg downloaded. Extracting to {ffmpeg_path}...")
134
+ with zipfile.ZipFile(ffmpeg_archive, 'r') as zip_ref:
135
+ for member in zip_ref.namelist():
136
+ filename = os.path.basename(member)
137
+ if filename: # Skip directories
138
+ source = zip_ref.open(member)
139
+ target = open(os.path.join(ffmpeg_path, filename), "wb")
140
+ with source, target:
141
+ shutil.copyfileobj(source, target)
142
+ logger.info(f"FFmpeg extracted to {ffmpeg_path}.")
143
+ def main():
144
+ # Run dependency checks
145
+ download_obs_if_needed()
146
+ download_ffmpeg_if_needed()
147
+
148
+ if __name__ == "__main__":
149
+ main()
@@ -1,19 +1,21 @@
1
+ import subprocess
1
2
  import tempfile
2
3
  import time
3
4
 
4
- from . import obs
5
- from . import util
6
- from . import configuration
7
- from .configuration import *
8
- from .util import *
5
+ from src import obs, util, configuration
6
+ from src.configuration import *
7
+ from src.util import *
9
8
 
10
- ffmpeg_base_command_list = ["ffmpeg", "-hide_banner", "-loglevel", "error", '-nostdin']
9
+ def get_ffmpeg_path():
10
+ return os.path.join(get_app_directory(), "ffmpeg", "ffmpeg.exe") if util.is_windows() else "ffmpeg"
11
+
12
+ ffmpeg_base_command_list = [get_ffmpeg_path(), "-hide_banner", "-loglevel", "error", '-nostdin']
11
13
 
12
14
 
13
15
  def get_screenshot(video_file, time_from_end):
14
16
  time_from_end_to_capture = -time_from_end if time_from_end else -1
15
- output_image = make_unique_file_name(
16
- get_config().paths.screenshot_destination + obs.get_current_game(sanitize=True) + f".{get_config().screenshot.extension}")
17
+ output_image = make_unique_file_name(os.path.join(
18
+ get_config().paths.screenshot_destination, f"{obs.get_current_game(sanitize=True)}.{get_config().screenshot.extension}"))
17
19
  # FFmpeg command to extract the last frame of the video
18
20
  ffmpeg_command = ffmpeg_base_command_list + [
19
21
  "-sseof", f"{time_from_end_to_capture}", # Seek to 1 second before the end of the video
@@ -59,7 +61,7 @@ def get_screenshot_time(video_path, line_time):
59
61
 
60
62
  def process_image(image_file):
61
63
  output_image = make_unique_file_name(
62
- get_config().paths.screenshot_destination + obs.get_current_game(sanitize=True) + f".{get_config().screenshot.extension}")
64
+ os.path.join(get_config().paths.screenshot_destination, f"{obs.get_current_game(sanitize=True)}.{get_config().screenshot.extension}"))
63
65
 
64
66
  # FFmpeg command to process the input image
65
67
  ffmpeg_command = ffmpeg_base_command_list + [
@@ -112,7 +114,7 @@ def get_audio_codec(video_path):
112
114
 
113
115
  def get_audio_and_trim(video_path, line_time, next_line_time):
114
116
  supported_formats = {
115
- 'opus': 'opus',
117
+ 'opus': 'libopus',
116
118
  'mp3': 'libmp3lame',
117
119
  'ogg': 'libvorbis',
118
120
  'aac': 'aac',
@@ -139,7 +141,7 @@ def get_audio_and_trim(video_path, line_time, next_line_time):
139
141
 
140
142
  # FFmpeg command to extract OR re-encode the audio
141
143
  # command = f"{ffmpeg_base_command} -i \"{video_path}\" -map 0:a {codec_command} \"{untrimmed_audio}\""
142
-
144
+ logger.debug("Doing initial audio extraction")
143
145
  logger.debug(" ".join(command))
144
146
 
145
147
  subprocess.run(command)
@@ -295,3 +297,4 @@ def is_video_big_enough(file_path, min_size_kb=250):
295
297
  except Exception as e:
296
298
  logger.error(f"Error: {e}")
297
299
  return False
300
+
@@ -7,10 +7,10 @@ from datetime import datetime
7
7
  import pyperclip
8
8
  import websockets
9
9
 
10
- from . import util
11
- from .configuration import *
12
- from .configuration import get_config, logger
13
- from .util import remove_html_tags
10
+ from src import util
11
+ from src.configuration import *
12
+ from src.configuration import get_config, logger
13
+ from src.util import remove_html_tags
14
14
  from difflib import SequenceMatcher
15
15
 
16
16
 
@@ -1,8 +1,8 @@
1
- import shutil
2
1
  import signal
2
+ import subprocess
3
3
  import sys
4
- import tempfile
5
4
  import time
5
+ from subprocess import Popen
6
6
 
7
7
  import keyboard
8
8
  import psutil
@@ -12,21 +12,23 @@ from pystray import Icon, Menu, MenuItem
12
12
  from watchdog.events import FileSystemEventHandler
13
13
  from watchdog.observers import Observer
14
14
 
15
- from . import anki
16
- from . import config_gui
17
- from . import configuration
18
- from . import ffmpeg
19
- from . import gametext
20
- from . import notification
21
- from . import obs
22
- from . import util
23
- from .vad import vosk_helper, silero_trim, whisper_helper
24
- from .configuration import *
25
- from .ffmpeg import get_audio_and_trim
26
- from .gametext import get_line_timing
27
- from .util import *
28
-
29
- config_pids = []
15
+ from src import anki
16
+ from src import config_gui
17
+ from src import configuration
18
+ from src import ffmpeg
19
+ from src import gametext
20
+ from src import notification
21
+ from src import obs
22
+ from src import util
23
+ from src.downloader.download_tools import download_obs_if_needed, download_ffmpeg_if_needed
24
+ from src.vad import vosk_helper, silero_trim, whisper_helper
25
+ from src.configuration import *
26
+ from src.ffmpeg import get_audio_and_trim
27
+ from src.gametext import get_line_timing
28
+ from src.util import *
29
+
30
+ obs_process: Popen
31
+ procs_to_close = []
30
32
  settings_window: config_gui.ConfigApp = None
31
33
  obs_paused = False
32
34
  icon: Icon
@@ -35,7 +37,7 @@ menu: Menu
35
37
 
36
38
  class VideoToAudioHandler(FileSystemEventHandler):
37
39
  def on_created(self, event):
38
- if event.is_directory or "Replay" not in event.src_path:
40
+ if event.is_directory or ("Replay" not in event.src_path and "GSM" not in event.src_path):
39
41
  return
40
42
  if event.src_path.endswith(".mkv") or event.src_path.endswith(".mp4"): # Adjust based on your OBS output format
41
43
  logger.info(f"MKV {event.src_path} FOUND, RUNNING LOGIC")
@@ -46,14 +48,19 @@ class VideoToAudioHandler(FileSystemEventHandler):
46
48
  def convert_to_audio(video_path):
47
49
  try:
48
50
  with util.lock:
51
+ if os.path.exists(video_path) and os.access(video_path, os.R_OK):
52
+ logger.debug(f"Video found and is readable: {video_path}")
53
+
49
54
  if get_config().obs.minimum_replay_size and not ffmpeg.is_video_big_enough(video_path,
50
55
  get_config().obs.minimum_replay_size):
56
+ logger.debug("Checking if video is big enough")
51
57
  notification.send_check_obs_notification(reason="Video may be empty, check scene in OBS.")
52
58
  logger.error(
53
59
  f"Video was unusually small, potentially empty! Check OBS for Correct Scene Settings! Path: {video_path}")
54
60
  return
55
61
  util.use_previous_audio = True
56
62
  last_note = None
63
+ logger.debug("Attempting to get last anki card")
57
64
  if get_config().anki.update_anki:
58
65
  last_note = anki.get_last_anki_card()
59
66
  if get_config().features.backfill_audio:
@@ -70,6 +77,7 @@ class VideoToAudioHandler(FileSystemEventHandler):
70
77
  tango = last_note['fields'][get_config().anki.word_field]['value'] if last_note else ''
71
78
 
72
79
  if get_config().anki.sentence_audio_field:
80
+ logger.debug("Attempting to get audio from video")
73
81
  final_audio_output, should_update_audio, vad_trimmed_audio = VideoToAudioHandler.get_audio(
74
82
  line_time,
75
83
  next_line_time,
@@ -95,7 +103,7 @@ class VideoToAudioHandler(FileSystemEventHandler):
95
103
  print(f)
96
104
  print("Something went wrong with processing, anki card not updated")
97
105
  except Exception as e:
98
- logger.error(f"Some error was hit catching to allow further work to be done: {e}")
106
+ logger.error(f"Some error was hit catching to allow further work to be done: {e}", exc_info=1)
99
107
  if get_config().paths.remove_video and os.path.exists(video_path):
100
108
  os.remove(video_path) # Optionally remove the video after conversion
101
109
  if get_config().paths.remove_audio and os.path.exists(vad_trimmed_audio):
@@ -106,8 +114,7 @@ class VideoToAudioHandler(FileSystemEventHandler):
106
114
  trimmed_audio = get_audio_and_trim(video_path, line_time, next_line_time)
107
115
  vad_trimmed_audio = make_unique_file_name(
108
116
  f"{os.path.abspath(configuration.get_temporary_directory())}/{obs.get_current_game(sanitize=True)}.{get_config().audio.extension}")
109
- final_audio_output = make_unique_file_name(
110
- f"{get_config().paths.audio_destination}{obs.get_current_game(sanitize=True)}.{get_config().audio.extension}")
117
+ final_audio_output = make_unique_file_name(os.path.join(get_config().paths.audio_destination, f"{obs.get_current_game(sanitize=True)}.{get_config().audio.extension}"))
111
118
  should_update_audio = True
112
119
  if get_config().vad.do_vad_postprocessing:
113
120
  match get_config().vad.selected_vad_model:
@@ -139,26 +146,33 @@ class VideoToAudioHandler(FileSystemEventHandler):
139
146
 
140
147
 
141
148
  def initialize(reloading=False):
149
+ global obs_process
142
150
  if not reloading:
151
+ if is_windows():
152
+ download_obs_if_needed()
153
+ download_ffmpeg_if_needed()
143
154
  if get_config().obs.enabled:
155
+ obs_process = obs.start_obs()
144
156
  obs.connect_to_obs(start_replay=True)
145
157
  anki.start_monitoring_anki()
146
- if get_config().general.open_config_on_startup:
147
- proc = subprocess.Popen([sys.executable, "config_gui.py"])
148
- config_pids.append(proc.pid)
149
158
  gametext.start_text_monitor()
150
- if not os.path.exists(get_config().paths.folder_to_watch):
151
- os.mkdir(get_config().paths.folder_to_watch)
152
- if not os.path.exists(get_config().paths.screenshot_destination):
153
- os.mkdir(get_config().paths.screenshot_destination)
154
- if not os.path.exists(get_config().paths.audio_destination):
155
- os.mkdir(get_config().paths.audio_destination)
159
+ os.makedirs(get_config().paths.folder_to_watch, exist_ok=True)
160
+ os.makedirs(get_config().paths.screenshot_destination, exist_ok=True)
161
+ os.makedirs(get_config().paths.audio_destination, exist_ok=True)
156
162
  if get_config().vad.do_vad_postprocessing:
157
163
  if VOSK in (get_config().vad.backup_vad_model, get_config().vad.selected_vad_model):
158
164
  vosk_helper.get_vosk_model()
159
165
  if WHISPER in (get_config().vad.backup_vad_model, get_config().vad.selected_vad_model):
160
166
  whisper_helper.initialize_whisper_model()
161
167
 
168
+ def initial_checks():
169
+ try:
170
+ subprocess.run(ffmpeg.ffmpeg_base_command_list)
171
+ logger.debug("FFMPEG is installed and accessible.")
172
+ except FileNotFoundError:
173
+ logger.error("FFmpeg not found, please install it and add it to your PATH.")
174
+ raise
175
+
162
176
 
163
177
  def register_hotkeys():
164
178
  keyboard.add_hotkey(get_config().hotkeys.reset_line, gametext.reset_line_hotkey_pressed)
@@ -216,7 +230,7 @@ def open_settings():
216
230
  def open_log():
217
231
  """Function to handle opening log."""
218
232
  """Open log file with the default application."""
219
- log_file_path = "../../gamesentenceminer.log"
233
+ log_file_path = get_log_path()
220
234
  if not os.path.exists(log_file_path):
221
235
  print("Log file not found!")
222
236
  return
@@ -241,17 +255,9 @@ def exit_program(icon, item):
241
255
 
242
256
  def play_pause(icon, item):
243
257
  global obs_paused, menu
244
- if obs_paused:
245
- obs.start_replay_buffer()
246
- else:
247
- obs.stop_replay_buffer()
248
-
249
- obs_paused = not obs_paused
258
+ obs.toggle_replay_buffer()
250
259
  update_icon()
251
260
 
252
- def get_obs_icon_text():
253
- return "Pause OBS" if obs_paused else "Resume OBS"
254
-
255
261
 
256
262
  def update_icon():
257
263
  global menu, icon
@@ -264,7 +270,8 @@ def update_icon():
264
270
  menu = Menu(
265
271
  MenuItem("Open Settings", open_settings),
266
272
  MenuItem("Open Log", open_log),
267
- MenuItem(get_obs_icon_text(), play_pause),
273
+ MenuItem("Toggle Replay Buffer", play_pause),
274
+ MenuItem("Restart OBS", restart_obs),
268
275
  MenuItem("Switch Profile", profile_menu),
269
276
  MenuItem("Exit", exit_program)
270
277
  )
@@ -295,7 +302,8 @@ def run_tray():
295
302
  menu = Menu(
296
303
  MenuItem("Open Settings", open_settings),
297
304
  MenuItem("Open Log", open_log),
298
- MenuItem(get_obs_icon_text(), play_pause),
305
+ MenuItem("Toggle Replay Buffer", play_pause),
306
+ MenuItem("Restart OBS", restart_obs),
299
307
  MenuItem("Switch Profile", profile_menu),
300
308
  MenuItem("Exit", exit_program)
301
309
  )
@@ -303,24 +311,43 @@ def run_tray():
303
311
  icon = Icon("TrayApp", create_image(), "Game Sentence Miner", menu)
304
312
  icon.run()
305
313
 
314
+ def close_obs():
315
+ if obs_process:
316
+ logger.info("Closing OBS")
317
+ obs_process.terminate()
318
+ obs_process.wait()
319
+
320
+ def restart_obs():
321
+ global obs_process
322
+ close_obs()
323
+ time.sleep(2)
324
+ obs_process = obs.start_obs()
325
+ obs.connect_to_obs(start_replay=True)
306
326
 
307
327
  def cleanup():
308
328
  logger.info("Performing cleanup...")
309
329
  util.keep_running = False
310
330
 
311
- for pid in config_pids:
331
+ if get_config().obs.enabled:
332
+ if get_config().obs.start_buffer:
333
+ obs.stop_replay_buffer()
334
+ obs.disconnect_from_obs()
335
+ close_obs()
336
+
337
+ proc: Popen
338
+ for proc in procs_to_close:
312
339
  try:
313
- p = psutil.Process(pid)
314
- p.terminate() # Gracefully terminate the process
340
+ logger.info(f"Terminating process {proc.args[0]}")
341
+ proc.terminate()
342
+ proc.wait() # Wait for OBS to fully close
343
+ logger.info(f"Process {proc.args[0]} terminated.")
315
344
  except psutil.NoSuchProcess:
316
- logger.info("Config process already closed.")
345
+ logger.info("PID already closed.")
317
346
  except Exception as e:
318
- logger.error(f"Error terminating process {pid}: {e}")
347
+ proc.kill()
348
+ logger.error(f"Error terminating process {proc}: {e}")
349
+
319
350
 
320
- if get_config().obs.enabled:
321
- if get_config().obs.start_buffer:
322
- obs.stop_replay_buffer()
323
- obs.disconnect_from_obs()
324
351
  settings_window.window.destroy()
325
352
  logger.info("Cleanup complete.")
326
353
 
@@ -340,6 +367,7 @@ def main(reloading=False, do_config_input=True):
340
367
  global settings_window
341
368
  logger.info("Script started.")
342
369
  initialize(reloading)
370
+ initial_checks()
343
371
  event_handler = VideoToAudioHandler()
344
372
  observer = Observer()
345
373
  observer.schedule(event_handler, get_config().paths.folder_to_watch, recursive=False)
@@ -360,6 +388,8 @@ def main(reloading=False, do_config_input=True):
360
388
  settings_window = config_gui.ConfigApp()
361
389
  if get_config().general.check_for_update_on_startup:
362
390
  settings_window.window.after(0, settings_window.check_update)
391
+ if get_config().general.open_config_on_startup:
392
+ settings_window.window.after(0, settings_window.show)
363
393
  settings_window.add_save_hook(update_icon)
364
394
  settings_window.window.mainloop()
365
395
  except KeyboardInterrupt:
@@ -1,18 +1,37 @@
1
+ import subprocess
1
2
  import time
2
- from sys import platform
3
3
 
4
4
  from obswebsocket import obsws, requests
5
5
 
6
- from . import util
7
- from . import configuration
8
- from .configuration import *
9
- from .model import *
6
+ from src import util, configuration
7
+ from src.configuration import *
8
+ from src.model import *
10
9
 
11
10
  client: obsws = None
12
11
 
13
12
  # REFERENCE: https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md
14
13
 
15
14
 
15
+ def get_obs_path():
16
+ return os.path.join(configuration.get_app_directory(), 'obs-studio/bin/64bit/obs64.exe')
17
+
18
+ def start_obs():
19
+ obs_path = get_obs_path()
20
+ if not os.path.exists(obs_path):
21
+ logger.error(f"OBS not found at {obs_path}. Please install OBS.")
22
+ return None
23
+
24
+ try:
25
+ # process = subprocess.Popen([obs_path], cwd=os.path.dirname(obs_path))
26
+ # process = subprocess.Popen([obs_path, '--minimize-to-tray'], cwd=os.path.dirname(obs_path))
27
+ process = subprocess.Popen([obs_path, '--disable-shutdown-check'], cwd=os.path.dirname(obs_path))
28
+ logger.info("OBS launched")
29
+ return process
30
+ except Exception as e:
31
+ logger.error(f"Error launching OBS: {e}")
32
+ return None
33
+
34
+
16
35
  def get_obs_websocket_config_values():
17
36
  if platform == "win32":
18
37
  config_path = os.path.expanduser(r"~\AppData\Roaming\obs-studio\plugin_config\obs-websocket\config.json")
@@ -89,6 +108,14 @@ def disconnect_from_obs():
89
108
  logger.info("Disconnected from OBS WebSocket.")
90
109
 
91
110
 
111
+ def toggle_replay_buffer():
112
+ try:
113
+ client.call(requests.ToggleReplayBuffer())
114
+ print("Replay buffer Toggled.")
115
+ except Exception as e:
116
+ print(f"Error toggling buffer: {e}")
117
+
118
+
92
119
  # Start replay buffer
93
120
  def start_replay_buffer():
94
121
  try:
@@ -110,7 +137,12 @@ def stop_replay_buffer():
110
137
  # Save the current replay buffer
111
138
  def save_replay_buffer():
112
139
  try:
113
- client.call(requests.SaveReplayBuffer())
140
+ replay_buffer_started = client.call(requests.GetReplayBufferStatus()).datain['outputActive']
141
+ if replay_buffer_started:
142
+ client.call(requests.SaveReplayBuffer())
143
+ logger.info("Replay buffer saved.")
144
+ else:
145
+ logger.error("Replay Buffer is not active, could not save Replay Buffer!")
114
146
  except Exception as e:
115
147
  print(f"Error saving replay buffer: {e}")
116
148
 
@@ -138,7 +170,8 @@ def get_source_from_scene(scene_name):
138
170
 
139
171
  def get_screenshot():
140
172
  try:
141
- screenshot = util.make_unique_file_name(os.path.abspath(configuration.get_temporary_directory()) + '/screenshot.png')
173
+ screenshot = util.make_unique_file_name(os.path.abspath(
174
+ configuration.get_temporary_directory()) + '/screenshot.png')
142
175
  update_current_game()
143
176
  current_source = get_source_from_scene(get_current_game())
144
177
  current_source_name = current_source.sourceName
@@ -5,7 +5,7 @@ import sys
5
5
  import pyperclip
6
6
  import requests
7
7
 
8
- from .configuration import logger, get_app_directory
8
+ from src.configuration import logger, get_app_directory
9
9
 
10
10
  PACKAGE_NAME = "GameSentenceMiner"
11
11
  VERSION_FILE_PATH = os.path.join(get_app_directory(), 'version.txt')
@@ -123,6 +123,9 @@ def run_agent_and_hook(pname, agent_script):
123
123
  def is_linux():
124
124
  return platform == 'linux'
125
125
 
126
+ def is_windows():
127
+ return platform == 'win32'
128
+
126
129
  # def run_command(command, shell=False, input=None, capture_output=False, timeout=None, check=False, **kwargs):
127
130
  # # Use shell=True if the OS is Linux, otherwise shell=False
128
131
  # if is_linux():
src/vad/__init__.py ADDED
File without changes
@@ -2,8 +2,8 @@ import tempfile
2
2
 
3
3
  from silero_vad import load_silero_vad, read_audio, get_speech_timestamps
4
4
 
5
- from .. import configuration, ffmpeg
6
- from ..configuration import *
5
+ from src import configuration, ffmpeg
6
+ from src.configuration import *
7
7
 
8
8
  # Silero VAD setup
9
9
  vad_model = load_silero_vad()
@@ -7,8 +7,8 @@ import requests
7
7
  import soundfile as sf
8
8
  import vosk
9
9
 
10
- from .. import ffmpeg, configuration
11
- from ..configuration import *
10
+ from src import configuration, ffmpeg
11
+ from src.configuration import *
12
12
 
13
13
  ffmpeg_base_command_list = ["ffmpeg", "-hide_banner", "-loglevel", "error"]
14
14
  vosk.SetLogLevel(-1)
@@ -4,8 +4,8 @@ import warnings
4
4
  import stable_whisper as whisper
5
5
  from stable_whisper import WhisperResult
6
6
 
7
- from .. import ffmpeg, configuration
8
- from ..configuration import *
7
+ from src import configuration, ffmpeg
8
+ from src.configuration import *
9
9
 
10
10
  ffmpeg_base_command_list = ["ffmpeg", "-hide_banner", "-loglevel", "error"]
11
11
  whisper_model = None
@@ -1,21 +0,0 @@
1
- GameSentenceMiner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- GameSentenceMiner/anki.py,sha256=3UT6K5PxzJMDoiXyOULrkeCoJ0KMq7JvBw6XhcLCirE,9114
3
- GameSentenceMiner/config_gui.py,sha256=R16wJtFxPcqIixnKmxy3iIlpEIqFJwKmxXS7AoZVO0Y,48968
4
- GameSentenceMiner/configuration.py,sha256=CSg67qIzEdj_w-dS-NEls9syyTeJD3rfPrwSZLomFcU,14029
5
- GameSentenceMiner/ffmpeg.py,sha256=hdKimzkpAKsE-17qEAQg4uHy4-TtdFywYx48Skn9cPs,10418
6
- GameSentenceMiner/gametext.py,sha256=GpR9P8h3GmmKH46Dw13kJPx66n3jGjFCiV8Fcrqn9E8,3999
7
- GameSentenceMiner/gsm.py,sha256=GqMNcb8w117clJfFiNLhDbZ8eOFQTyVhejrjHvsBJXo,15072
8
- GameSentenceMiner/model.py,sha256=oh8VVT8T1UKekbmP6MGNgQ8jIuQ_7Rg4GPzDCn2kJo8,1999
9
- GameSentenceMiner/notification.py,sha256=sWgIIXhaB9WV1K_oQGf5-IR6q3dakae_QS-RuIvbcEs,1939
10
- GameSentenceMiner/obs.py,sha256=gutnRk30jIxuvrpEosR9jw2h_tll36wgtAZkUF-vWDY,5256
11
- GameSentenceMiner/package_updater.py,sha256=aexojWH6JcDt01ZcxZN5bHdt_TFxWgPKC4w-Pvjp_dQ,1469
12
- GameSentenceMiner/util.py,sha256=OYg0j_rT9F7v3aJRwWnHvdWMYyxGlimrvw7U2C9ifeY,4441
13
- GameSentenceMiner/vad/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- GameSentenceMiner/vad/silero_trim.py,sha256=r7bZYEj-NUXGKgD2UIhLrbTPyq0rau97qGtrMZcRK4A,1517
15
- GameSentenceMiner/vad/vosk_helper.py,sha256=lWmlGMhmg_0QoWeCHrXwz9wDKPqY37BckHCekGVtJUI,5794
16
- GameSentenceMiner/vad/whisper_helper.py,sha256=9kmPeSs6jRcKSVxYY-vtyTcqVUDORR4q1nl8fqxHHn4,3379
17
- GameSentenceMiner-2.1.2.post1.dist-info/METADATA,sha256=w3DyH8RZX7bSR3VmuPNz9zCyCLIGsLWL0WuiilXIHVU,13541
18
- GameSentenceMiner-2.1.2.post1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
19
- GameSentenceMiner-2.1.2.post1.dist-info/entry_points.txt,sha256=2APEP25DbfjSxGeHtwBstMH8mulVhLkqF_b9bqzU6vQ,65
20
- GameSentenceMiner-2.1.2.post1.dist-info/top_level.txt,sha256=V1hUY6xVSyUEohb0uDoN4UIE6rUZ_JYx8yMyPGX4PgQ,18
21
- GameSentenceMiner-2.1.2.post1.dist-info/RECORD,,
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- gamesentenceminer = GameSentenceMiner.gsm:main
@@ -1 +0,0 @@
1
- GameSentenceMiner
File without changes
File without changes
File without changes
File without changes