lyrics-transcriber 0.60.0__py3-none-any.whl → 0.62.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.
- lyrics_transcriber/core/controller.py +29 -0
- lyrics_transcriber/frontend/package.json +1 -1
- lyrics_transcriber/frontend/src/types.ts +2 -2
- lyrics_transcriber/frontend/src/validation.ts +2 -2
- lyrics_transcriber/frontend/web_assets/assets/{index-Bktwnsnn.js → index-CYF5xuZH.js} +4 -4
- lyrics_transcriber/frontend/web_assets/assets/{index-Bktwnsnn.js.map → index-CYF5xuZH.js.map} +1 -1
- lyrics_transcriber/frontend/web_assets/index.html +1 -1
- lyrics_transcriber/output/video.py +269 -60
- {lyrics_transcriber-0.60.0.dist-info → lyrics_transcriber-0.62.0.dist-info}/METADATA +1 -1
- {lyrics_transcriber-0.60.0.dist-info → lyrics_transcriber-0.62.0.dist-info}/RECORD +13 -13
- {lyrics_transcriber-0.60.0.dist-info → lyrics_transcriber-0.62.0.dist-info}/LICENSE +0 -0
- {lyrics_transcriber-0.60.0.dist-info → lyrics_transcriber-0.62.0.dist-info}/WHEEL +0 -0
- {lyrics_transcriber-0.60.0.dist-info → lyrics_transcriber-0.62.0.dist-info}/entry_points.txt +0 -0
@@ -5,7 +5,7 @@
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
7
7
|
<title>Lyrics Transcriber Analyzer</title>
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
8
|
+
<script type="module" crossorigin src="/assets/index-CYF5xuZH.js"></script>
|
9
9
|
</head>
|
10
10
|
<body>
|
11
11
|
<div id="root"></div>
|
@@ -43,6 +43,182 @@ class VideoGenerator:
|
|
43
43
|
if self.background_image and not os.path.isfile(self.background_image):
|
44
44
|
raise FileNotFoundError(f"Video background image not found: {self.background_image}")
|
45
45
|
|
46
|
+
# Detect and configure hardware acceleration
|
47
|
+
self.nvenc_available = self.detect_nvenc_support()
|
48
|
+
self.configure_hardware_acceleration()
|
49
|
+
|
50
|
+
def detect_nvenc_support(self):
|
51
|
+
"""Detect if NVENC hardware encoding is available with comprehensive debugging."""
|
52
|
+
try:
|
53
|
+
self.logger.info("🔍 Detecting NVENC hardware acceleration for video generation...")
|
54
|
+
|
55
|
+
# Step 1: Check if NVIDIA GPU is available
|
56
|
+
try:
|
57
|
+
nvidia_smi_cmd = ["nvidia-smi", "--query-gpu=name,driver_version", "--format=csv,noheader"]
|
58
|
+
nvidia_result = subprocess.run(nvidia_smi_cmd, capture_output=True, text=True, timeout=10)
|
59
|
+
if nvidia_result.returncode == 0:
|
60
|
+
gpu_info = nvidia_result.stdout.strip()
|
61
|
+
self.logger.info(f"✓ NVIDIA GPU detected: {gpu_info}")
|
62
|
+
else:
|
63
|
+
self.logger.warning(f"⚠️ nvidia-smi failed: {nvidia_result.stderr}")
|
64
|
+
except Exception as e:
|
65
|
+
self.logger.warning(f"⚠️ nvidia-smi not available or failed: {e}")
|
66
|
+
|
67
|
+
# Step 2: List all available FFmpeg encoders
|
68
|
+
try:
|
69
|
+
encoders_cmd = ["ffmpeg", "-hide_banner", "-encoders"]
|
70
|
+
encoders_result = subprocess.run(encoders_cmd, capture_output=True, text=True, timeout=10)
|
71
|
+
if encoders_result.returncode == 0:
|
72
|
+
# Look for NVENC encoders in the output
|
73
|
+
encoder_lines = encoders_result.stdout.split('\n')
|
74
|
+
nvenc_encoders = [line for line in encoder_lines if 'nvenc' in line.lower()]
|
75
|
+
|
76
|
+
if nvenc_encoders:
|
77
|
+
self.logger.info(f"✓ Found NVENC encoders in FFmpeg:")
|
78
|
+
for encoder in nvenc_encoders:
|
79
|
+
self.logger.info(f" {encoder.strip()}")
|
80
|
+
else:
|
81
|
+
self.logger.warning("⚠️ No NVENC encoders found in FFmpeg encoder list")
|
82
|
+
# Log the first few encoder lines for debugging
|
83
|
+
self.logger.debug("Available encoders (first 10 lines):")
|
84
|
+
for line in encoder_lines[:10]:
|
85
|
+
if line.strip():
|
86
|
+
self.logger.debug(f" {line.strip()}")
|
87
|
+
else:
|
88
|
+
self.logger.error(f"❌ Failed to list FFmpeg encoders: {encoders_result.stderr}")
|
89
|
+
except Exception as e:
|
90
|
+
self.logger.error(f"❌ Error listing FFmpeg encoders: {e}")
|
91
|
+
|
92
|
+
# Step 3: Test h264_nvenc specifically
|
93
|
+
self.logger.info("🧪 Testing h264_nvenc encoder...")
|
94
|
+
test_cmd = [
|
95
|
+
"ffmpeg", "-hide_banner", "-loglevel", "warning", # Changed to warning to get more info
|
96
|
+
"-f", "lavfi", "-i", "testsrc=duration=1:size=320x240:rate=1",
|
97
|
+
"-c:v", "h264_nvenc", "-f", "null", "-"
|
98
|
+
]
|
99
|
+
|
100
|
+
self.logger.debug(f"Running test command: {' '.join(test_cmd)}")
|
101
|
+
|
102
|
+
result = subprocess.run(test_cmd, capture_output=True, text=True, timeout=30)
|
103
|
+
nvenc_available = result.returncode == 0
|
104
|
+
|
105
|
+
if nvenc_available:
|
106
|
+
self.logger.info("✅ NVENC hardware encoding available for video generation")
|
107
|
+
self.logger.info(f"Test command succeeded. Output: {result.stderr[:200]}...")
|
108
|
+
else:
|
109
|
+
self.logger.error("❌ NVENC test failed")
|
110
|
+
self.logger.error(f"Return code: {result.returncode}")
|
111
|
+
self.logger.error(f"STDERR: {result.stderr}")
|
112
|
+
self.logger.error(f"STDOUT: {result.stdout}")
|
113
|
+
|
114
|
+
# Step 4: Try alternative NVENC test
|
115
|
+
self.logger.info("🔄 Trying alternative NVENC detection...")
|
116
|
+
alt_test_cmd = [
|
117
|
+
"ffmpeg", "-hide_banner", "-loglevel", "info",
|
118
|
+
"-f", "lavfi", "-i", "color=red:size=320x240:duration=0.1",
|
119
|
+
"-c:v", "h264_nvenc", "-preset", "fast", "-f", "null", "-"
|
120
|
+
]
|
121
|
+
|
122
|
+
alt_result = subprocess.run(alt_test_cmd, capture_output=True, text=True, timeout=30)
|
123
|
+
if alt_result.returncode == 0:
|
124
|
+
self.logger.info("✅ Alternative NVENC test succeeded!")
|
125
|
+
nvenc_available = True
|
126
|
+
else:
|
127
|
+
self.logger.error(f"❌ Alternative NVENC test also failed:")
|
128
|
+
self.logger.error(f"Alt return code: {alt_result.returncode}")
|
129
|
+
self.logger.error(f"Alt STDERR: {alt_result.stderr}")
|
130
|
+
|
131
|
+
# Step 5: Check for CUDA availability and libraries
|
132
|
+
try:
|
133
|
+
cuda_test_cmd = ["ffmpeg", "-hide_banner", "-loglevel", "error", "-hwaccels"]
|
134
|
+
cuda_result = subprocess.run(cuda_test_cmd, capture_output=True, text=True, timeout=10)
|
135
|
+
if cuda_result.returncode == 0:
|
136
|
+
hwaccels = cuda_result.stdout
|
137
|
+
if 'cuda' in hwaccels:
|
138
|
+
self.logger.info("✓ CUDA hardware acceleration available in FFmpeg")
|
139
|
+
else:
|
140
|
+
self.logger.warning("⚠️ CUDA not found in FFmpeg hardware accelerators")
|
141
|
+
self.logger.debug(f"Available hardware accelerators: {hwaccels.strip()}")
|
142
|
+
else:
|
143
|
+
self.logger.error(f"❌ Failed to list hardware accelerators: {cuda_result.stderr}")
|
144
|
+
except Exception as e:
|
145
|
+
self.logger.error(f"❌ Error checking CUDA availability: {e}")
|
146
|
+
|
147
|
+
# Step 6: Check for CUDA libraries and provide specific troubleshooting
|
148
|
+
self.logger.info("🔍 Checking CUDA library availability...")
|
149
|
+
try:
|
150
|
+
# Check for libcuda.so.1 specifically
|
151
|
+
ldconfig_cmd = ["ldconfig", "-p"]
|
152
|
+
ldconfig_result = subprocess.run(ldconfig_cmd, capture_output=True, text=True, timeout=10)
|
153
|
+
if ldconfig_result.returncode == 0:
|
154
|
+
if "libcuda.so.1" in ldconfig_result.stdout:
|
155
|
+
self.logger.info("✓ libcuda.so.1 found in system libraries")
|
156
|
+
else:
|
157
|
+
self.logger.error("❌ libcuda.so.1 NOT found in system libraries")
|
158
|
+
self.logger.error("💡 This is why NVENC failed - FFmpeg needs libcuda.so.1 for NVENC")
|
159
|
+
self.logger.error("🔧 Solution: Use nvidia/cuda:*-devel image instead of *-runtime")
|
160
|
+
|
161
|
+
# Also check for other NVIDIA libraries
|
162
|
+
if "libnvidia-encode.so" in ldconfig_result.stdout:
|
163
|
+
self.logger.info("✓ libnvidia-encode.so found in system libraries")
|
164
|
+
else:
|
165
|
+
self.logger.warning("⚠️ libnvidia-encode.so not found in system libraries")
|
166
|
+
|
167
|
+
except Exception as e:
|
168
|
+
self.logger.error(f"❌ Error checking CUDA libraries: {e}")
|
169
|
+
|
170
|
+
return nvenc_available
|
171
|
+
|
172
|
+
except subprocess.TimeoutExpired:
|
173
|
+
self.logger.error("❌ NVENC detection timed out")
|
174
|
+
return False
|
175
|
+
except Exception as e:
|
176
|
+
self.logger.error(f"❌ Failed to detect NVENC support: {e}")
|
177
|
+
import traceback
|
178
|
+
self.logger.debug(f"Full traceback: {traceback.format_exc()}")
|
179
|
+
return False
|
180
|
+
|
181
|
+
def configure_hardware_acceleration(self):
|
182
|
+
"""Configure hardware acceleration settings based on detected capabilities."""
|
183
|
+
if self.nvenc_available:
|
184
|
+
self.video_encoder = "h264_nvenc"
|
185
|
+
self.hwaccel_flags = ["-hwaccel", "cuda", "-hwaccel_output_format", "cuda"]
|
186
|
+
self.logger.info("🚀 Configured video generation for NVIDIA hardware acceleration")
|
187
|
+
else:
|
188
|
+
self.video_encoder = "libx264"
|
189
|
+
self.hwaccel_flags = []
|
190
|
+
self.logger.warning("⚠️ NVENC not available, falling back to software encoding for video generation")
|
191
|
+
self.logger.info("💡 This will be slower but should still work. Check logs above for NVENC detection details.")
|
192
|
+
|
193
|
+
def get_nvenc_settings(self, quality_mode="high", is_preview=False):
|
194
|
+
"""Get optimized NVENC settings for subtitle overlay content."""
|
195
|
+
if not self.nvenc_available:
|
196
|
+
return []
|
197
|
+
|
198
|
+
if is_preview:
|
199
|
+
# Fast encoding for preview
|
200
|
+
return [
|
201
|
+
"-preset", "p1", # Fastest preset
|
202
|
+
"-tune", "ll", # Low latency
|
203
|
+
"-rc", "vbr", # Variable bitrate
|
204
|
+
]
|
205
|
+
elif quality_mode == "high":
|
206
|
+
# High quality for final output
|
207
|
+
return [
|
208
|
+
"-preset", "p4", # Balanced preset
|
209
|
+
"-tune", "hq", # High quality
|
210
|
+
"-rc", "vbr", # Variable bitrate
|
211
|
+
"-cq", "18", # Constant quality (higher quality)
|
212
|
+
"-spatial-aq", "1", # Spatial adaptive quantization
|
213
|
+
"-temporal-aq", "1", # Temporal adaptive quantization
|
214
|
+
]
|
215
|
+
else:
|
216
|
+
# Balanced settings
|
217
|
+
return [
|
218
|
+
"-preset", "p4",
|
219
|
+
"-rc", "vbr",
|
220
|
+
]
|
221
|
+
|
46
222
|
def generate_video(self, ass_path: str, audio_path: str, output_prefix: str) -> str:
|
47
223
|
"""Generate MP4 video with lyrics overlay.
|
48
224
|
|
@@ -216,10 +392,9 @@ class VideoGenerator:
|
|
216
392
|
return ass_filter
|
217
393
|
|
218
394
|
def _build_ffmpeg_command(self, ass_path: str, audio_path: str, output_path: str) -> List[str]:
|
219
|
-
"""Build FFmpeg command for video generation with
|
395
|
+
"""Build FFmpeg command for video generation with hardware acceleration when available."""
|
220
396
|
width, height = self.video_resolution
|
221
397
|
|
222
|
-
# fmt: off
|
223
398
|
cmd = [
|
224
399
|
"ffmpeg",
|
225
400
|
"-hide_banner",
|
@@ -227,6 +402,9 @@ class VideoGenerator:
|
|
227
402
|
"-r", "30", # Set frame rate to 30 fps
|
228
403
|
]
|
229
404
|
|
405
|
+
# Add hardware acceleration flags if available
|
406
|
+
cmd.extend(self.hwaccel_flags)
|
407
|
+
|
230
408
|
# Input source (background)
|
231
409
|
if self.background_image:
|
232
410
|
# Resize background image first
|
@@ -250,17 +428,35 @@ class VideoGenerator:
|
|
250
428
|
"-i", audio_path,
|
251
429
|
"-c:a", "flac", # Re-encode audio as FLAC
|
252
430
|
"-vf", self._build_ass_filter(ass_path), # Add subtitles with font directories
|
253
|
-
"-c:v", self.
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
"
|
431
|
+
"-c:v", self.video_encoder,
|
432
|
+
])
|
433
|
+
|
434
|
+
# Add encoder-specific settings
|
435
|
+
if self.nvenc_available:
|
436
|
+
# NVENC settings optimized for subtitle content
|
437
|
+
cmd.extend(self.get_nvenc_settings("high", is_preview=False))
|
438
|
+
# Use higher bitrate for NVENC as it's more efficient
|
439
|
+
cmd.extend([
|
440
|
+
"-b:v", "8000k", # Higher base bitrate for NVENC
|
441
|
+
"-maxrate", "15000k", # Reasonable max for 4K
|
442
|
+
"-bufsize", "16000k", # Buffer size
|
443
|
+
])
|
444
|
+
self.logger.debug("Using NVENC encoding for high-quality video generation")
|
445
|
+
else:
|
446
|
+
# Software encoding fallback settings
|
447
|
+
cmd.extend([
|
448
|
+
"-preset", "fast", # Better compression efficiency
|
449
|
+
"-b:v", "5000k", # Base video bitrate
|
450
|
+
"-minrate", "5000k", # Minimum bitrate
|
451
|
+
"-maxrate", "20000k", # Maximum bitrate
|
452
|
+
"-bufsize", "10000k", # Buffer size (2x base rate)
|
453
|
+
])
|
454
|
+
self.logger.debug("Using software encoding for video generation")
|
455
|
+
|
456
|
+
cmd.extend([
|
260
457
|
"-shortest", # End encoding after shortest stream
|
261
|
-
"-y",
|
458
|
+
"-y", # Overwrite output without asking
|
262
459
|
])
|
263
|
-
# fmt: on
|
264
460
|
|
265
461
|
# Add output path
|
266
462
|
cmd.append(output_path)
|
@@ -268,27 +464,30 @@ class VideoGenerator:
|
|
268
464
|
return cmd
|
269
465
|
|
270
466
|
def _build_preview_ffmpeg_command(self, ass_path: str, audio_path: str, output_path: str) -> List[str]:
|
271
|
-
"""Build FFmpeg command for preview video generation with
|
272
|
-
# Use
|
273
|
-
width, height =
|
467
|
+
"""Build FFmpeg command for preview video generation with hardware acceleration when available."""
|
468
|
+
# Use even lower resolution for preview (480x270 instead of 640x360 for faster encoding)
|
469
|
+
width, height = 480, 270
|
274
470
|
|
275
|
-
# fmt: off
|
276
471
|
cmd = [
|
277
472
|
"ffmpeg",
|
278
473
|
"-hide_banner",
|
279
474
|
"-loglevel", "error",
|
280
|
-
"-r", "
|
475
|
+
"-r", "24", # Reduced frame rate to 24 fps for faster encoding
|
281
476
|
]
|
282
477
|
|
283
|
-
#
|
478
|
+
# Add hardware acceleration flags if available
|
479
|
+
cmd.extend(self.hwaccel_flags)
|
480
|
+
|
481
|
+
# Input source (background) - simplified for preview
|
284
482
|
if self.background_image:
|
285
|
-
#
|
286
|
-
|
287
|
-
self.logger.debug(f"Using resized background image: {resized_bg}")
|
483
|
+
# For preview, use the original image without resizing to save time
|
484
|
+
self.logger.debug(f"Using original background image for preview: {self.background_image}")
|
288
485
|
cmd.extend([
|
289
486
|
"-loop", "1", # Loop the image
|
290
|
-
"-i",
|
487
|
+
"-i", self.background_image,
|
291
488
|
])
|
489
|
+
# Build video filter with scaling and ASS subtitles
|
490
|
+
video_filter = f"scale={width}:{height}:force_original_aspect_ratio=decrease,pad={width}:{height}:(ow-iw)/2:(oh-ih)/2,{self._build_ass_filter(ass_path)}"
|
292
491
|
else:
|
293
492
|
self.logger.debug(
|
294
493
|
f"Using solid {self.background_color} background "
|
@@ -296,30 +495,55 @@ class VideoGenerator:
|
|
296
495
|
)
|
297
496
|
cmd.extend([
|
298
497
|
"-f", "lavfi",
|
299
|
-
"-i", f"color=c={self.background_color}:s={width}x{height}:r=
|
498
|
+
"-i", f"color=c={self.background_color}:s={width}x{height}:r=24",
|
300
499
|
])
|
500
|
+
# Build video filter with just ASS subtitles (no scaling needed)
|
501
|
+
video_filter = self._build_ass_filter(ass_path)
|
301
502
|
|
302
503
|
cmd.extend([
|
303
504
|
"-i", audio_path,
|
304
|
-
"-
|
305
|
-
"-
|
306
|
-
"-
|
307
|
-
"-c:v",
|
308
|
-
|
309
|
-
|
505
|
+
"-vf", video_filter, # Apply the video filter
|
506
|
+
"-c:a", "aac", # Use AAC for audio compatibility
|
507
|
+
"-b:a", "96k", # Reduced audio bitrate for faster encoding
|
508
|
+
"-c:v", self.video_encoder,
|
509
|
+
])
|
510
|
+
|
511
|
+
# Add encoder-specific settings for preview with maximum speed priority
|
512
|
+
if self.nvenc_available:
|
513
|
+
# NVENC settings optimized for maximum speed
|
514
|
+
cmd.extend([
|
515
|
+
"-preset", "p1", # Fastest NVENC preset
|
516
|
+
"-tune", "ll", # Low latency
|
517
|
+
"-rc", "cbr", # Constant bitrate for speed
|
518
|
+
"-b:v", "800k", # Lower bitrate for speed
|
519
|
+
"-profile:v", "baseline", # Most compatible profile
|
520
|
+
"-level", "3.1", # Lower level for speed
|
521
|
+
])
|
522
|
+
self.logger.debug("Using NVENC encoding with maximum speed settings for preview video generation")
|
523
|
+
else:
|
524
|
+
# Software encoding with maximum speed priority
|
525
|
+
cmd.extend([
|
526
|
+
"-profile:v", "baseline", # Most compatible H.264 profile
|
527
|
+
"-level", "3.0", # Compatibility level
|
528
|
+
"-preset", "superfast", # Even faster than ultrafast for preview
|
529
|
+
"-tune", "fastdecode", # Optimize for fast decoding
|
530
|
+
"-b:v", "600k", # Lower base bitrate for speed
|
531
|
+
"-maxrate", "800k", # Lower max bitrate
|
532
|
+
"-bufsize", "1200k", # Smaller buffer size
|
533
|
+
"-crf", "28", # Higher CRF for faster encoding (lower quality but faster)
|
534
|
+
])
|
535
|
+
self.logger.debug("Using software encoding with maximum speed settings for preview video generation")
|
536
|
+
|
537
|
+
cmd.extend([
|
310
538
|
"-pix_fmt", "yuv420p", # Required for browser compatibility
|
311
|
-
"-
|
312
|
-
"-
|
313
|
-
"-
|
314
|
-
"-
|
315
|
-
"-
|
316
|
-
"-
|
317
|
-
"-
|
318
|
-
"-sc_threshold", "0", # Disable scene change detection
|
319
|
-
"-shortest",
|
320
|
-
"-y"
|
539
|
+
"-movflags", "+faststart+frag_keyframe+empty_moov+dash", # Enhanced streaming with dash for faster start
|
540
|
+
"-g", "48", # Keyframe every 48 frames (2 seconds at 24fps) - fewer keyframes for speed
|
541
|
+
"-keyint_min", "48", # Minimum keyframe interval
|
542
|
+
"-sc_threshold", "0", # Disable scene change detection for speed
|
543
|
+
"-threads", "0", # Use all available CPU threads
|
544
|
+
"-shortest", # End encoding after shortest stream
|
545
|
+
"-y" # Overwrite output without asking
|
321
546
|
])
|
322
|
-
# fmt: on
|
323
547
|
|
324
548
|
# Add output path
|
325
549
|
cmd.append(output_path)
|
@@ -327,33 +551,18 @@ class VideoGenerator:
|
|
327
551
|
return cmd
|
328
552
|
|
329
553
|
def _get_video_codec(self) -> str:
|
330
|
-
"""Determine the best available video codec."""
|
331
|
-
#
|
332
|
-
#
|
333
|
-
|
334
|
-
|
335
|
-
# return "h264_videotoolbox"
|
336
|
-
# except Exception as e:
|
337
|
-
# self.logger.warning(f"Error checking for hardware acceleration: {e}")
|
338
|
-
|
339
|
-
# 2025-02-03 00:33:47.948 - INFO - video - Using hardware accelerated h264_videotoolbox
|
340
|
-
# 2025-02-03 00:35:56.761 - INFO - video - Video generated: ./Duran Duran - The Reflex/lyrics/Duran Duran - The Reflex (With Vocals).mkv
|
341
|
-
# Duration: 2:09
|
342
|
-
|
343
|
-
# 2025-02-03 00:41:20.429 - INFO - video - Generating video with lyrics overlay
|
344
|
-
# 2025-02-03 00:42:09.958 - INFO - video - Video generated: ./Duran Duran - The Reflex/lyrics/Duran Duran - The Reflex (With Vocals).mkv
|
345
|
-
# Duration: 49 seconds
|
346
|
-
|
347
|
-
# Conclusion: libx264 is faster than h264_videotoolbox
|
348
|
-
|
349
|
-
return "libx264"
|
554
|
+
"""Determine the best available video codec (legacy method - use video_encoder instead)."""
|
555
|
+
# This method is kept for backwards compatibility but is deprecated
|
556
|
+
# The new hardware acceleration system uses self.video_encoder instead
|
557
|
+
self.logger.warning("_get_video_codec is deprecated, use self.video_encoder instead")
|
558
|
+
return self.video_encoder
|
350
559
|
|
351
560
|
def _run_ffmpeg_command(self, cmd: List[str]) -> None:
|
352
561
|
"""Execute FFmpeg command with output handling."""
|
353
562
|
self.logger.debug(f"Running FFmpeg command: {' '.join(cmd)}")
|
354
563
|
try:
|
355
564
|
output = subprocess.check_output(cmd, universal_newlines=True, stderr=subprocess.STDOUT)
|
356
|
-
|
565
|
+
self.logger.debug(f"FFmpeg output: {output}")
|
357
566
|
except subprocess.CalledProcessError as e:
|
358
567
|
self.logger.error(f"FFmpeg error: {e.output}")
|
359
568
|
raise
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: lyrics-transcriber
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.62.0
|
4
4
|
Summary: Automatically create synchronised lyrics files in ASS and MidiCo LRC formats with word-level timestamps, using Whisper and lyrics from Genius and Spotify
|
5
5
|
License: MIT
|
6
6
|
Author: Andrew Beveridge
|
@@ -3,7 +3,7 @@ lyrics_transcriber/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
|
|
3
3
|
lyrics_transcriber/cli/cli_main.py,sha256=Tk_PtZyAogsPSrmAD8KNQsPMWFW_patX2XM0EZGaVis,10752
|
4
4
|
lyrics_transcriber/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
5
|
lyrics_transcriber/core/config.py,sha256=G4Z5kEBMDXRscEiRKbnofAPuFTDB5h1fLJvwxaHaT4I,1268
|
6
|
-
lyrics_transcriber/core/controller.py,sha256=
|
6
|
+
lyrics_transcriber/core/controller.py,sha256=ZPbOMvVJVke1YlO4CvjDtU2RNQPfRszCEFLn2XjTsuM,22051
|
7
7
|
lyrics_transcriber/correction/anchor_sequence.py,sha256=Bz08zB8yS8orz73aA5dDyNUgBBU87KtQM6yOZGNDoFI,32228
|
8
8
|
lyrics_transcriber/correction/corrector.py,sha256=wwSLHat4SGKEJffFQVcmSfMN_I8Drv-jpeTkO8ndLu0,20930
|
9
9
|
lyrics_transcriber/correction/handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -29,7 +29,7 @@ lyrics_transcriber/frontend/README.md,sha256=-D6CAfKTT7Y0V3EjlZ2fMy7fyctFQ4x2TJ9
|
|
29
29
|
lyrics_transcriber/frontend/__init__.py,sha256=nW8acRSWTjXoRwGqcTU4w-__X7tMAE0iXL0uihBN3CU,836
|
30
30
|
lyrics_transcriber/frontend/eslint.config.js,sha256=3ADH23ANA4NNBKFy6nCVk65e8bx1DrVd_FIaYNnhuqA,734
|
31
31
|
lyrics_transcriber/frontend/index.html,sha256=KfqJVONzpUyPIwV73nZRiCWlwLnFWeB3z0vzxDPNudU,376
|
32
|
-
lyrics_transcriber/frontend/package.json,sha256=
|
32
|
+
lyrics_transcriber/frontend/package.json,sha256=tcF8f7OX1_xEuh3QOZpZKCuZeRpV_1NXT8uVqMyFtAs,1182
|
33
33
|
lyrics_transcriber/frontend/public/vite.svg,sha256=SnSK_UQ5GLsWWRyDTEAdrjPoeGGrXbrQgRw6O0qSFPs,1497
|
34
34
|
lyrics_transcriber/frontend/src/App.tsx,sha256=f1-dp-MU8vap18eAXacwVDO5P4eE2iG9zSvjau-7NJs,6533
|
35
35
|
lyrics_transcriber/frontend/src/api.ts,sha256=UgqPc1jo8DEVgxh3_9Lyf9GBsHYpqMAqsPEE5BzTV4w,6640
|
@@ -72,8 +72,8 @@ lyrics_transcriber/frontend/src/main.tsx,sha256=qNDmjgzD2Dd4d9J42o1z0JcKBElsMWHp
|
|
72
72
|
lyrics_transcriber/frontend/src/theme.ts,sha256=9F2xyLct_gJmvLEZEhrYdKIahUsBzi5kgnydSWJHphE,3864
|
73
73
|
lyrics_transcriber/frontend/src/types/global.d.ts,sha256=NvltPF-n4_1oRLfihD3oHXbdT7txMC8B6fhCgvNY-jk,191
|
74
74
|
lyrics_transcriber/frontend/src/types.js,sha256=1DqoH1vIn6o1ng-XyBS6JRVVkf8Hj7ub_UD4x8loMjA,77
|
75
|
-
lyrics_transcriber/frontend/src/types.ts,sha256=
|
76
|
-
lyrics_transcriber/frontend/src/validation.ts,sha256=
|
75
|
+
lyrics_transcriber/frontend/src/types.ts,sha256=A1BEElm1AsK0qer8rnVbtNYg4cvLZzKiilbKzN1ir4c,3522
|
76
|
+
lyrics_transcriber/frontend/src/validation.ts,sha256=hxMSGfF35JhQprSVBKNyOciqNog9p3twSOqSUdrzT-Q,4297
|
77
77
|
lyrics_transcriber/frontend/src/vite-env.d.ts,sha256=ZZlpNvuwQpFfe3SiAPzd5-QQ8ypmmxq5WXz6pLD63bU,38
|
78
78
|
lyrics_transcriber/frontend/tsconfig.app.json,sha256=7aUBVcaBqEtmtfQXsbwsgBxSUng06xzQi5t4QCgWQ3E,665
|
79
79
|
lyrics_transcriber/frontend/tsconfig.json,sha256=AOS5v1AsNPL3wGc8bt58Ybh8HHpbYrlK91q0KIzaSgs,627
|
@@ -83,9 +83,9 @@ lyrics_transcriber/frontend/update_version.js,sha256=PxkqCnsucXnXiIqutsanVcx00Gq
|
|
83
83
|
lyrics_transcriber/frontend/vite.config.d.ts,sha256=S5bdGf0pSdKM6A6RNBKwAm3EIeW_bDHYfHtesRtXU7Q,76
|
84
84
|
lyrics_transcriber/frontend/vite.config.js,sha256=P4GuPgRZzwEWPQZpyujUe7eA3mjPoFAe2CgE5sQAXg8,232
|
85
85
|
lyrics_transcriber/frontend/vite.config.ts,sha256=8FdW0dN8zDFqfhQSxX5h7sIu72X2piLYlp_TZYRQvBQ,216
|
86
|
-
lyrics_transcriber/frontend/web_assets/assets/index-
|
87
|
-
lyrics_transcriber/frontend/web_assets/assets/index-
|
88
|
-
lyrics_transcriber/frontend/web_assets/index.html,sha256=
|
86
|
+
lyrics_transcriber/frontend/web_assets/assets/index-CYF5xuZH.js,sha256=pxGUWxGTlCLxvBIv6Ud7JXCFSthosLJjFAgVfUREt8s,1257981
|
87
|
+
lyrics_transcriber/frontend/web_assets/assets/index-CYF5xuZH.js.map,sha256=gG53g6J1S56EqzaOn0HbotmLl_o8Stu4gePXIjjtNgs,2678510
|
88
|
+
lyrics_transcriber/frontend/web_assets/index.html,sha256=8g28E4JotmYVKSqIYPpMEgXUfREGAMUiceB3_26-uaY,400
|
89
89
|
lyrics_transcriber/frontend/web_assets/vite.svg,sha256=SnSK_UQ5GLsWWRyDTEAdrjPoeGGrXbrQgRw6O0qSFPs,1497
|
90
90
|
lyrics_transcriber/frontend/yarn.lock,sha256=wtImLsCO1P1Lpkhc1jAN6IiHQ0As4xn39n0cwKoh4LM,131996
|
91
91
|
lyrics_transcriber/lyrics/base_lyrics_provider.py,sha256=LCzmwpBFgSfC6VVY5AtJHmE0OvgjAQyjPnL-dYLLwg4,9172
|
@@ -143,7 +143,7 @@ lyrics_transcriber/output/lyrics_file.py,sha256=_KQyQjCOMIwQdQ0115uEAUIjQWTRmShk
|
|
143
143
|
lyrics_transcriber/output/plain_text.py,sha256=XARaWcy6MeQeQCUoz0PV_bHoBw5dba-u79bjS7XucnE,3867
|
144
144
|
lyrics_transcriber/output/segment_resizer.py,sha256=rrgcQC28eExSAmGnm6ytkF-E-nH4Fe3gjvpaCD0MCmA,17510
|
145
145
|
lyrics_transcriber/output/subtitles.py,sha256=yQCR7YO3aitKnGRjfAtSwsdi6byfpEZgnCumJO16M2E,19085
|
146
|
-
lyrics_transcriber/output/video.py,sha256=
|
146
|
+
lyrics_transcriber/output/video.py,sha256=VLsoDTGb3aXuxg7o6Uv-JJV0A79C06o3LtzywOHwHcE,26268
|
147
147
|
lyrics_transcriber/review/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
148
148
|
lyrics_transcriber/review/server.py,sha256=WXWyJZJsKm6_HhGxRdP2fD7kyMAmuc_I-Kvqx_uA4NI,14833
|
149
149
|
lyrics_transcriber/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -153,8 +153,8 @@ lyrics_transcriber/transcribers/base_transcriber.py,sha256=T3m4ZCwZ9Bpv6Jvb2hNcn
|
|
153
153
|
lyrics_transcriber/transcribers/whisper.py,sha256=YcCB1ic9H6zL1GS0jD0emu8-qlcH0QVEjjjYB4aLlIQ,13260
|
154
154
|
lyrics_transcriber/types.py,sha256=wqFrTKhb8qAUB48zH-51_EEGCGrxm0Ji-ETfQumtSKc,27666
|
155
155
|
lyrics_transcriber/utils/word_utils.py,sha256=-cMGpj9UV4F6IsoDKAV2i1aiqSO8eI91HMAm_igtVMk,958
|
156
|
-
lyrics_transcriber-0.
|
157
|
-
lyrics_transcriber-0.
|
158
|
-
lyrics_transcriber-0.
|
159
|
-
lyrics_transcriber-0.
|
160
|
-
lyrics_transcriber-0.
|
156
|
+
lyrics_transcriber-0.62.0.dist-info/LICENSE,sha256=81R_4XwMZDODHD7JcZeUR8IiCU8AD7Ajl6bmwR9tYDk,1074
|
157
|
+
lyrics_transcriber-0.62.0.dist-info/METADATA,sha256=-kzEJYYhIJMt1xI1Az6tqeIDRYJ7WUDp71NZIDmCNhA,6637
|
158
|
+
lyrics_transcriber-0.62.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
159
|
+
lyrics_transcriber-0.62.0.dist-info/entry_points.txt,sha256=kcp-bSFkCACAEA0t166Kek0HpaJUXRo5SlF5tVrqNBU,216
|
160
|
+
lyrics_transcriber-0.62.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
{lyrics_transcriber-0.60.0.dist-info → lyrics_transcriber-0.62.0.dist-info}/entry_points.txt
RENAMED
File without changes
|