GameSentenceMiner 2.13.1__tar.gz → 2.13.2.post1__tar.gz

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 (79) hide show
  1. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/obs.py +4 -0
  2. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/ocr/owocr_area_selector.py +32 -5
  3. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/owocr/owocr/ocr.py +16 -31
  4. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/owocr/owocr/run.py +44 -4
  5. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/util/configuration.py +1 -1
  6. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/util/notification.py +7 -0
  7. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/wip/get_overlay_coords.py +2 -2
  8. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner.egg-info/PKG-INFO +1 -1
  9. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/PKG-INFO +1 -1
  10. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/pyproject.toml +1 -1
  11. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/__init__.py +0 -0
  12. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/ai/__init__.py +0 -0
  13. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/ai/ai_prompting.py +0 -0
  14. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/anki.py +0 -0
  15. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/assets/__init__.py +0 -0
  16. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/assets/icon.png +0 -0
  17. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/assets/icon128.png +0 -0
  18. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/assets/icon256.png +0 -0
  19. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/assets/icon32.png +0 -0
  20. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/assets/icon512.png +0 -0
  21. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/assets/icon64.png +0 -0
  22. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/assets/pickaxe.png +0 -0
  23. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/config_gui.py +0 -0
  24. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/gametext.py +0 -0
  25. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/gsm.py +0 -0
  26. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/locales/en_us.json +0 -0
  27. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/locales/ja_jp.json +0 -0
  28. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/locales/zh_cn.json +0 -0
  29. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/ocr/__init__.py +0 -0
  30. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/ocr/gsm_ocr_config.py +0 -0
  31. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/ocr/ocrconfig.py +0 -0
  32. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/ocr/owocr_helper.py +0 -0
  33. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/ocr/ss_picker.py +0 -0
  34. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/owocr/owocr/__init__.py +0 -0
  35. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/owocr/owocr/__main__.py +0 -0
  36. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/owocr/owocr/config.py +0 -0
  37. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/owocr/owocr/lens_betterproto.py +0 -0
  38. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/owocr/owocr/screen_coordinate_picker.py +0 -0
  39. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/util/__init__.py +0 -0
  40. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/util/audio_offset_selector.py +0 -0
  41. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/util/communication/__init__.py +0 -0
  42. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/util/communication/send.py +0 -0
  43. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/util/communication/websocket.py +0 -0
  44. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/util/downloader/Untitled_json.py +0 -0
  45. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/util/downloader/__init__.py +0 -0
  46. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/util/downloader/download_tools.py +0 -0
  47. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/util/downloader/oneocr_dl.py +0 -0
  48. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/util/electron_config.py +0 -0
  49. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/util/ffmpeg.py +0 -0
  50. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/util/gsm_utils.py +0 -0
  51. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/util/model.py +0 -0
  52. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/util/package.py +0 -0
  53. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/util/ss_selector.py +0 -0
  54. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/util/text_log.py +0 -0
  55. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/util/window_transparency.py +0 -0
  56. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/vad.py +0 -0
  57. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/web/__init__.py +0 -0
  58. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/web/service.py +0 -0
  59. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/web/static/__init__.py +0 -0
  60. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/web/static/apple-touch-icon.png +0 -0
  61. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/web/static/favicon-96x96.png +0 -0
  62. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/web/static/favicon.ico +0 -0
  63. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/web/static/favicon.svg +0 -0
  64. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/web/static/site.webmanifest +0 -0
  65. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/web/static/style.css +0 -0
  66. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/web/static/web-app-manifest-192x192.png +0 -0
  67. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/web/static/web-app-manifest-512x512.png +0 -0
  68. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/web/templates/__init__.py +0 -0
  69. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/web/templates/index.html +0 -0
  70. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/web/templates/text_replacements.html +0 -0
  71. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/web/templates/utility.html +0 -0
  72. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner/web/texthooking_page.py +0 -0
  73. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner.egg-info/SOURCES.txt +0 -0
  74. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner.egg-info/dependency_links.txt +0 -0
  75. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner.egg-info/entry_points.txt +0 -0
  76. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner.egg-info/requires.txt +0 -0
  77. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/GameSentenceMiner.egg-info/top_level.txt +0 -0
  78. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/LICENSE +0 -0
  79. {gamesentenceminer-2.13.1 → gamesentenceminer-2.13.2.post1}/setup.cfg +0 -0
@@ -468,6 +468,10 @@ if __name__ == '__main__':
468
468
  logging.basicConfig(level=logging.INFO)
469
469
  # main()
470
470
  connect_to_obs_sync()
471
+
472
+ while True:
473
+ print(get_active_source())
474
+ time.sleep(3)
471
475
  # i = 100
472
476
  # for i in range(1, 100):
473
477
  # print(f"Getting screenshot {i}")
@@ -55,15 +55,13 @@ class ScreenSelector:
55
55
 
56
56
  if self.use_obs_screenshot:
57
57
  print("Using OBS screenshot as target.")
58
- screenshot_base64 = obs.get_screenshot_base64(compression=75)
58
+ self.screenshot_img = obs.get_screenshot_PIL(compression=75)
59
59
  # print(screenshot_base64)
60
- if not screenshot_base64:
60
+ if not self.screenshot_img:
61
61
  raise RuntimeError("Failed to get OBS screenshot.")
62
62
  try:
63
- img_data = base64.b64decode(screenshot_base64)
64
- self.screenshot_img = Image.open(io.BytesIO(img_data))
65
63
  # Scale image to 1280x720
66
- self.screenshot_img = self.screenshot_img.resize((1280, 720), Image.LANCZOS)
64
+ self.screenshot_img = self.screenshot_img.resize(self.scale_down_width_height(self.screenshot_img.width, self.screenshot_img.height), Image.LANCZOS)
67
65
  except Exception as e:
68
66
  raise RuntimeError(f"Failed to decode or open OBS screenshot: {e}")
69
67
 
@@ -104,6 +102,35 @@ class ScreenSelector:
104
102
  self.instructions_window_id = None
105
103
 
106
104
  self.load_existing_rectangles()
105
+
106
+ def scale_down_width_height(self, width, height):
107
+ if width == 0 or height == 0:
108
+ return self.width, self.height
109
+ aspect_ratio = width / height
110
+ if aspect_ratio > 2.66:
111
+ # Ultra-wide (32:9) - use 1920x540
112
+ return 1920, 540
113
+ elif aspect_ratio > 2.33:
114
+ # 21:9 - use 1920x800
115
+ return 1920, 800
116
+ elif aspect_ratio > 1.77:
117
+ # 16:9 - use 1280x720
118
+ return 1280, 720
119
+ elif aspect_ratio > 1.6:
120
+ # 16:10 - use 1280x800
121
+ return 1280, 800
122
+ elif aspect_ratio > 1.33:
123
+ # 4:3 - use 960x720
124
+ return 960, 720
125
+ elif aspect_ratio > 1.25:
126
+ # 5:4 - use 900x720
127
+ return 900, 720
128
+ elif aspect_ratio > 1.5:
129
+ # 3:2 - use 1080x720
130
+ return 1080, 720
131
+ else:
132
+ # Default/fallback - use 1280x720
133
+ return 1280, 720
107
134
 
108
135
  def _find_target_window(self):
109
136
  try:
@@ -344,7 +344,6 @@ class GoogleLens:
344
344
  text = response_dict['objects_response']['text']
345
345
  skipped = []
346
346
  previous_line = None
347
- lines = []
348
347
  if 'text_layout' in text:
349
348
  for paragraph in text['text_layout']['paragraphs']:
350
349
  if previous_line:
@@ -360,38 +359,21 @@ class GoogleLens:
360
359
  if vertical_space > avg_height * 2:
361
360
  res += 'BLANK_LINE'
362
361
  for line in paragraph['lines']:
363
- # Build a list of word boxes for this line
364
- words_info = []
365
- for word in line['words']:
366
- word_info = {
367
- "word": word['plain_text'],
368
- "x1": int(word['geometry']['bounding_box']['center_x'] * img.width - (word['geometry']['bounding_box']['width'] * img.width) / 2),
369
- "y1": int(word['geometry']['bounding_box']['center_y'] * img.height - (word['geometry']['bounding_box']['height'] * img.height) / 2),
370
- "x2": int(word['geometry']['bounding_box']['center_x'] * img.width + (word['geometry']['bounding_box']['width'] * img.width) / 2),
371
- "y2": int(word['geometry']['bounding_box']['center_y'] * img.height + (word['geometry']['bounding_box']['height'] * img.height) / 2)
372
- }
373
- words_info.append(word_info)
374
-
375
- line_text = ''.join([w['word'] for w in words_info])
376
- line_box = {
377
- "sentence": line_text,
378
- "words": words_info
379
- }
380
-
381
- # Optionally apply furigana filter
382
362
  if furigana_filter_sensitivity:
383
- line_width = line['geometry']['bounding_box']['width'] * img.width
384
- line_height = line['geometry']['bounding_box']['height'] * img.height
385
- if furigana_filter_sensitivity < line_width and furigana_filter_sensitivity < line_height and self.regex.search(line_text):
386
- for w in words_info:
387
- res += w['word']
388
- else:
389
- skipped.extend([w['word'] for w in words_info])
390
- continue
363
+ for word in line['words']:
364
+ if 'geometry' not in word:
365
+ res += word['plain_text']
366
+ continue
367
+ word_width = word['geometry']['bounding_box']['width'] * img.width
368
+ word_height = word['geometry']['bounding_box']['height'] * img.height
369
+ if word_width > furigana_filter_sensitivity and word_height > furigana_filter_sensitivity:
370
+ res += word['plain_text']
371
+ else:
372
+ skipped.extend([word['plain_text'] for word in line['words']])
373
+ continue
391
374
  else:
392
- for w in words_info:
393
- res += w['word']
394
- lines.append(line_box)
375
+ for word in line['words']:
376
+ res += word['plain_text']
395
377
  previous_line = paragraph
396
378
  res += '\n'
397
379
  # logger.info(
@@ -440,6 +422,9 @@ class GoogleLens:
440
422
  else:
441
423
  x = (True, res)
442
424
 
425
+ if skipped:
426
+ logger.info(f"Skipped {len(skipped)} chars due to furigana filter sensitivity: {furigana_filter_sensitivity}")
427
+
443
428
  # img.close()
444
429
  return x
445
430
 
@@ -831,7 +831,7 @@ class OBSScreenshotThread(threading.Thread):
831
831
  self.width = width
832
832
  self.height = height
833
833
  self.use_periodic_queue = not screen_capture_on_combo
834
-
834
+
835
835
  def write_result(self, result):
836
836
  if self.use_periodic_queue:
837
837
  periodic_screenshot_queue.put(result)
@@ -841,18 +841,58 @@ class OBSScreenshotThread(threading.Thread):
841
841
  def connect_obs(self):
842
842
  import GameSentenceMiner.obs as obs
843
843
  obs.connect_to_obs_sync()
844
-
844
+
845
+ def scale_down_width_height(self, width, height):
846
+ if width == 0 or height == 0:
847
+ return self.width, self.height
848
+ aspect_ratio = width / height
849
+ logger.info(f"Scaling down OBS source dimensions: {width}x{height} (Aspect Ratio: {aspect_ratio})")
850
+ if aspect_ratio > 2.66:
851
+ # Ultra-wide (32:9) - use 1920x540
852
+ logger.info("Using ultra-wide aspect ratio scaling (32:9).")
853
+ return 1920, 540
854
+ elif aspect_ratio > 2.33:
855
+ # 21:9 - use 1920x800
856
+ logger.info("Using ultra-wide aspect ratio scaling (21:9).")
857
+ return 1920, 800
858
+ elif aspect_ratio > 1.77:
859
+ # 16:9 - use 1280x720
860
+ logger.info("Using standard aspect ratio scaling (16:9).")
861
+ return 1280, 720
862
+ elif aspect_ratio > 1.6:
863
+ # 16:10 - use 1280x800
864
+ logger.info("Using standard aspect ratio scaling (16:10).")
865
+ return 1280, 800
866
+ elif aspect_ratio > 1.33:
867
+ # 4:3 - use 960x720
868
+ logger.info("Using standard aspect ratio scaling (4:3).")
869
+ return 960, 720
870
+ elif aspect_ratio > 1.25:
871
+ # 5:4 - use 900x720
872
+ logger.info("Using standard aspect ratio scaling (5:4).")
873
+ return 900, 720
874
+ elif aspect_ratio > 1.5:
875
+ # 3:2 - use 1080x720
876
+ logger.info("Using standard aspect ratio scaling (3:2).")
877
+ return 1080, 720
878
+ else:
879
+ # Default/fallback - use 1280x720
880
+ logger.info("Using default aspect ratio scaling (1280x720).")
881
+ return 1280, 720
845
882
 
846
883
  def run(self):
847
884
  global last_image
848
- import base64
849
- import io
850
885
  from PIL import Image
851
886
  import GameSentenceMiner.obs as obs
852
887
 
853
888
  def init_config(source=None, scene=None):
854
889
  obs.update_current_game()
855
890
  self.current_source = source if source else obs.get_active_source()
891
+ self.source_width = self.current_source.get("sceneItemTransform").get("sourceWidth") or self.width
892
+ self.source_height = self.current_source.get("sceneItemTransform").get("sourceHeight") or self.height
893
+ if self.source_width and self.source_height:
894
+ self.width, self.height = self.scale_down_width_height(self.source_width, self.source_height)
895
+ logger.info(f"Using OBS source dimensions: {self.width}x{self.height}")
856
896
  self.current_source_name = self.current_source.get("sourceName") or None
857
897
  self.current_scene = scene if scene else obs.get_current_game()
858
898
  self.ocr_config = get_scene_ocr_config()
@@ -689,7 +689,7 @@ class Config:
689
689
  configs: Dict[str, ProfileConfig] = field(default_factory=dict)
690
690
  current_profile: str = DEFAULT_CONFIG
691
691
  switch_to_default_if_not_found: bool = True
692
- locale: Locale = Locale.English
692
+ locale: Locale = Locale.English.value
693
693
 
694
694
  @classmethod
695
695
  def new(cls):
@@ -138,3 +138,10 @@ def send_error_no_anki_update():
138
138
  message=f"Anki Card not updated, Check Console for Reason!",
139
139
  timeout=5 # Notification disappears after 5 seconds
140
140
  )
141
+
142
+ def send_error_notification(message):
143
+ send_notification(
144
+ title="Error",
145
+ message=message,
146
+ timeout=5 # Notification disappears after 5 seconds
147
+ )
@@ -168,8 +168,8 @@ def extract_text_with_pixel_boxes(
168
168
 
169
169
 
170
170
  for word in line.get("words", []):
171
- if not regex.search(word.get("plain_text", "")):
172
- continue
171
+ # if not regex.search(word.get("plain_text", "")):
172
+ # continue
173
173
  word_text = word.get("plain_text", "")
174
174
  line_text_parts.append(word_text)
175
175
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GameSentenceMiner
3
- Version: 2.13.1
3
+ Version: 2.13.2.post1
4
4
  Summary: A tool for mining sentences from games. Update: Overlay?
5
5
  Author-email: Beangate <bpwhelan95@gmail.com>
6
6
  License: MIT License
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GameSentenceMiner
3
- Version: 2.13.1
3
+ Version: 2.13.2.post1
4
4
  Summary: A tool for mining sentences from games. Update: Overlay?
5
5
  Author-email: Beangate <bpwhelan95@gmail.com>
6
6
  License: MIT License
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
7
7
 
8
8
  [project]
9
9
  name = "GameSentenceMiner"
10
- version = "2.13.1"
10
+ version = "2.13.2.post1"
11
11
  description = "A tool for mining sentences from games. Update: Overlay?"
12
12
  readme = "README.md"
13
13
  requires-python = ">=3.10"