lyrics-transcriber 0.30.1__tar.gz → 0.32.1__tar.gz
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-0.30.1 → lyrics_transcriber-0.32.1}/PKG-INFO +14 -3
- lyrics_transcriber-0.32.1/lyrics_transcriber/__init__.py +4 -0
- {lyrics_transcriber-0.30.1 → lyrics_transcriber-0.32.1}/lyrics_transcriber/cli/cli_main.py +33 -12
- lyrics_transcriber-0.32.1/lyrics_transcriber/core/config.py +35 -0
- {lyrics_transcriber-0.30.1 → lyrics_transcriber-0.32.1}/lyrics_transcriber/core/controller.py +85 -121
- lyrics_transcriber-0.32.1/lyrics_transcriber/correction/anchor_sequence.py +471 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/correction/corrector.py +256 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/correction/handlers/base.py +30 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/correction/handlers/extend_anchor.py +91 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/correction/handlers/levenshtein.py +147 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/correction/handlers/no_space_punct_match.py +98 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/correction/handlers/relaxed_word_count_match.py +55 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/correction/handlers/repeat.py +71 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/correction/handlers/sound_alike.py +223 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/correction/handlers/syllables_match.py +182 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/correction/handlers/word_count_match.py +54 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/correction/handlers/word_operations.py +135 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/correction/phrase_analyzer.py +426 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/correction/text_utils.py +30 -0
- {lyrics_transcriber-0.30.1 → lyrics_transcriber-0.32.1}/lyrics_transcriber/lyrics/base_lyrics_provider.py +5 -81
- {lyrics_transcriber-0.30.1 → lyrics_transcriber-0.32.1}/lyrics_transcriber/lyrics/genius.py +5 -2
- {lyrics_transcriber-0.30.1 → lyrics_transcriber-0.32.1}/lyrics_transcriber/lyrics/spotify.py +3 -3
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/ass/__init__.py +21 -0
- {lyrics_transcriber-0.30.1/lyrics_transcriber/output → lyrics_transcriber-0.32.1/lyrics_transcriber/output/ass}/ass.py +150 -690
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/ass/ass_specs.txt +732 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/ass/config.py +37 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/ass/constants.py +23 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/ass/event.py +94 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/ass/formatters.py +132 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/ass/lyrics_line.py +219 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/ass/lyrics_screen.py +252 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/ass/section_detector.py +89 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/ass/section_screen.py +106 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/ass/style.py +187 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdg.py +503 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/__init__.py +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/cdg.py +262 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/composer.py +1919 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/config.py +151 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/images/instrumental.png +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/images/intro.png +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/pack.py +507 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/render.py +346 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/transitions/centertexttoplogobottomtext.png +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/transitions/circlein.png +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/transitions/circleout.png +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/transitions/fizzle.png +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/transitions/largecentertexttoplogo.png +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/transitions/rectangle.png +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/transitions/spiral.png +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/transitions/topleftmusicalnotes.png +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/transitions/wipein.png +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/transitions/wipeleft.png +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/transitions/wipeout.png +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/transitions/wiperight.png +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/cdgmaker/utils.py +132 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/fonts/AvenirNext-Bold.ttf +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/fonts/DMSans-VariableFont_opsz,wght.ttf +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/fonts/DMSerifDisplay-Regular.ttf +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/fonts/Oswald-SemiBold.ttf +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/fonts/Zurich_Cn_BT_Bold.ttf +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/fonts/arial.ttf +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/fonts/georgia.ttf +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/fonts/verdana.ttf +0 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/generator.py +179 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/lyrics_file.py +102 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/plain_text.py +91 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/segment_resizer.py +416 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/subtitles.py +331 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/output/video.py +219 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/review/__init__.py +1 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/review/server.py +138 -0
- lyrics_transcriber-0.32.1/lyrics_transcriber/storage/__init__.py +0 -0
- {lyrics_transcriber-0.30.1 → lyrics_transcriber-0.32.1}/lyrics_transcriber/transcribers/audioshake.py +3 -2
- {lyrics_transcriber-0.30.1 → lyrics_transcriber-0.32.1}/lyrics_transcriber/transcribers/base_transcriber.py +5 -42
- {lyrics_transcriber-0.30.1 → lyrics_transcriber-0.32.1}/lyrics_transcriber/transcribers/whisper.py +3 -4
- lyrics_transcriber-0.32.1/lyrics_transcriber/types.py +454 -0
- {lyrics_transcriber-0.30.1 → lyrics_transcriber-0.32.1}/pyproject.toml +13 -2
- lyrics_transcriber-0.30.1/lyrics_transcriber/__init__.py +0 -3
- lyrics_transcriber-0.30.1/lyrics_transcriber/correction/base_strategy.py +0 -29
- lyrics_transcriber-0.30.1/lyrics_transcriber/correction/corrector.py +0 -52
- lyrics_transcriber-0.30.1/lyrics_transcriber/correction/strategy_diff.py +0 -263
- lyrics_transcriber-0.30.1/lyrics_transcriber/output/generator.py +0 -271
- lyrics_transcriber-0.30.1/lyrics_transcriber/output/subtitles.py +0 -305
- {lyrics_transcriber-0.30.1 → lyrics_transcriber-0.32.1}/LICENSE +0 -0
- {lyrics_transcriber-0.30.1 → lyrics_transcriber-0.32.1}/README.md +0 -0
- {lyrics_transcriber-0.30.1 → lyrics_transcriber-0.32.1}/lyrics_transcriber/cli/__init__.py +0 -0
- {lyrics_transcriber-0.30.1 → lyrics_transcriber-0.32.1}/lyrics_transcriber/core/__init__.py +0 -0
- {lyrics_transcriber-0.30.1/lyrics_transcriber/output → lyrics_transcriber-0.32.1/lyrics_transcriber/correction/handlers}/__init__.py +0 -0
- {lyrics_transcriber-0.30.1/lyrics_transcriber/storage → lyrics_transcriber-0.32.1/lyrics_transcriber/output}/__init__.py +0 -0
- {lyrics_transcriber-0.30.1 → lyrics_transcriber-0.32.1}/lyrics_transcriber/storage/dropbox.py +0 -0
@@ -1,8 +1,7 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.3
|
2
2
|
Name: lyrics-transcriber
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.32.1
|
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
|
-
Home-page: https://github.com/karaokenerds/python-lyrics-transcriber
|
6
5
|
License: MIT
|
7
6
|
Author: Andrew Beveridge
|
8
7
|
Author-email: andrew@beveridge.uk
|
@@ -14,13 +13,25 @@ Classifier: Programming Language :: Python :: 3.10
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.11
|
15
14
|
Classifier: Programming Language :: Python :: 3.12
|
16
15
|
Requires-Dist: dropbox (>=12)
|
16
|
+
Requires-Dist: fastapi (>=0.115.6,<0.116.0)
|
17
17
|
Requires-Dist: karaoke-lyrics-processor (>=0.4)
|
18
18
|
Requires-Dist: lyricsgenius (>=3)
|
19
|
+
Requires-Dist: metaphone (>=0.6,<0.7)
|
20
|
+
Requires-Dist: nltk (>=3.9.1,<4.0.0)
|
19
21
|
Requires-Dist: pydub (>=0.25)
|
20
22
|
Requires-Dist: python-dotenv (>=1)
|
23
|
+
Requires-Dist: python-levenshtein (>=0.26.1,<0.27.0)
|
21
24
|
Requires-Dist: python-slugify (>=8)
|
25
|
+
Requires-Dist: spacy (>=3.8.3,<4.0.0)
|
26
|
+
Requires-Dist: spacy-syllables (>=3.0.2,<4.0.0)
|
27
|
+
Requires-Dist: syllables (>=1.0.9,<2.0.0)
|
22
28
|
Requires-Dist: syrics (>=0)
|
29
|
+
Requires-Dist: torch (>=2.5.1,<3.0.0)
|
30
|
+
Requires-Dist: tqdm (>=4.67.1,<5.0.0)
|
31
|
+
Requires-Dist: transformers (>=4.47.1,<5.0.0)
|
32
|
+
Requires-Dist: uvicorn (>=0.34.0,<0.35.0)
|
23
33
|
Project-URL: Documentation, https://github.com/karaokenerds/python-lyrics-transcriber/blob/main/README.md
|
34
|
+
Project-URL: Homepage, https://github.com/karaokenerds/python-lyrics-transcriber
|
24
35
|
Project-URL: Repository, https://github.com/karaokenerds/python-lyrics-transcriber
|
25
36
|
Description-Content-Type: text/markdown
|
26
37
|
|
@@ -57,12 +57,17 @@ def create_arg_parser() -> argparse.ArgumentParser:
|
|
57
57
|
# Output options
|
58
58
|
output_group = parser.add_argument_group("Output Options")
|
59
59
|
output_group.add_argument("--output_dir", type=Path, help="Directory where output files will be saved. Default: current directory")
|
60
|
-
|
61
60
|
output_group.add_argument(
|
62
61
|
"--cache_dir",
|
63
62
|
type=Path,
|
64
63
|
help="Directory to cache downloaded/generated files. Default: /tmp/lyrics-transcriber-cache/",
|
65
64
|
)
|
65
|
+
output_group.add_argument(
|
66
|
+
"--output_styles_json",
|
67
|
+
type=Path,
|
68
|
+
help="JSON file containing output style configurations for CDG and video generation",
|
69
|
+
)
|
70
|
+
output_group.add_argument("--generate_cdg", action="store_true", help="Generate CDG karaoke files")
|
66
71
|
|
67
72
|
# Video options
|
68
73
|
video_group = parser.add_argument_group("Video Options")
|
@@ -70,12 +75,6 @@ def create_arg_parser() -> argparse.ArgumentParser:
|
|
70
75
|
video_group.add_argument(
|
71
76
|
"--video_resolution", choices=["4k", "1080p", "720p", "360p"], default="360p", help="Resolution of the karaoke video. Default: 360p"
|
72
77
|
)
|
73
|
-
video_group.add_argument("--video_background_image", type=Path, help="Image file to use for karaoke video background")
|
74
|
-
video_group.add_argument(
|
75
|
-
"--video_background_color",
|
76
|
-
default="black",
|
77
|
-
help="Color for karaoke video background (hex format or FFmpeg color name). Default: black",
|
78
|
-
)
|
79
78
|
|
80
79
|
return parser
|
81
80
|
|
@@ -133,12 +132,12 @@ def create_configs(args: argparse.Namespace, env_config: Dict[str, str]) -> tupl
|
|
133
132
|
)
|
134
133
|
|
135
134
|
output_config = OutputConfig(
|
135
|
+
output_styles_json=str(args.output_styles_json),
|
136
136
|
output_dir=str(args.output_dir) if args.output_dir else os.getcwd(),
|
137
137
|
cache_dir=str(args.cache_dir),
|
138
138
|
render_video=args.render_video,
|
139
|
+
generate_cdg=args.generate_cdg,
|
139
140
|
video_resolution=args.video_resolution,
|
140
|
-
video_background_image=str(args.video_background_image) if args.video_background_image else None,
|
141
|
-
video_background_color=args.video_background_color,
|
142
141
|
)
|
143
142
|
|
144
143
|
return transcriber_config, lyrics_config, output_config
|
@@ -194,13 +193,35 @@ def main() -> None:
|
|
194
193
|
# Log results
|
195
194
|
logger.info("*** Success! ***")
|
196
195
|
|
196
|
+
# Log all generated output files
|
197
|
+
if results.original_txt:
|
198
|
+
logger.info(f"Generated original transcription: {results.original_txt}")
|
199
|
+
if results.corrections_json:
|
200
|
+
logger.info(f"Generated corrections data: {results.corrections_json}")
|
201
|
+
|
202
|
+
if results.corrected_txt:
|
203
|
+
logger.info(f"Generated corrected lyrics: {results.corrected_txt}")
|
197
204
|
if results.lrc_filepath:
|
198
205
|
logger.info(f"Generated LRC file: {results.lrc_filepath}")
|
206
|
+
|
207
|
+
if results.cdg_filepath:
|
208
|
+
logger.info(f"Generated CDG file: {results.cdg_filepath}")
|
209
|
+
if results.mp3_filepath:
|
210
|
+
logger.info(f"Generated MP3 file: {results.mp3_filepath}")
|
211
|
+
if results.cdg_zip_filepath:
|
212
|
+
logger.info(f"Generated CDG ZIP archive: {results.cdg_zip_filepath}")
|
213
|
+
|
199
214
|
if results.ass_filepath:
|
200
|
-
logger.info(f"Generated ASS
|
215
|
+
logger.info(f"Generated ASS subtitles: {results.ass_filepath}")
|
201
216
|
if results.video_filepath:
|
202
|
-
logger.info(f"Generated video
|
217
|
+
logger.info(f"Generated video: {results.video_filepath}")
|
203
218
|
|
204
219
|
except Exception as e:
|
205
|
-
|
220
|
+
# Get the full exception traceback
|
221
|
+
import traceback
|
222
|
+
|
223
|
+
error_details = traceback.format_exc()
|
224
|
+
|
225
|
+
# Log both the error message and the full traceback
|
226
|
+
logger.error(f"Processing failed: {str(e)}\n\nFull traceback:\n{error_details}")
|
206
227
|
exit(1)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import os
|
2
|
+
from dataclasses import dataclass, field
|
3
|
+
from typing import Any, Dict, Optional
|
4
|
+
|
5
|
+
|
6
|
+
@dataclass
|
7
|
+
class TranscriberConfig:
|
8
|
+
"""Configuration for transcription services."""
|
9
|
+
|
10
|
+
audioshake_api_token: Optional[str] = None
|
11
|
+
runpod_api_key: Optional[str] = None
|
12
|
+
whisper_runpod_id: Optional[str] = None
|
13
|
+
|
14
|
+
|
15
|
+
@dataclass
|
16
|
+
class LyricsConfig:
|
17
|
+
"""Configuration for lyrics services."""
|
18
|
+
|
19
|
+
genius_api_token: Optional[str] = None
|
20
|
+
spotify_cookie: Optional[str] = None
|
21
|
+
|
22
|
+
|
23
|
+
@dataclass
|
24
|
+
class OutputConfig:
|
25
|
+
"""Configuration for output generation."""
|
26
|
+
|
27
|
+
output_styles_json: str
|
28
|
+
max_line_length: int = 36
|
29
|
+
styles: Dict[str, Any] = field(default_factory=dict)
|
30
|
+
output_dir: Optional[str] = os.getcwd()
|
31
|
+
cache_dir: str = os.getenv("LYRICS_TRANSCRIBER_CACHE_DIR", "/tmp/lyrics-transcriber-cache/")
|
32
|
+
render_video: bool = False
|
33
|
+
generate_cdg: bool = False
|
34
|
+
video_resolution: str = "360p"
|
35
|
+
enable_review: bool = True
|
{lyrics_transcriber-0.30.1 → lyrics_transcriber-0.32.1}/lyrics_transcriber/core/controller.py
RENAMED
@@ -1,44 +1,21 @@
|
|
1
1
|
import os
|
2
2
|
import logging
|
3
3
|
from dataclasses import dataclass, field
|
4
|
-
from typing import Dict, Optional,
|
5
|
-
from
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
from
|
11
|
-
from
|
12
|
-
from
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
audioshake_api_token: Optional[str] = None
|
20
|
-
runpod_api_key: Optional[str] = None
|
21
|
-
whisper_runpod_id: Optional[str] = None
|
22
|
-
|
23
|
-
|
24
|
-
@dataclass
|
25
|
-
class LyricsConfig:
|
26
|
-
"""Configuration for lyrics services."""
|
27
|
-
|
28
|
-
genius_api_token: Optional[str] = None
|
29
|
-
spotify_cookie: Optional[str] = None
|
30
|
-
|
31
|
-
|
32
|
-
@dataclass
|
33
|
-
class OutputConfig:
|
34
|
-
"""Configuration for output generation."""
|
35
|
-
|
36
|
-
output_dir: Optional[str] = os.getcwd()
|
37
|
-
cache_dir: str = os.getenv("LYRICS_TRANSCRIBER_CACHE_DIR", "/tmp/lyrics-transcriber-cache/")
|
38
|
-
render_video: bool = False
|
39
|
-
video_resolution: str = "360p"
|
40
|
-
video_background_image: Optional[str] = None
|
41
|
-
video_background_color: str = "black"
|
4
|
+
from typing import Dict, Optional, List
|
5
|
+
from lyrics_transcriber.types import (
|
6
|
+
LyricsData,
|
7
|
+
TranscriptionResult,
|
8
|
+
CorrectionResult,
|
9
|
+
)
|
10
|
+
from lyrics_transcriber.transcribers.base_transcriber import BaseTranscriber
|
11
|
+
from lyrics_transcriber.transcribers.audioshake import AudioShakeTranscriber, AudioShakeConfig
|
12
|
+
from lyrics_transcriber.transcribers.whisper import WhisperTranscriber, WhisperConfig
|
13
|
+
from lyrics_transcriber.lyrics.base_lyrics_provider import BaseLyricsProvider, LyricsProviderConfig
|
14
|
+
from lyrics_transcriber.lyrics.genius import GeniusProvider
|
15
|
+
from lyrics_transcriber.lyrics.spotify import SpotifyProvider
|
16
|
+
from lyrics_transcriber.output.generator import OutputGenerator
|
17
|
+
from lyrics_transcriber.correction.corrector import LyricsCorrector
|
18
|
+
from lyrics_transcriber.core.config import TranscriberConfig, LyricsConfig, OutputConfig
|
42
19
|
|
43
20
|
|
44
21
|
@dataclass
|
@@ -56,6 +33,12 @@ class LyricsControllerResult:
|
|
56
33
|
lrc_filepath: Optional[str] = None
|
57
34
|
ass_filepath: Optional[str] = None
|
58
35
|
video_filepath: Optional[str] = None
|
36
|
+
mp3_filepath: Optional[str] = None
|
37
|
+
cdg_filepath: Optional[str] = None
|
38
|
+
cdg_zip_filepath: Optional[str] = None
|
39
|
+
original_txt: Optional[str] = None
|
40
|
+
corrected_txt: Optional[str] = None
|
41
|
+
corrections_json: Optional[str] = None
|
59
42
|
|
60
43
|
|
61
44
|
class LyricsTranscriber:
|
@@ -120,7 +103,7 @@ class LyricsTranscriber:
|
|
120
103
|
# Initialize components (with dependency injection)
|
121
104
|
self.transcribers = transcribers or self._initialize_transcribers()
|
122
105
|
self.lyrics_providers = lyrics_providers or self._initialize_lyrics_providers()
|
123
|
-
self.corrector = corrector or LyricsCorrector(logger=self.logger)
|
106
|
+
self.corrector = corrector or LyricsCorrector(cache_dir=self.output_config.cache_dir, logger=self.logger)
|
124
107
|
self.output_generator = output_generator or self._initialize_output_generator()
|
125
108
|
|
126
109
|
def _initialize_transcribers(self) -> Dict[str, BaseTranscriber]:
|
@@ -189,18 +172,7 @@ class LyricsTranscriber:
|
|
189
172
|
|
190
173
|
def _initialize_output_generator(self) -> OutputGenerator:
|
191
174
|
"""Initialize output generation service."""
|
192
|
-
|
193
|
-
# Convert OutputConfig to OutputGeneratorConfig
|
194
|
-
generator_config = OutputGeneratorConfig(
|
195
|
-
output_dir=self.output_config.output_dir,
|
196
|
-
cache_dir=self.output_config.cache_dir,
|
197
|
-
video_resolution=self.output_config.video_resolution,
|
198
|
-
video_background_image=self.output_config.video_background_image,
|
199
|
-
video_background_color=self.output_config.video_background_color,
|
200
|
-
)
|
201
|
-
|
202
|
-
# Initialize output generator
|
203
|
-
return OutputGenerator(config=generator_config, logger=self.logger)
|
175
|
+
return OutputGenerator(config=self.output_config, logger=self.logger)
|
204
176
|
|
205
177
|
def process(self) -> LyricsControllerResult:
|
206
178
|
"""
|
@@ -212,49 +184,39 @@ class LyricsTranscriber:
|
|
212
184
|
Raises:
|
213
185
|
Exception: If a critical error occurs during processing.
|
214
186
|
"""
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
self.fetch_lyrics()
|
187
|
+
# Step 1: Fetch lyrics if artist and title are provided
|
188
|
+
if self.artist and self.title:
|
189
|
+
self.fetch_lyrics()
|
219
190
|
|
220
|
-
|
221
|
-
|
191
|
+
# Step 2: Run transcription
|
192
|
+
self.transcribe()
|
222
193
|
|
223
|
-
|
224
|
-
|
194
|
+
# Step 3: Process and correct lyrics
|
195
|
+
self.correct_lyrics()
|
225
196
|
|
226
|
-
|
227
|
-
|
197
|
+
# Step 4: Generate outputs
|
198
|
+
self.generate_outputs()
|
228
199
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
except Exception as e:
|
233
|
-
self.logger.error(f"Error during processing: {str(e)}")
|
234
|
-
raise
|
200
|
+
self.logger.info("Processing completed successfully")
|
201
|
+
return self.results
|
235
202
|
|
236
203
|
def fetch_lyrics(self) -> None:
|
237
204
|
"""Fetch lyrics from available providers."""
|
238
205
|
self.logger.info(f"Fetching lyrics for {self.artist} - {self.title}")
|
239
206
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
self.logger.info(f"Successfully fetched lyrics from {name}")
|
247
|
-
|
248
|
-
except Exception as e:
|
249
|
-
self.logger.error(f"Failed to fetch lyrics from {name}: {str(e)}")
|
250
|
-
continue
|
207
|
+
for name, provider in self.lyrics_providers.items():
|
208
|
+
try:
|
209
|
+
result = provider.fetch_lyrics(self.artist, self.title)
|
210
|
+
if result:
|
211
|
+
self.results.lyrics_results.append(result)
|
212
|
+
self.logger.info(f"Successfully fetched lyrics from {name}")
|
251
213
|
|
252
|
-
|
253
|
-
self.logger.
|
214
|
+
except Exception as e:
|
215
|
+
self.logger.error(f"Failed to fetch lyrics from {name}: {str(e)}")
|
216
|
+
continue
|
254
217
|
|
255
|
-
|
256
|
-
self.logger.
|
257
|
-
# Don't raise - we can continue without lyrics
|
218
|
+
if not self.results.lyrics_results:
|
219
|
+
self.logger.warning("No lyrics found from any source")
|
258
220
|
|
259
221
|
def transcribe(self) -> None:
|
260
222
|
"""Run transcription using all available transcribers."""
|
@@ -262,18 +224,13 @@ class LyricsTranscriber:
|
|
262
224
|
|
263
225
|
for name, transcriber_info in self.transcribers.items():
|
264
226
|
self.logger.info(f"Running transcription with {name}")
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
self.logger.debug(f"Transcription completed for {name}")
|
273
|
-
|
274
|
-
except Exception as e:
|
275
|
-
self.logger.error(f"Transcription failed for {name}: {str(e)}", exc_info=True)
|
276
|
-
continue
|
227
|
+
result = transcriber_info["instance"].transcribe(self.audio_filepath)
|
228
|
+
if result:
|
229
|
+
# Add the transcriber name and priority to the result
|
230
|
+
self.results.transcription_results.append(
|
231
|
+
TranscriptionResult(name=name, priority=transcriber_info["priority"], result=result)
|
232
|
+
)
|
233
|
+
self.logger.debug(f"Transcription completed for {name}")
|
277
234
|
|
278
235
|
if not self.results.transcription_results:
|
279
236
|
self.logger.warning("No successful transcriptions from any provider")
|
@@ -282,36 +239,43 @@ class LyricsTranscriber:
|
|
282
239
|
"""Run lyrics correction using transcription and internet lyrics."""
|
283
240
|
self.logger.info("Starting lyrics correction process")
|
284
241
|
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
242
|
+
# Run correction
|
243
|
+
corrected_data = self.corrector.run(
|
244
|
+
transcription_results=self.results.transcription_results, lyrics_results=self.results.lyrics_results
|
245
|
+
)
|
246
|
+
|
247
|
+
# Store corrected results
|
248
|
+
self.results.transcription_corrected = corrected_data
|
249
|
+
self.logger.info("Lyrics correction completed")
|
290
250
|
|
291
|
-
|
292
|
-
|
293
|
-
|
251
|
+
# Add human review step
|
252
|
+
if self.output_config.enable_review: # We'll need to add this config option
|
253
|
+
from ..review import start_review_server
|
294
254
|
|
295
|
-
|
296
|
-
self.
|
255
|
+
self.logger.info("Starting human review process")
|
256
|
+
self.results.transcription_corrected = start_review_server(corrected_data)
|
257
|
+
self.logger.info("Human review completed")
|
297
258
|
|
298
259
|
def generate_outputs(self) -> None:
|
299
260
|
"""Generate output files."""
|
300
261
|
self.logger.info("Generating output files")
|
301
262
|
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
263
|
+
output_files = self.output_generator.generate_outputs(
|
264
|
+
transcription_corrected=self.results.transcription_corrected,
|
265
|
+
lyrics_results=self.results.lyrics_results,
|
266
|
+
output_prefix=self.output_prefix,
|
267
|
+
audio_filepath=self.audio_filepath,
|
268
|
+
artist=self.artist,
|
269
|
+
title=self.title,
|
270
|
+
)
|
271
|
+
|
272
|
+
# Store all output paths in results
|
273
|
+
self.results.lrc_filepath = output_files.lrc
|
274
|
+
self.results.ass_filepath = output_files.ass
|
275
|
+
self.results.video_filepath = output_files.video
|
276
|
+
self.results.original_txt = output_files.original_txt
|
277
|
+
self.results.corrected_txt = output_files.corrected_txt
|
278
|
+
self.results.corrections_json = output_files.corrections_json
|
279
|
+
self.results.cdg_filepath = output_files.cdg
|
280
|
+
self.results.mp3_filepath = output_files.mp3
|
281
|
+
self.results.cdg_zip_filepath = output_files.cdg_zip
|