GameSentenceMiner 2.3.5__py3-none-any.whl → 2.3.7__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.
GameSentenceMiner/anki.py CHANGED
@@ -17,6 +17,7 @@ from GameSentenceMiner.util import remove_html_tags
17
17
 
18
18
  audio_in_anki = None
19
19
  screenshot_in_anki = None
20
+ prev_screenshot_in_anki = None
20
21
 
21
22
  # Global variables to track state
22
23
  previous_note_ids = set()
@@ -26,7 +27,7 @@ card_queue = []
26
27
 
27
28
  def update_anki_card(last_note, note=None, audio_path='', video_path='', tango='', reuse_audio=False,
28
29
  should_update_audio=True, ss_time=0):
29
- global audio_in_anki, screenshot_in_anki
30
+ global audio_in_anki, screenshot_in_anki, prev_screenshot_in_anki
30
31
  update_audio = should_update_audio and (get_config().anki.sentence_audio_field and not
31
32
  last_note['fields'][get_config().anki.sentence_audio_field][
32
33
  'value'] or get_config().anki.overwrite_audio)
@@ -42,9 +43,16 @@ def update_anki_card(last_note, note=None, audio_path='', video_path='', tango='
42
43
  screenshot_in_anki = store_media_file(screenshot)
43
44
  if get_config().paths.remove_screenshot:
44
45
  os.remove(screenshot)
46
+ if get_config().anki.previous_image_field:
47
+ _, previous_sentence = get_last_two_sentences(last_note)
48
+ prev_screenshot = ffmpeg.get_screenshot(video_path, ffmpeg.get_screenshot_time(video_path, gametext.get_time_of_line(previous_sentence)))
49
+ prev_screenshot_in_anki = store_media_file(prev_screenshot)
50
+ if get_config().paths.remove_screenshot:
51
+ os.remove(prev_screenshot)
45
52
  util.set_last_mined_line(get_sentence(last_note))
46
53
  audio_html = f"[sound:{audio_in_anki}]"
47
54
  image_html = f"<img src=\"{screenshot_in_anki}\">"
55
+ prev_screenshot_html = f"<img src=\"{prev_screenshot_in_anki}\">"
48
56
 
49
57
  # note = {'id': last_note['noteId'], 'fields': {}}
50
58
 
@@ -54,6 +62,9 @@ def update_anki_card(last_note, note=None, audio_path='', video_path='', tango='
54
62
  if update_picture:
55
63
  note['fields'][get_config().anki.picture_field] = image_html
56
64
 
65
+ if prev_screenshot_in_anki:
66
+ note['fields'][get_config().anki.previous_image_field] = prev_screenshot_html
67
+
57
68
  if get_config().anki.anki_custom_fields:
58
69
  for key, value in get_config().anki.anki_custom_fields.items():
59
70
  note['fields'][key] = str(value)
@@ -112,8 +123,6 @@ def get_initial_card_info(last_note, selected_lines):
112
123
  if not last_note:
113
124
  return note
114
125
  current_line, previous_line = get_last_two_sentences(last_note)
115
- logger.debug(f"Previous Sentence {previous_line}")
116
- logger.debug(f"Current Sentence {current_line}")
117
126
 
118
127
  if get_config().audio.mining_from_history_grab_all_audio and get_config().anki.multi_overwrites_sentence:
119
128
  lines = gametext.get_line_and_future_lines(last_note)
@@ -496,12 +496,12 @@ class ConfigApp:
496
496
  row=self.current_row,
497
497
  column=2)
498
498
 
499
- ttk.Label(anki_frame, text="Previous Image Field:").grid(row=self.current_row, column=0, sticky='W')
499
+ ttk.Label(anki_frame, text="Previous VoiceLine SS Field:").grid(row=self.current_row, column=0, sticky='W')
500
500
  self.previous_image_field = ttk.Entry(anki_frame)
501
501
  self.previous_image_field.insert(0, self.settings.anki.previous_image_field)
502
502
  self.previous_image_field.grid(row=self.current_row, column=1)
503
503
  self.add_label_and_increment_row(anki_frame,
504
- "Field in Anki for the image line of previous Image. If Empty, will not populate",
504
+ "Field in Anki for the screenshot of previous line. If Empty, will not populate",
505
505
  row=self.current_row,
506
506
  column=2)
507
507
 
@@ -911,6 +911,10 @@ class ConfigApp:
911
911
  self.reload_settings()
912
912
 
913
913
 
914
+ def show_error_box(self, title, message):
915
+ messagebox.showerror(title, message)
916
+
917
+
914
918
  if __name__ == '__main__':
915
919
  window = ConfigApp()
916
920
  window.show()
@@ -163,6 +163,7 @@ def get_video_duration(file_path):
163
163
  logger.debug(" ".join(ffprobe_command))
164
164
  result = subprocess.run(ffprobe_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
165
165
  duration_info = json.loads(result.stdout)
166
+ logger.debug(f"Video duration: {duration_info}")
166
167
  return float(duration_info["format"]["duration"]) # Return the duration in seconds
167
168
 
168
169
 
@@ -16,6 +16,7 @@ from GameSentenceMiner.util import remove_html_tags
16
16
  from difflib import SequenceMatcher
17
17
 
18
18
 
19
+ initial_time = datetime.now()
19
20
  current_line = ''
20
21
  current_line_after_regex = ''
21
22
  current_line_time = datetime.now()
@@ -188,3 +189,9 @@ def get_line_and_future_lines(last_note):
188
189
  found = True
189
190
  found_lines.append(line)
190
191
  return found_lines
192
+
193
+
194
+ def get_time_of_line(line):
195
+ if line and line in line_history:
196
+ return line_history[line]
197
+ return initial_time
GameSentenceMiner/gsm.py CHANGED
@@ -53,9 +53,10 @@ class VideoToAudioHandler(FileSystemEventHandler):
53
53
  @staticmethod
54
54
  def convert_to_audio(video_path):
55
55
  try:
56
+ last_note = None
57
+ if anki.card_queue and len(anki.card_queue) > 0:
58
+ last_note = anki.card_queue.pop(0)
56
59
  with util.lock:
57
- if anki.card_queue and len(anki.card_queue) > 0:
58
- last_note = anki.card_queue.pop(0)
59
60
  if os.path.exists(video_path) and os.access(video_path, os.R_OK):
60
61
  logger.debug(f"Video found and is readable: {video_path}")
61
62
 
@@ -109,6 +110,7 @@ class VideoToAudioHandler(FileSystemEventHandler):
109
110
  logger.exception(f"Card failed to update! Maybe it was removed? {e}")
110
111
  except Exception as e:
111
112
  logger.exception(f"Some error was hit catching to allow further work to be done: {e}")
113
+ # settings_window.show_error_box("Error", f"Some error was hit, check logs for more info: {e}")
112
114
  if get_config().paths.remove_video and os.path.exists(video_path):
113
115
  os.remove(video_path) # Optionally remove the video after conversion
114
116
  if get_config().paths.remove_audio and os.path.exists(vad_trimmed_audio):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: GameSentenceMiner
3
- Version: 2.3.5
3
+ Version: 2.3.7
4
4
  Summary: A tool for mining sentences from games. Update: Multi-Line Mining! Fixed!
5
5
  Author-email: Beangate <bpwhelan95@gmail.com>
6
6
  License: MIT License
@@ -39,9 +39,9 @@ This project automates the recording of game sentence audio to help with Anki Ca
39
39
  This allows us to create cards from texthooker/yomitan, and automatically get screenshot and sentence audio from the
40
40
  game we are playing.
41
41
 
42
- Short Demo (Watch this first): https://www.youtube.com/watch?v=J2At52oWieU
42
+ Short Demo (Watch this first): https://www.youtube.com/watch?v=FeFBL7py6HY
43
43
 
44
- Installation: https://www.youtube.com/watch?v=b-L4g9tA508
44
+ Installation: https://www.youtube.com/watch?v=ybRRB1eIYhk
45
45
 
46
46
  ## How Does it Work?
47
47
 
@@ -1,10 +1,10 @@
1
1
  GameSentenceMiner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- GameSentenceMiner/anki.py,sha256=OHtzFSwfO3GNPFNfxOyPtOy9ATuM6IpeqPPIJX1x7j8,10116
3
- GameSentenceMiner/config_gui.py,sha256=10VaSYc2OGdRT219HLrNkBpUONMUtQG5DKAQf1phano,54171
2
+ GameSentenceMiner/anki.py,sha256=bg_RKaY8bT19hfQQ6BJoPp5G634-xDqTryONLUoK6Z8,10691
3
+ GameSentenceMiner/config_gui.py,sha256=-Jq3ZZZxsLyIaXkQtYVvDeiH3PC4PnrYHxh_wD22174,54270
4
4
  GameSentenceMiner/configuration.py,sha256=_nS-9sWNn97Zdv2V4Ypt_hf4PL6oLa5oK2Z7rWrqEmc,14405
5
- GameSentenceMiner/ffmpeg.py,sha256=VExJYWSFhYuWukIXgOiHufsoSROEDA8LnVQFG8srRGc,10924
6
- GameSentenceMiner/gametext.py,sha256=pPkjIbjHo4XEzwZmShtOwqVxGMraHeAAInxLVahvln4,6502
7
- GameSentenceMiner/gsm.py,sha256=X93WBDGn6Tj1PeHjUm1QNrb6E91MdylbCYsrUe1posU,18259
5
+ GameSentenceMiner/ffmpeg.py,sha256=RN3XlO5uPmD-76wvMZi1CIom0aTq8aNZSZUjLacfJbo,10977
6
+ GameSentenceMiner/gametext.py,sha256=qK9GA9Mn081Ih6kGmunvDhG8HZ5x1RhEco81F2sK4g4,6658
7
+ GameSentenceMiner/gsm.py,sha256=pUKOiJxxSHBqBR3v3U8YiHdwqMxAwvz5keDAGUKGQQA,18388
8
8
  GameSentenceMiner/model.py,sha256=oh8VVT8T1UKekbmP6MGNgQ8jIuQ_7Rg4GPzDCn2kJo8,1999
9
9
  GameSentenceMiner/notification.py,sha256=WBaQWoPNhW4XqdPBUmxPBgjk0ngzH_4v9zMQ-XQAKC8,2010
10
10
  GameSentenceMiner/obs.py,sha256=8ImXAVUWa4JdzwcBOEFShlZRZzh1dCvdpD1aEGhQfbU,6566
@@ -18,8 +18,8 @@ GameSentenceMiner/vad/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
18
18
  GameSentenceMiner/vad/silero_trim.py,sha256=syDJX_KbFmdyFFtnQqYTD0tICsUCJizYhs-atPgXtxA,1549
19
19
  GameSentenceMiner/vad/vosk_helper.py,sha256=-AAwK0cgOC5rK3_gL0sQgrPJ75E49g_PxZR4d5ckwc4,5826
20
20
  GameSentenceMiner/vad/whisper_helper.py,sha256=bpR1HVnJRn9H5u8XaHBqBJ6JwIjzqn-Fajps8QmQ4zc,3411
21
- GameSentenceMiner-2.3.5.dist-info/METADATA,sha256=wddaYl1riJBIO4utwCZC1YjrDBa1YPs0TXsSBKC2Be0,10120
22
- GameSentenceMiner-2.3.5.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
23
- GameSentenceMiner-2.3.5.dist-info/entry_points.txt,sha256=2APEP25DbfjSxGeHtwBstMH8mulVhLkqF_b9bqzU6vQ,65
24
- GameSentenceMiner-2.3.5.dist-info/top_level.txt,sha256=V1hUY6xVSyUEohb0uDoN4UIE6rUZ_JYx8yMyPGX4PgQ,18
25
- GameSentenceMiner-2.3.5.dist-info/RECORD,,
21
+ GameSentenceMiner-2.3.7.dist-info/METADATA,sha256=1O5tVlKwbajXxt2uSpqH1_yOgt8zHMWo4DTyFKKc3iI,10120
22
+ GameSentenceMiner-2.3.7.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
23
+ GameSentenceMiner-2.3.7.dist-info/entry_points.txt,sha256=2APEP25DbfjSxGeHtwBstMH8mulVhLkqF_b9bqzU6vQ,65
24
+ GameSentenceMiner-2.3.7.dist-info/top_level.txt,sha256=V1hUY6xVSyUEohb0uDoN4UIE6rUZ_JYx8yMyPGX4PgQ,18
25
+ GameSentenceMiner-2.3.7.dist-info/RECORD,,