lyrics-transcriber 0.57.1__py3-none-any.whl → 0.59.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/cli/cli_main.py +2 -0
- lyrics_transcriber/core/config.py +1 -0
- lyrics_transcriber/core/controller.py +1 -0
- lyrics_transcriber/frontend/package.json +1 -1
- lyrics_transcriber/frontend/web_assets/assets/{index-BEnewYea.js → index-HT4AHF8U.js} +2 -2
- lyrics_transcriber/frontend/web_assets/assets/{index-BEnewYea.js.map → index-HT4AHF8U.js.map} +1 -1
- lyrics_transcriber/frontend/web_assets/index.html +1 -1
- lyrics_transcriber/lyrics/base_lyrics_provider.py +1 -0
- lyrics_transcriber/lyrics/genius.py +255 -4
- lyrics_transcriber/output/video.py +18 -4
- {lyrics_transcriber-0.57.1.dist-info → lyrics_transcriber-0.59.0.dist-info}/METADATA +1 -1
- {lyrics_transcriber-0.57.1.dist-info → lyrics_transcriber-0.59.0.dist-info}/RECORD +15 -15
- {lyrics_transcriber-0.57.1.dist-info → lyrics_transcriber-0.59.0.dist-info}/LICENSE +0 -0
- {lyrics_transcriber-0.57.1.dist-info → lyrics_transcriber-0.59.0.dist-info}/WHEEL +0 -0
- {lyrics_transcriber-0.57.1.dist-info → lyrics_transcriber-0.59.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-HT4AHF8U.js"></script>
|
9
9
|
</head>
|
10
10
|
<body>
|
11
11
|
<div id="root"></div>
|
@@ -16,6 +16,7 @@ class LyricsProviderConfig:
|
|
16
16
|
"""Configuration for lyrics providers."""
|
17
17
|
|
18
18
|
genius_api_token: Optional[str] = None
|
19
|
+
rapidapi_key: Optional[str] = None
|
19
20
|
spotify_cookie: Optional[str] = None
|
20
21
|
lyrics_file: Optional[str] = None
|
21
22
|
cache_dir: Optional[str] = None
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import logging
|
2
2
|
import re
|
3
3
|
from typing import Optional, Dict, Any
|
4
|
+
import requests
|
4
5
|
import lyricsgenius
|
5
6
|
from lyrics_transcriber.types import LyricsData, LyricsMetadata
|
6
7
|
from lyrics_transcriber.lyrics.base_lyrics_provider import BaseLyricsProvider, LyricsProviderConfig
|
@@ -12,6 +13,7 @@ class GeniusProvider(BaseLyricsProvider):
|
|
12
13
|
def __init__(self, config: LyricsProviderConfig, logger: Optional[logging.Logger] = None):
|
13
14
|
super().__init__(config, logger)
|
14
15
|
self.api_token = config.genius_api_token
|
16
|
+
self.rapidapi_key = config.rapidapi_key
|
15
17
|
self.client = None
|
16
18
|
if self.api_token:
|
17
19
|
self.client = lyricsgenius.Genius(
|
@@ -25,9 +27,17 @@ class GeniusProvider(BaseLyricsProvider):
|
|
25
27
|
)
|
26
28
|
|
27
29
|
def _fetch_data_from_source(self, artist: str, title: str) -> Optional[Dict[str, Any]]:
|
28
|
-
"""Fetch raw song data from Genius API."""
|
30
|
+
"""Fetch raw song data from Genius API or RapidAPI."""
|
31
|
+
# Try RapidAPI first if available
|
32
|
+
if self.rapidapi_key:
|
33
|
+
self.logger.info(f"Trying RapidAPI for {artist} - {title}")
|
34
|
+
result = self._fetch_from_rapidapi(artist, title)
|
35
|
+
if result:
|
36
|
+
return result
|
37
|
+
|
38
|
+
# Fall back to direct Genius API
|
29
39
|
if not self.client:
|
30
|
-
self.logger.warning("No Genius API token provided")
|
40
|
+
self.logger.warning("No Genius API token provided and RapidAPI failed")
|
31
41
|
return None
|
32
42
|
|
33
43
|
self.logger.info(f"Searching Genius for {artist} - {title}")
|
@@ -40,8 +50,186 @@ class GeniusProvider(BaseLyricsProvider):
|
|
40
50
|
self.logger.error(f"Error fetching from Genius: {str(e)}")
|
41
51
|
return None
|
42
52
|
|
53
|
+
def _fetch_from_rapidapi(self, artist: str, title: str) -> Optional[Dict[str, Any]]:
|
54
|
+
"""Fetch song data using RapidAPI."""
|
55
|
+
try:
|
56
|
+
# Step 1: Search for the song
|
57
|
+
search_url = "https://genius-song-lyrics1.p.rapidapi.com/search/"
|
58
|
+
search_params = {
|
59
|
+
"q": f"{artist} {title}",
|
60
|
+
"per_page": "10",
|
61
|
+
"page": "1"
|
62
|
+
}
|
63
|
+
|
64
|
+
headers = {
|
65
|
+
"x-rapidapi-key": self.rapidapi_key,
|
66
|
+
"x-rapidapi-host": "genius-song-lyrics1.p.rapidapi.com"
|
67
|
+
}
|
68
|
+
|
69
|
+
self.logger.debug(f"Making RapidAPI search request for '{artist} {title}'")
|
70
|
+
search_response = requests.get(search_url, headers=headers, params=search_params, timeout=10)
|
71
|
+
search_response.raise_for_status()
|
72
|
+
|
73
|
+
search_data = search_response.json()
|
74
|
+
|
75
|
+
# Find the best match from search results
|
76
|
+
if not search_data.get("hits"):
|
77
|
+
self.logger.warning("No search results from RapidAPI")
|
78
|
+
return None
|
79
|
+
|
80
|
+
best_match = None
|
81
|
+
for hit in search_data["hits"]:
|
82
|
+
result = hit.get("result", {})
|
83
|
+
if result.get("id"):
|
84
|
+
best_match = result
|
85
|
+
break
|
86
|
+
|
87
|
+
if not best_match:
|
88
|
+
self.logger.warning("No valid song ID found in RapidAPI search results")
|
89
|
+
return None
|
90
|
+
|
91
|
+
song_id = best_match["id"]
|
92
|
+
self.logger.debug(f"Found song ID: {song_id}")
|
93
|
+
|
94
|
+
# Step 2: Fetch lyrics using the song ID
|
95
|
+
lyrics_url = "https://genius-song-lyrics1.p.rapidapi.com/song/lyrics/"
|
96
|
+
lyrics_params = {"id": str(song_id)}
|
97
|
+
|
98
|
+
self.logger.debug(f"Making RapidAPI lyrics request for song ID {song_id}")
|
99
|
+
lyrics_response = requests.get(lyrics_url, headers=headers, params=lyrics_params, timeout=10)
|
100
|
+
lyrics_response.raise_for_status()
|
101
|
+
|
102
|
+
lyrics_data = lyrics_response.json()
|
103
|
+
|
104
|
+
# Extract lyrics from the nested response structure
|
105
|
+
lyrics_text = self._extract_lyrics_from_rapidapi_response(lyrics_data)
|
106
|
+
if not lyrics_text:
|
107
|
+
self.logger.warning("No lyrics found in RapidAPI response")
|
108
|
+
return None
|
109
|
+
|
110
|
+
# Create a clean RapidAPI-only response structure
|
111
|
+
# Don't mix search metadata (which contains Genius fields) with our clean structure
|
112
|
+
rapidapi_response = {
|
113
|
+
"title": best_match.get("title", ""),
|
114
|
+
"primary_artist": best_match.get("primary_artist", {}),
|
115
|
+
"lyrics": lyrics_text,
|
116
|
+
"id": song_id,
|
117
|
+
"url": best_match.get("url", ""),
|
118
|
+
"release_date_for_display": best_match.get("release_date_for_display", ""),
|
119
|
+
# Mark this as RapidAPI source
|
120
|
+
"_rapidapi_source": True
|
121
|
+
}
|
122
|
+
|
123
|
+
self.logger.info("Successfully fetched lyrics from RapidAPI")
|
124
|
+
return rapidapi_response
|
125
|
+
|
126
|
+
except requests.exceptions.RequestException as e:
|
127
|
+
self.logger.error(f"RapidAPI request failed: {str(e)}")
|
128
|
+
return None
|
129
|
+
except Exception as e:
|
130
|
+
self.logger.error(f"Error fetching from RapidAPI: {str(e)}")
|
131
|
+
return None
|
132
|
+
|
133
|
+
def _extract_lyrics_from_rapidapi_response(self, lyrics_data: Dict[str, Any]) -> Optional[str]:
|
134
|
+
"""Extract lyrics text from RapidAPI response structure."""
|
135
|
+
try:
|
136
|
+
# Log the actual response structure for debugging
|
137
|
+
self.logger.debug(f"RapidAPI response structure: {lyrics_data}")
|
138
|
+
|
139
|
+
# Try different possible response structures
|
140
|
+
|
141
|
+
# Structure 1: lyrics.lyrics.body.html (the actual RapidAPI structure)
|
142
|
+
nested_lyrics = lyrics_data.get("lyrics", {}).get("lyrics", {})
|
143
|
+
if isinstance(nested_lyrics, dict):
|
144
|
+
html_content = nested_lyrics.get("body", {}).get("html")
|
145
|
+
if html_content:
|
146
|
+
return self._clean_html_lyrics(html_content)
|
147
|
+
|
148
|
+
# Structure 2: lyrics.lyrics (simple string)
|
149
|
+
if isinstance(lyrics_data.get("lyrics", {}).get("lyrics"), str):
|
150
|
+
return lyrics_data["lyrics"]["lyrics"]
|
151
|
+
|
152
|
+
# Structure 3: lyrics.body.html (HTML content)
|
153
|
+
html_content = lyrics_data.get("lyrics", {}).get("body", {}).get("html")
|
154
|
+
if html_content:
|
155
|
+
return self._clean_html_lyrics(html_content)
|
156
|
+
|
157
|
+
# Structure 4: Direct lyrics field
|
158
|
+
if isinstance(lyrics_data.get("lyrics"), str):
|
159
|
+
return lyrics_data["lyrics"]
|
160
|
+
|
161
|
+
# Structure 5: body.html at top level
|
162
|
+
if lyrics_data.get("body", {}).get("html"):
|
163
|
+
return self._clean_html_lyrics(lyrics_data["body"]["html"])
|
164
|
+
|
165
|
+
# Structure 6: Check if lyrics is a dict with other possible keys
|
166
|
+
lyrics_obj = lyrics_data.get("lyrics", {})
|
167
|
+
if isinstance(lyrics_obj, dict):
|
168
|
+
# Try common alternative keys
|
169
|
+
for key in ["text", "content", "plain", "body"]:
|
170
|
+
if key in lyrics_obj:
|
171
|
+
content = lyrics_obj[key]
|
172
|
+
if isinstance(content, str):
|
173
|
+
return content
|
174
|
+
elif isinstance(content, dict) and "html" in content:
|
175
|
+
return self._clean_html_lyrics(content["html"])
|
176
|
+
elif isinstance(content, dict) and "text" in content:
|
177
|
+
return content["text"]
|
178
|
+
|
179
|
+
self.logger.warning(f"Unknown RapidAPI response structure: {list(lyrics_data.keys())}")
|
180
|
+
if "lyrics" in lyrics_data:
|
181
|
+
self.logger.warning(f"Lyrics object structure: {lyrics_data['lyrics']}")
|
182
|
+
return None
|
183
|
+
|
184
|
+
except Exception as e:
|
185
|
+
self.logger.error(f"Error extracting lyrics from RapidAPI response: {str(e)}")
|
186
|
+
return None
|
187
|
+
|
188
|
+
def _clean_html_lyrics(self, html_content: str) -> str:
|
189
|
+
"""Clean HTML content to extract plain text lyrics."""
|
190
|
+
import re
|
191
|
+
|
192
|
+
if not html_content:
|
193
|
+
return ""
|
194
|
+
|
195
|
+
# Remove HTML tags while preserving line breaks
|
196
|
+
text = re.sub(r'<br\s*/?>', '\n', html_content) # Convert <br> to newlines
|
197
|
+
text = re.sub(r'<[^>]+>', '', text) # Remove all other HTML tags
|
198
|
+
|
199
|
+
# Decode HTML entities
|
200
|
+
text = text.replace('<', '<').replace('>', '>').replace('&', '&')
|
201
|
+
text = text.replace('"', '"').replace(''', "'").replace(' ', ' ')
|
202
|
+
|
203
|
+
# Remove section markers but keep the lyrics content
|
204
|
+
# Instead of removing entire lines, just remove the square bracket markers
|
205
|
+
text = re.sub(r'\[Verse \d+\]', '', text)
|
206
|
+
text = re.sub(r'\[Pre-Chorus\]', '', text)
|
207
|
+
text = re.sub(r'\[Chorus\]', '', text)
|
208
|
+
text = re.sub(r'\[Refrain\]', '', text)
|
209
|
+
text = re.sub(r'\[Outro\]', '', text)
|
210
|
+
text = re.sub(r'\[Bridge\]', '', text)
|
211
|
+
text = re.sub(r'\[Intro\]', '', text)
|
212
|
+
|
213
|
+
# Clean up multiple consecutive newlines
|
214
|
+
text = re.sub(r'\n\s*\n\s*\n+', '\n\n', text)
|
215
|
+
|
216
|
+
# Clean up leading/trailing whitespace
|
217
|
+
text = text.strip()
|
218
|
+
|
219
|
+
return text
|
220
|
+
|
43
221
|
def _convert_result_format(self, raw_data: Dict[str, Any]) -> LyricsData:
|
44
222
|
"""Convert Genius's raw API response to standardized format."""
|
223
|
+
# Use our explicit source marker for detection
|
224
|
+
is_rapidapi = raw_data.get("_rapidapi_source", False)
|
225
|
+
|
226
|
+
if is_rapidapi:
|
227
|
+
return self._convert_rapidapi_format(raw_data)
|
228
|
+
else:
|
229
|
+
return self._convert_lyricsgenius_format(raw_data)
|
230
|
+
|
231
|
+
def _convert_lyricsgenius_format(self, raw_data: Dict[str, Any]) -> LyricsData:
|
232
|
+
"""Convert lyricsgenius format to standardized format."""
|
45
233
|
# Clean the lyrics before processing
|
46
234
|
lyrics = self._clean_lyrics(raw_data.get("lyrics", ""))
|
47
235
|
|
@@ -74,6 +262,46 @@ class GeniusProvider(BaseLyricsProvider):
|
|
74
262
|
"verified_annotations": len(raw_data.get("verified_annotations_by", [])),
|
75
263
|
"verified_contributors": len(raw_data.get("verified_contributors", [])),
|
76
264
|
"external_urls": {"genius": raw_data.get("url")},
|
265
|
+
"api_source": "lyricsgenius",
|
266
|
+
},
|
267
|
+
)
|
268
|
+
|
269
|
+
# Create segments with words from cleaned lyrics
|
270
|
+
segments = self._create_segments_with_words(lyrics, is_synced=False)
|
271
|
+
|
272
|
+
# Create result object with segments
|
273
|
+
return LyricsData(source="genius", segments=segments, metadata=metadata)
|
274
|
+
|
275
|
+
def _convert_rapidapi_format(self, raw_data: Dict[str, Any]) -> LyricsData:
|
276
|
+
"""Convert RapidAPI format to standardized format."""
|
277
|
+
# Clean the lyrics before processing
|
278
|
+
lyrics = self._clean_lyrics(raw_data.get("lyrics", ""))
|
279
|
+
|
280
|
+
# Extract artist name from primary_artist
|
281
|
+
primary_artist = raw_data.get("primary_artist", {})
|
282
|
+
artist_name = primary_artist.get("name", "")
|
283
|
+
|
284
|
+
# Extract release date from release_date_for_display
|
285
|
+
release_date = raw_data.get("release_date_for_display")
|
286
|
+
|
287
|
+
# Create metadata object
|
288
|
+
metadata = LyricsMetadata(
|
289
|
+
source="genius",
|
290
|
+
track_name=raw_data.get("title", ""),
|
291
|
+
artist_names=artist_name,
|
292
|
+
album_name=raw_data.get("album", {}).get("name") if raw_data.get("album") else None,
|
293
|
+
lyrics_provider="genius",
|
294
|
+
lyrics_provider_id=str(raw_data.get("id")),
|
295
|
+
is_synced=False, # Genius doesn't provide synced lyrics
|
296
|
+
provider_metadata={
|
297
|
+
"genius_id": raw_data.get("id"),
|
298
|
+
"release_date": release_date,
|
299
|
+
"page_url": raw_data.get("url"),
|
300
|
+
"annotation_count": raw_data.get("annotation_count"),
|
301
|
+
"lyrics_state": raw_data.get("lyrics_state"),
|
302
|
+
"pyongs_count": raw_data.get("pyongs_count"),
|
303
|
+
"external_urls": {"genius": raw_data.get("url")},
|
304
|
+
"api_source": "rapidapi",
|
77
305
|
},
|
78
306
|
)
|
79
307
|
|
@@ -86,6 +314,19 @@ class GeniusProvider(BaseLyricsProvider):
|
|
86
314
|
def _clean_lyrics(self, lyrics: str) -> str:
|
87
315
|
"""Clean and process lyrics from Genius to remove unwanted content."""
|
88
316
|
self.logger.debug("Starting lyrics cleaning process")
|
317
|
+
|
318
|
+
# Handle unexpected input types
|
319
|
+
if not isinstance(lyrics, str):
|
320
|
+
self.logger.warning(f"Expected string for lyrics, got {type(lyrics)}: {repr(lyrics)}")
|
321
|
+
if lyrics is None:
|
322
|
+
return ""
|
323
|
+
# Try to convert to string
|
324
|
+
try:
|
325
|
+
lyrics = str(lyrics)
|
326
|
+
except Exception as e:
|
327
|
+
self.logger.error(f"Failed to convert lyrics to string: {e}")
|
328
|
+
return ""
|
329
|
+
|
89
330
|
original = lyrics
|
90
331
|
|
91
332
|
lyrics = lyrics.replace("\\n", "\n")
|
@@ -123,10 +364,20 @@ class GeniusProvider(BaseLyricsProvider):
|
|
123
364
|
if original != lyrics:
|
124
365
|
self.logger.debug("Removed standalone 'Embed' text")
|
125
366
|
|
367
|
+
# Remove section markers but keep the lyrics content (for non-HTML lyrics)
|
368
|
+
# Instead of removing entire lines, just remove the square bracket markers
|
126
369
|
original = lyrics
|
127
|
-
lyrics = re.sub(r
|
370
|
+
lyrics = re.sub(r'\[Verse \d+\]', '', lyrics)
|
371
|
+
lyrics = re.sub(r'\[Pre-Chorus\]', '', lyrics)
|
372
|
+
lyrics = re.sub(r'\[Chorus\]', '', lyrics)
|
373
|
+
lyrics = re.sub(r'\[Refrain\]', '', lyrics)
|
374
|
+
lyrics = re.sub(r'\[Outro\]', '', lyrics)
|
375
|
+
lyrics = re.sub(r'\[Bridge\]', '', lyrics)
|
376
|
+
lyrics = re.sub(r'\[Intro\]', '', lyrics)
|
128
377
|
if original != lyrics:
|
129
|
-
self.logger.debug("Removed
|
378
|
+
self.logger.debug("Removed section markers while preserving lyrics content")
|
379
|
+
|
380
|
+
# Remove common LyricsGenius page elements
|
130
381
|
|
131
382
|
self.logger.debug("Completed lyrics cleaning process")
|
132
383
|
return lyrics
|
@@ -31,6 +31,7 @@ class VideoGenerator:
|
|
31
31
|
self.output_dir = output_dir
|
32
32
|
self.cache_dir = cache_dir
|
33
33
|
self.video_resolution = video_resolution
|
34
|
+
self.styles = styles
|
34
35
|
self.logger = logger or logging.getLogger(__name__)
|
35
36
|
|
36
37
|
# Get background settings from styles, with defaults
|
@@ -199,6 +200,21 @@ class VideoGenerator:
|
|
199
200
|
self.logger.error(f"Failed to resize background image: {e.output}")
|
200
201
|
raise
|
201
202
|
|
203
|
+
def _build_ass_filter(self, ass_path: str) -> str:
|
204
|
+
"""Build ASS filter with font directory support."""
|
205
|
+
ass_filter = f"ass={ass_path}"
|
206
|
+
|
207
|
+
# Get font path from styles configuration
|
208
|
+
karaoke_styles = self.styles.get("karaoke", {})
|
209
|
+
font_path = karaoke_styles.get("font_path")
|
210
|
+
|
211
|
+
if font_path and os.path.isfile(font_path):
|
212
|
+
font_dir = os.path.dirname(font_path)
|
213
|
+
ass_filter += f":fontsdir={font_dir}"
|
214
|
+
self.logger.info(f"Returning ASS filter with fonts dir: {ass_filter}")
|
215
|
+
|
216
|
+
return ass_filter
|
217
|
+
|
202
218
|
def _build_ffmpeg_command(self, ass_path: str, audio_path: str, output_path: str) -> List[str]:
|
203
219
|
"""Build FFmpeg command for video generation with optimized settings."""
|
204
220
|
width, height = self.video_resolution
|
@@ -230,11 +246,10 @@ class VideoGenerator:
|
|
230
246
|
"-i", f"color=c={self.background_color}:s={width}x{height}:r=30"
|
231
247
|
])
|
232
248
|
|
233
|
-
# Add audio input and subtitle overlay
|
234
249
|
cmd.extend([
|
235
250
|
"-i", audio_path,
|
236
251
|
"-c:a", "flac", # Re-encode audio as FLAC
|
237
|
-
"-vf",
|
252
|
+
"-vf", self._build_ass_filter(ass_path), # Add subtitles with font directories
|
238
253
|
"-c:v", self._get_video_codec(),
|
239
254
|
# Video quality settings
|
240
255
|
"-preset", "fast", # Better compression efficiency
|
@@ -284,12 +299,11 @@ class VideoGenerator:
|
|
284
299
|
"-i", f"color=c={self.background_color}:s={width}x{height}:r=30"
|
285
300
|
])
|
286
301
|
|
287
|
-
# Add audio input and subtitle overlay
|
288
302
|
cmd.extend([
|
289
303
|
"-i", audio_path,
|
290
304
|
"-c:a", "aac", # Use AAC for audio
|
291
305
|
"-b:a", "128k", # Audio bitrate
|
292
|
-
"-vf",
|
306
|
+
"-vf", self._build_ass_filter(ass_path), # Add subtitles with font directories
|
293
307
|
"-c:v", "libx264", # Use H.264 codec
|
294
308
|
"-profile:v", "baseline", # Most compatible H.264 profile
|
295
309
|
"-level", "3.0", # Compatibility level
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: lyrics-transcriber
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.59.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
|
@@ -1,9 +1,9 @@
|
|
1
1
|
lyrics_transcriber/__init__.py,sha256=g9ZbJg9U1qo7XzrC25J3bTKcNzzwUJWDVdi_7-hjcM4,412
|
2
2
|
lyrics_transcriber/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
-
lyrics_transcriber/cli/cli_main.py,sha256=
|
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
|
-
lyrics_transcriber/core/config.py,sha256=
|
6
|
-
lyrics_transcriber/core/controller.py,sha256=
|
5
|
+
lyrics_transcriber/core/config.py,sha256=G4Z5kEBMDXRscEiRKbnofAPuFTDB5h1fLJvwxaHaT4I,1268
|
6
|
+
lyrics_transcriber/core/controller.py,sha256=Hnt2QCiks3xu27NX5-xALxVaZW9lW1jqN0siq2m11ao,20313
|
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=0Ype6MfIJ7iJxzG1KKBiLRYWA6w4s-H6OE9imao7Z34,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
|
@@ -83,14 +83,14 @@ 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-HT4AHF8U.js,sha256=nKbCXqqGWcXcfH9frPnLAqT8LUbQG7IJW79R1juuz0g,1257959
|
87
|
+
lyrics_transcriber/frontend/web_assets/assets/index-HT4AHF8U.js.map,sha256=mIQ6VHnsNXeDQn7aVn_T_KUWhqVcaSK6_NrlRFKDF-o,2678465
|
88
|
+
lyrics_transcriber/frontend/web_assets/index.html,sha256=c7kYw9N3wwGxjIjhOLCObcAkSLMt1Jp8D7RPY6xemlM,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
|
-
lyrics_transcriber/lyrics/base_lyrics_provider.py,sha256=
|
91
|
+
lyrics_transcriber/lyrics/base_lyrics_provider.py,sha256=LCzmwpBFgSfC6VVY5AtJHmE0OvgjAQyjPnL-dYLLwg4,9172
|
92
92
|
lyrics_transcriber/lyrics/file_provider.py,sha256=WNd6mHMV2FhrnHiWBvxUxPkdVi47mbLE4hXaTYqStTM,4290
|
93
|
-
lyrics_transcriber/lyrics/genius.py,sha256=
|
93
|
+
lyrics_transcriber/lyrics/genius.py,sha256=k6Q5B44ry9DpIABy9YPT1r-4dN5cqsvGyZ3TyrbulKM,17022
|
94
94
|
lyrics_transcriber/lyrics/spotify.py,sha256=K7aL_OHdQjhI8ydnHUq8-PUvkyDu2s-et7njiLIBVgY,5457
|
95
95
|
lyrics_transcriber/lyrics/user_input_provider.py,sha256=oNzwjk2bOQYyUXvVqPcbrF8vJU7LLtwTvJTXxtPaQto,1798
|
96
96
|
lyrics_transcriber/output/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -142,7 +142,7 @@ lyrics_transcriber/output/lyrics_file.py,sha256=_KQyQjCOMIwQdQ0115uEAUIjQWTRmShk
|
|
142
142
|
lyrics_transcriber/output/plain_text.py,sha256=XARaWcy6MeQeQCUoz0PV_bHoBw5dba-u79bjS7XucnE,3867
|
143
143
|
lyrics_transcriber/output/segment_resizer.py,sha256=rrgcQC28eExSAmGnm6ytkF-E-nH4Fe3gjvpaCD0MCmA,17510
|
144
144
|
lyrics_transcriber/output/subtitles.py,sha256=yQCR7YO3aitKnGRjfAtSwsdi6byfpEZgnCumJO16M2E,19085
|
145
|
-
lyrics_transcriber/output/video.py,sha256=
|
145
|
+
lyrics_transcriber/output/video.py,sha256=Dk8HGyHti0w9ymubIrFF5fVGAEi6GRpFDg6ifGGE3F8,14361
|
146
146
|
lyrics_transcriber/review/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
147
147
|
lyrics_transcriber/review/server.py,sha256=WXWyJZJsKm6_HhGxRdP2fD7kyMAmuc_I-Kvqx_uA4NI,14833
|
148
148
|
lyrics_transcriber/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -152,8 +152,8 @@ lyrics_transcriber/transcribers/base_transcriber.py,sha256=T3m4ZCwZ9Bpv6Jvb2hNcn
|
|
152
152
|
lyrics_transcriber/transcribers/whisper.py,sha256=YcCB1ic9H6zL1GS0jD0emu8-qlcH0QVEjjjYB4aLlIQ,13260
|
153
153
|
lyrics_transcriber/types.py,sha256=wqFrTKhb8qAUB48zH-51_EEGCGrxm0Ji-ETfQumtSKc,27666
|
154
154
|
lyrics_transcriber/utils/word_utils.py,sha256=-cMGpj9UV4F6IsoDKAV2i1aiqSO8eI91HMAm_igtVMk,958
|
155
|
-
lyrics_transcriber-0.
|
156
|
-
lyrics_transcriber-0.
|
157
|
-
lyrics_transcriber-0.
|
158
|
-
lyrics_transcriber-0.
|
159
|
-
lyrics_transcriber-0.
|
155
|
+
lyrics_transcriber-0.59.0.dist-info/LICENSE,sha256=81R_4XwMZDODHD7JcZeUR8IiCU8AD7Ajl6bmwR9tYDk,1074
|
156
|
+
lyrics_transcriber-0.59.0.dist-info/METADATA,sha256=Qqo8bsJOrzonGfM9jr6Kv-6rWWWHxu7ubTijEMK8CEc,6637
|
157
|
+
lyrics_transcriber-0.59.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
158
|
+
lyrics_transcriber-0.59.0.dist-info/entry_points.txt,sha256=kcp-bSFkCACAEA0t166Kek0HpaJUXRo5SlF5tVrqNBU,216
|
159
|
+
lyrics_transcriber-0.59.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
{lyrics_transcriber-0.57.1.dist-info → lyrics_transcriber-0.59.0.dist-info}/entry_points.txt
RENAMED
File without changes
|