GameSentenceMiner 2.9.16__py3-none-any.whl → 2.9.17__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/util/ffmpeg.py +83 -3
- {gamesentenceminer-2.9.16.dist-info → gamesentenceminer-2.9.17.dist-info}/METADATA +1 -1
- {gamesentenceminer-2.9.16.dist-info → gamesentenceminer-2.9.17.dist-info}/RECORD +7 -7
- {gamesentenceminer-2.9.16.dist-info → gamesentenceminer-2.9.17.dist-info}/WHEEL +0 -0
- {gamesentenceminer-2.9.16.dist-info → gamesentenceminer-2.9.17.dist-info}/entry_points.txt +0 -0
- {gamesentenceminer-2.9.16.dist-info → gamesentenceminer-2.9.17.dist-info}/licenses/LICENSE +0 -0
- {gamesentenceminer-2.9.16.dist-info → gamesentenceminer-2.9.17.dist-info}/top_level.txt +0 -0
GameSentenceMiner/util/ffmpeg.py
CHANGED
@@ -124,7 +124,7 @@ def get_screenshot_for_line(video_file, game_line, try_selector=False):
|
|
124
124
|
return get_screenshot(video_file, get_screenshot_time(video_file, game_line), try_selector)
|
125
125
|
|
126
126
|
|
127
|
-
def get_screenshot_time(video_path, game_line, default_beginning=False, vad_result=None, doing_multi_line=False, previous_line=False):
|
127
|
+
def get_screenshot_time(video_path, game_line, default_beginning=False, vad_result=None, doing_multi_line=False, previous_line=False, anki_card_creation_time=0):
|
128
128
|
if game_line:
|
129
129
|
line_time = game_line.time
|
130
130
|
else:
|
@@ -136,7 +136,10 @@ def get_screenshot_time(video_path, game_line, default_beginning=False, vad_resu
|
|
136
136
|
logger.debug("Calculating screenshot time for line: " + str(game_line.text))
|
137
137
|
|
138
138
|
file_length = get_video_duration(video_path)
|
139
|
-
|
139
|
+
if anki_card_creation_time:
|
140
|
+
file_mod_time = anki_card_creation_time
|
141
|
+
else:
|
142
|
+
file_mod_time = get_file_modification_time(video_path)
|
140
143
|
|
141
144
|
# Calculate when the line occurred within the video file (seconds from start)
|
142
145
|
time_delta = file_mod_time - line_time
|
@@ -279,6 +282,83 @@ def get_audio_and_trim(video_path, game_line, next_line_time, anki_card_creation
|
|
279
282
|
|
280
283
|
return trim_audio_based_on_last_line(untrimmed_audio, video_path, game_line, next_line_time, anki_card_creation_time)
|
281
284
|
|
285
|
+
def get_audio_and_trim_combined(video_path, game_line, next_line_time, anki_card_creation_time):
|
286
|
+
supported_formats = {
|
287
|
+
'opus': 'libopus',
|
288
|
+
'mp3': 'libmp3lame',
|
289
|
+
'ogg': 'libvorbis',
|
290
|
+
'aac': 'aac',
|
291
|
+
'm4a': 'aac',
|
292
|
+
}
|
293
|
+
|
294
|
+
codec = get_audio_codec(video_path)
|
295
|
+
output_extension = get_config().audio.extension
|
296
|
+
output_audio_path = tempfile.NamedTemporaryFile(
|
297
|
+
dir=configuration.get_temporary_directory(),
|
298
|
+
suffix=f".{output_extension}",
|
299
|
+
delete=False
|
300
|
+
).name
|
301
|
+
|
302
|
+
if codec == output_extension:
|
303
|
+
codec_command = ['-c:a', 'copy']
|
304
|
+
logger.debug(f"Extracting {output_extension} from video (copying)")
|
305
|
+
else:
|
306
|
+
codec_command = ["-c:a", f"{supported_formats[output_extension]}"]
|
307
|
+
logger.debug(f"Re-encoding {codec} to {output_extension}")
|
308
|
+
|
309
|
+
start_trim_time, start_time_float, total_seconds_after_offset, file_length = get_video_timings(video_path, game_line, anki_card_creation_time)
|
310
|
+
|
311
|
+
ffmpeg_command = ffmpeg_base_command_list + [
|
312
|
+
"-ss", str(start_trim_time),
|
313
|
+
"-i", video_path,
|
314
|
+
"-map", "0:a"
|
315
|
+
]
|
316
|
+
|
317
|
+
end_trim_time_str = ""
|
318
|
+
|
319
|
+
if next_line_time and next_line_time > game_line.time:
|
320
|
+
end_total_seconds = next_line_time + get_config().audio.pre_vad_end_offset
|
321
|
+
hours, remainder = divmod(end_total_seconds, 3600)
|
322
|
+
minutes, seconds = divmod(remainder, 60)
|
323
|
+
end_trim_time_str = "{:02}:{:02}:{:06.3f}".format(int(hours), int(minutes), seconds)
|
324
|
+
ffmpeg_command.extend(['-to', end_trim_time_str])
|
325
|
+
logger.debug(
|
326
|
+
f"Trimming end of audio to {end_trim_time_str} based on next line time.")
|
327
|
+
elif get_config().audio.pre_vad_end_offset is not None and get_config().audio.pre_vad_end_offset < 0:
|
328
|
+
end_total_seconds = file_length + get_config().audio.pre_vad_end_offset
|
329
|
+
end_total_seconds = max(end_total_seconds, start_time_float)
|
330
|
+
|
331
|
+
hours, remainder = divmod(end_total_seconds, 3600)
|
332
|
+
minutes, seconds = divmod(remainder, 60)
|
333
|
+
end_trim_time_str = "{:02}:{:02}:{:06.3f}".format(int(hours), int(minutes), seconds)
|
334
|
+
ffmpeg_command.extend(['-to', end_trim_time_str])
|
335
|
+
logger.debug(f"Trimming end of audio to {end_trim_time_str} due to negative pre-vad end offset.")
|
336
|
+
|
337
|
+
ffmpeg_command.extend(codec_command)
|
338
|
+
ffmpeg_command.append(output_audio_path)
|
339
|
+
|
340
|
+
logger.debug("Executing combined audio extraction and trimming command")
|
341
|
+
logger.debug(" ".join(ffmpeg_command))
|
342
|
+
|
343
|
+
try:
|
344
|
+
subprocess.run(ffmpeg_command, check=True)
|
345
|
+
logger.debug(f"{total_seconds_after_offset} trimmed off of beginning")
|
346
|
+
|
347
|
+
if end_trim_time_str:
|
348
|
+
logger.info(f"Audio Extracted and trimmed to {start_trim_time} seconds with end time {end_trim_time_str}")
|
349
|
+
else:
|
350
|
+
logger.info(f"Audio Extracted and trimmed to {start_trim_time} seconds (to end of file)")
|
351
|
+
|
352
|
+
logger.debug(f"Audio trimmed and saved to {output_audio_path}")
|
353
|
+
return output_audio_path
|
354
|
+
except subprocess.CalledProcessError as e:
|
355
|
+
logger.error(f"FFmpeg command failed: {e}")
|
356
|
+
logger.error(f"Command: {' '.join(ffmpeg_command)}")
|
357
|
+
raise
|
358
|
+
except Exception as e:
|
359
|
+
logger.error(f"An unexpected error occurred: {e}")
|
360
|
+
raise
|
361
|
+
|
282
362
|
|
283
363
|
def get_video_duration(file_path):
|
284
364
|
ffprobe_command = [
|
@@ -339,7 +419,7 @@ def trim_audio_based_on_last_line(untrimmed_audio, video_path, game_line, next_l
|
|
339
419
|
return trimmed_audio
|
340
420
|
|
341
421
|
def get_video_timings(video_path, game_line, anki_card_creation_time=None):
|
342
|
-
if anki_card_creation_time
|
422
|
+
if anki_card_creation_time:
|
343
423
|
file_mod_time = anki_card_creation_time
|
344
424
|
else:
|
345
425
|
file_mod_time = get_file_modification_time(video_path)
|
@@ -30,7 +30,7 @@ GameSentenceMiner/owocr/owocr/screen_coordinate_picker.py,sha256=Na6XStbQBtpQUSd
|
|
30
30
|
GameSentenceMiner/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
31
31
|
GameSentenceMiner/util/configuration.py,sha256=Wgr1UAf_JoXBlp9h_f3-d2DAmIWnR1FtCmMX6mCfMNM,27461
|
32
32
|
GameSentenceMiner/util/electron_config.py,sha256=3VmIrcXhC-wIMMc4uqV85NrNenRl4ZUbnQfSjWEwuig,9852
|
33
|
-
GameSentenceMiner/util/ffmpeg.py,sha256=
|
33
|
+
GameSentenceMiner/util/ffmpeg.py,sha256=Z3lD5jd7P59-aNWIQDgovwmjT1kCo4-7DLxoG_VBU4M,22618
|
34
34
|
GameSentenceMiner/util/gsm_utils.py,sha256=Z_Lu4jSIfUaM2VljIJXQkSJD0UsyJ5hMB46H2NS0gZo,8819
|
35
35
|
GameSentenceMiner/util/model.py,sha256=iDtLTfR6D-ZC0gCiDqYno6-gA6Z07PZTM4B5MAA6xZI,5704
|
36
36
|
GameSentenceMiner/util/notification.py,sha256=0OnEYjn3DUEZ6c6OtPjdVZe-DG-QSoMAl9fetjjCvNU,3874
|
@@ -59,9 +59,9 @@ GameSentenceMiner/web/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm
|
|
59
59
|
GameSentenceMiner/web/templates/index.html,sha256=HZKiIjiGJV8PGQ9T2aLDUNSfJn71qOwbYCjbRuSIjpY,213583
|
60
60
|
GameSentenceMiner/web/templates/text_replacements.html,sha256=tV5c8mCaWSt_vKuUpbdbLAzXZ3ATZeDvQ9PnnAfqY0M,8598
|
61
61
|
GameSentenceMiner/web/templates/utility.html,sha256=3flZinKNqUJ7pvrZk6xu__v67z44rXnaK7UTZ303R-8,16946
|
62
|
-
gamesentenceminer-2.9.
|
63
|
-
gamesentenceminer-2.9.
|
64
|
-
gamesentenceminer-2.9.
|
65
|
-
gamesentenceminer-2.9.
|
66
|
-
gamesentenceminer-2.9.
|
67
|
-
gamesentenceminer-2.9.
|
62
|
+
gamesentenceminer-2.9.17.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
63
|
+
gamesentenceminer-2.9.17.dist-info/METADATA,sha256=Yj7pAOXZ_NzuJdwXiy5PY8olE4hOGkMq1qG4z59Ehrc,7221
|
64
|
+
gamesentenceminer-2.9.17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
65
|
+
gamesentenceminer-2.9.17.dist-info/entry_points.txt,sha256=2APEP25DbfjSxGeHtwBstMH8mulVhLkqF_b9bqzU6vQ,65
|
66
|
+
gamesentenceminer-2.9.17.dist-info/top_level.txt,sha256=V1hUY6xVSyUEohb0uDoN4UIE6rUZ_JYx8yMyPGX4PgQ,18
|
67
|
+
gamesentenceminer-2.9.17.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|