GameSentenceMiner 2.10.0__py3-none-any.whl → 2.10.2__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
@@ -261,11 +261,13 @@ def get_cards_by_sentence(sentence):
261
261
  logger.warning(f'Found more than 1, and not updating cards for query: \n{query}')
262
262
  return {}
263
263
 
264
- last_notes = invoke('notesInfo', notes=[card_ids[0]])[0]
265
-
266
- logger.info(f"Found Card to backfill!: {card_ids[0]}")
267
-
268
- return last_notes
264
+ card_dict = invoke('notesInfo', notes=[card_ids[-1]])[0]
265
+ try:
266
+ return AnkiCard.from_dict(card_dict)
267
+ except Exception as e:
268
+ logger.error(f"Error fetching last card: {e}")
269
+ logger.info(card_dict)
270
+ raise e
269
271
 
270
272
  last_connection_error = datetime.now()
271
273
 
GameSentenceMiner/gsm.py CHANGED
@@ -80,6 +80,9 @@ class VideoToAudioHandler(FileSystemEventHandler):
80
80
  vad_trimmed_audio = ''
81
81
  final_audio_output = ''
82
82
  skip_delete = False
83
+ selected_lines = []
84
+ anki_card_creation_time = None
85
+ mined_line = None
83
86
  gsm_state.previous_replay = video_path
84
87
  if gsm_state.line_for_audio or gsm_state.line_for_screenshot:
85
88
  handle_texthooker_button(video_path, get_audio_from_video=VideoToAudioHandler.get_audio)
@@ -87,6 +90,8 @@ class VideoToAudioHandler(FileSystemEventHandler):
87
90
  try:
88
91
  if anki.card_queue and len(anki.card_queue) > 0:
89
92
  last_note, anki_card_creation_time, selected_lines = anki.card_queue.pop(0)
93
+ elif get_config().features.backfill_audio:
94
+ last_note = anki.get_cards_by_sentence(gametext.current_line_after_regex)
90
95
  else:
91
96
  logger.info("Replay buffer initiated externally. Skipping processing.")
92
97
  skip_delete = True
@@ -103,8 +108,9 @@ class VideoToAudioHandler(FileSystemEventHandler):
103
108
  logger.error(
104
109
  f"Video was unusually small, potentially empty! Check OBS for Correct Scene Settings! Path: {video_path}")
105
110
  return
111
+
112
+ # Just for safety
106
113
  if not last_note:
107
- logger.debug("Attempting to get last anki card")
108
114
  if get_config().anki.update_anki:
109
115
  last_note = anki.get_last_anki_card()
110
116
  if get_config().features.backfill_audio:
@@ -165,7 +171,8 @@ class VideoToAudioHandler(FileSystemEventHandler):
165
171
  elif get_config().features.notify_on_update and vad_result.success:
166
172
  notification.send_audio_generated_notification(vad_trimmed_audio)
167
173
  except Exception as e:
168
- anki_results[mined_line.id] = AnkiUpdateResult.failure()
174
+ if mined_line:
175
+ anki_results[mined_line.id] = AnkiUpdateResult.failure()
169
176
  logger.error(f"Failed Processing and/or adding to Anki: Reason {e}")
170
177
  logger.debug(f"Some error was hit catching to allow further work to be done: {e}", exc_info=True)
171
178
  notification.send_error_no_anki_update()
@@ -1,4 +1,11 @@
1
+
1
2
  import os
3
+ import sys
4
+
5
+ sys_stdout = sys.stdout
6
+ sys_stderr = sys.stderr
7
+ sys.stdout = open(os.devnull, 'w')
8
+ sys.stderr = open(os.devnull, 'w')
2
9
  import tkinter as tk
3
10
  from tkinter import filedialog, messagebox
4
11
  import soundfile as sf
@@ -175,7 +182,10 @@ class AudioOffsetGUI:
175
182
 
176
183
  beg_offset = self.beg_slider.get() - 5.0
177
184
  end_offset = self.duration # End offset is always full duration
178
-
185
+ sys.stdout.close()
186
+ sys.stderr.close()
187
+ sys.stdout = sys_stdout
188
+ sys.stderr = sys_stderr
179
189
  print(f"{beg_offset:.2f}")
180
190
  exit(0)
181
191
 
@@ -223,10 +223,14 @@ def do_text_replacements(text, replacements_json):
223
223
 
224
224
  def open_audio_in_external(fileabspath, shell=False):
225
225
  logger.info(f"Opening audio in external program...")
226
- if shell:
227
- subprocess.Popen(f' "{get_config().audio.external_tool}" "{fileabspath}" ', shell=True)
228
- else:
229
- subprocess.Popen([get_config().audio.external_tool, fileabspath])
226
+ try:
227
+ if shell:
228
+ subprocess.Popen(f' "{get_config().audio.external_tool}" "{fileabspath}" ', shell=True)
229
+ else:
230
+ subprocess.Popen([get_config().audio.external_tool, fileabspath])
231
+ except Exception as e:
232
+ logger.error(f"Failed to open audio in external program: {e}")
233
+ return False
230
234
 
231
235
  def is_connected():
232
236
  try:
@@ -271,7 +275,7 @@ def remove_github_replacements_from_local_ocr():
271
275
  return
272
276
 
273
277
  if not os.path.exists(OCR_REPLACEMENTS_FILE):
274
- logger.warning(f"Local file {OCR_REPLACEMENTS_FILE} does not exist. No replacements to remove.")
278
+ logger.debug(f"Local file {OCR_REPLACEMENTS_FILE} does not exist. No replacements to remove.")
275
279
  return
276
280
 
277
281
  try:
@@ -303,4 +307,4 @@ def remove_github_replacements_from_local_ocr():
303
307
  logger.debug(f"An unexpected error occurred while processing {OCR_REPLACEMENTS_FILE}: {e}")
304
308
 
305
309
 
306
- remove_github_replacements_from_local_ocr()
310
+ remove_github_replacements_from_local_ocr()
@@ -1,15 +1,22 @@
1
- import tkinter as tk
2
- from PIL import Image, ImageTk
3
- import subprocess
1
+
2
+
4
3
  import os
5
4
  import sys
5
+ import subprocess
6
6
 
7
+ # Suppress stdout and stderr during imports
8
+ sys_stdout = sys.stdout
9
+ sys_stderr = sys.stderr
10
+ sys.stdout = open(os.devnull, 'w')
11
+ sys.stderr = open(os.devnull, 'w')
12
+
13
+ import tkinter as tk
14
+ from PIL import Image, ImageTk
7
15
  from GameSentenceMiner.util.gsm_utils import sanitize_filename
8
16
  from GameSentenceMiner.util.configuration import get_temporary_directory, logger
9
17
  from GameSentenceMiner.util.ffmpeg import ffmpeg_base_command_list
10
18
  from GameSentenceMiner.util import ffmpeg
11
19
 
12
-
13
20
  def extract_frames(video_path, timestamp, temp_dir, mode):
14
21
  frame_paths = []
15
22
  timestamp_number = float(timestamp)
@@ -98,6 +105,10 @@ def run_extraction_and_display(video_path, timestamp_str, mode):
98
105
  if image_paths:
99
106
  selected_image_path = display_images(image_paths, golden_frame)
100
107
  if selected_image_path:
108
+ sys.stdout.close()
109
+ sys.stderr.close()
110
+ sys.stdout = sys_stdout
111
+ sys.stderr = sys_stderr
101
112
  print(selected_image_path)
102
113
  else:
103
114
  logger.debug("No image was selected.")
@@ -105,6 +116,8 @@ def run_extraction_and_display(video_path, timestamp_str, mode):
105
116
  logger.debug("Frame extraction failed.")
106
117
 
107
118
  def main():
119
+
120
+
108
121
  # if len(sys.argv) != 3:
109
122
  # print("Usage: python script.py <video_path> <timestamp>")
110
123
  # sys.exit(1)
@@ -23,8 +23,10 @@ def handle_texthooker_button(video_path='', get_audio_from_video=None):
23
23
  elif get_config().advanced.video_player_path:
24
24
  play_video_in_external(line, gsm_state.previous_audio)
25
25
  else:
26
- play_obj = gsm_state.previous_audio.play()
27
- play_obj.wait_done()
26
+ import sounddevice as sd
27
+ data, samplerate = gsm_state.previous_audio
28
+ sd.play(data, samplerate)
29
+ sd.wait()
28
30
  return
29
31
  gsm_state.previous_line_for_audio = line
30
32
  if get_config().advanced.audio_player_path:
@@ -37,13 +39,14 @@ def handle_texthooker_button(video_path='', get_audio_from_video=None):
37
39
  gsm_state.previous_audio = new_video_path
38
40
  gsm_state.previous_replay = new_video_path
39
41
  else:
40
- import simpleaudio as sa
42
+ import sounddevice as sd
43
+ import soundfile as sf
41
44
  audio = get_audio_from_video(line, line.next.time if line.next else None, video_path,
42
45
  temporary=True)
43
- wave_obj = sa.WaveObject.from_wave_file(audio)
44
- play_obj = wave_obj.play()
45
- play_obj.wait_done()
46
- gsm_state.previous_audio = wave_obj
46
+ data, samplerate = sf.read(audio)
47
+ sd.play(data, samplerate)
48
+ sd.wait()
49
+ gsm_state.previous_audio = (data, samplerate)
47
50
  return
48
51
  if gsm_state.line_for_screenshot:
49
52
  line: GameLine = gsm_state.line_for_screenshot