karaoke-gen 0.90.1__py3-none-any.whl → 0.99.3__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.
Files changed (197) hide show
  1. backend/.coveragerc +20 -0
  2. backend/.gitignore +37 -0
  3. backend/Dockerfile +43 -0
  4. backend/Dockerfile.base +74 -0
  5. backend/README.md +242 -0
  6. backend/__init__.py +0 -0
  7. backend/api/__init__.py +0 -0
  8. backend/api/dependencies.py +457 -0
  9. backend/api/routes/__init__.py +0 -0
  10. backend/api/routes/admin.py +835 -0
  11. backend/api/routes/audio_search.py +913 -0
  12. backend/api/routes/auth.py +348 -0
  13. backend/api/routes/file_upload.py +2112 -0
  14. backend/api/routes/health.py +409 -0
  15. backend/api/routes/internal.py +435 -0
  16. backend/api/routes/jobs.py +1629 -0
  17. backend/api/routes/review.py +652 -0
  18. backend/api/routes/themes.py +162 -0
  19. backend/api/routes/users.py +1513 -0
  20. backend/config.py +172 -0
  21. backend/main.py +157 -0
  22. backend/middleware/__init__.py +5 -0
  23. backend/middleware/audit_logging.py +124 -0
  24. backend/models/__init__.py +0 -0
  25. backend/models/job.py +519 -0
  26. backend/models/requests.py +123 -0
  27. backend/models/theme.py +153 -0
  28. backend/models/user.py +254 -0
  29. backend/models/worker_log.py +164 -0
  30. backend/pyproject.toml +29 -0
  31. backend/quick-check.sh +93 -0
  32. backend/requirements.txt +29 -0
  33. backend/run_tests.sh +60 -0
  34. backend/services/__init__.py +0 -0
  35. backend/services/audio_analysis_service.py +243 -0
  36. backend/services/audio_editing_service.py +278 -0
  37. backend/services/audio_search_service.py +702 -0
  38. backend/services/auth_service.py +630 -0
  39. backend/services/credential_manager.py +792 -0
  40. backend/services/discord_service.py +172 -0
  41. backend/services/dropbox_service.py +301 -0
  42. backend/services/email_service.py +1093 -0
  43. backend/services/encoding_interface.py +454 -0
  44. backend/services/encoding_service.py +502 -0
  45. backend/services/firestore_service.py +512 -0
  46. backend/services/flacfetch_client.py +573 -0
  47. backend/services/gce_encoding/README.md +72 -0
  48. backend/services/gce_encoding/__init__.py +22 -0
  49. backend/services/gce_encoding/main.py +589 -0
  50. backend/services/gce_encoding/requirements.txt +16 -0
  51. backend/services/gdrive_service.py +356 -0
  52. backend/services/job_logging.py +258 -0
  53. backend/services/job_manager.py +853 -0
  54. backend/services/job_notification_service.py +271 -0
  55. backend/services/langfuse_preloader.py +98 -0
  56. backend/services/local_encoding_service.py +590 -0
  57. backend/services/local_preview_encoding_service.py +407 -0
  58. backend/services/lyrics_cache_service.py +216 -0
  59. backend/services/metrics.py +413 -0
  60. backend/services/nltk_preloader.py +122 -0
  61. backend/services/packaging_service.py +287 -0
  62. backend/services/rclone_service.py +106 -0
  63. backend/services/spacy_preloader.py +65 -0
  64. backend/services/storage_service.py +209 -0
  65. backend/services/stripe_service.py +371 -0
  66. backend/services/structured_logging.py +254 -0
  67. backend/services/template_service.py +330 -0
  68. backend/services/theme_service.py +469 -0
  69. backend/services/tracing.py +543 -0
  70. backend/services/user_service.py +721 -0
  71. backend/services/worker_service.py +558 -0
  72. backend/services/youtube_service.py +112 -0
  73. backend/services/youtube_upload_service.py +445 -0
  74. backend/tests/__init__.py +4 -0
  75. backend/tests/conftest.py +224 -0
  76. backend/tests/emulator/__init__.py +7 -0
  77. backend/tests/emulator/conftest.py +109 -0
  78. backend/tests/emulator/test_e2e_cli_backend.py +1053 -0
  79. backend/tests/emulator/test_emulator_integration.py +356 -0
  80. backend/tests/emulator/test_style_loading_direct.py +436 -0
  81. backend/tests/emulator/test_worker_logs_direct.py +229 -0
  82. backend/tests/emulator/test_worker_logs_subcollection.py +443 -0
  83. backend/tests/requirements-test.txt +10 -0
  84. backend/tests/requirements.txt +6 -0
  85. backend/tests/test_admin_email_endpoints.py +411 -0
  86. backend/tests/test_api_integration.py +460 -0
  87. backend/tests/test_api_routes.py +93 -0
  88. backend/tests/test_audio_analysis_service.py +294 -0
  89. backend/tests/test_audio_editing_service.py +386 -0
  90. backend/tests/test_audio_search.py +1398 -0
  91. backend/tests/test_audio_services.py +378 -0
  92. backend/tests/test_auth_firestore.py +231 -0
  93. backend/tests/test_config_extended.py +68 -0
  94. backend/tests/test_credential_manager.py +377 -0
  95. backend/tests/test_dependencies.py +54 -0
  96. backend/tests/test_discord_service.py +244 -0
  97. backend/tests/test_distribution_services.py +820 -0
  98. backend/tests/test_dropbox_service.py +472 -0
  99. backend/tests/test_email_service.py +492 -0
  100. backend/tests/test_emulator_integration.py +322 -0
  101. backend/tests/test_encoding_interface.py +412 -0
  102. backend/tests/test_file_upload.py +1739 -0
  103. backend/tests/test_flacfetch_client.py +632 -0
  104. backend/tests/test_gdrive_service.py +524 -0
  105. backend/tests/test_instrumental_api.py +431 -0
  106. backend/tests/test_internal_api.py +343 -0
  107. backend/tests/test_job_creation_regression.py +583 -0
  108. backend/tests/test_job_manager.py +356 -0
  109. backend/tests/test_job_manager_notifications.py +329 -0
  110. backend/tests/test_job_notification_service.py +443 -0
  111. backend/tests/test_jobs_api.py +283 -0
  112. backend/tests/test_local_encoding_service.py +423 -0
  113. backend/tests/test_local_preview_encoding_service.py +567 -0
  114. backend/tests/test_main.py +87 -0
  115. backend/tests/test_models.py +918 -0
  116. backend/tests/test_packaging_service.py +382 -0
  117. backend/tests/test_requests.py +201 -0
  118. backend/tests/test_routes_jobs.py +282 -0
  119. backend/tests/test_routes_review.py +337 -0
  120. backend/tests/test_services.py +556 -0
  121. backend/tests/test_services_extended.py +112 -0
  122. backend/tests/test_spacy_preloader.py +119 -0
  123. backend/tests/test_storage_service.py +448 -0
  124. backend/tests/test_style_upload.py +261 -0
  125. backend/tests/test_template_service.py +295 -0
  126. backend/tests/test_theme_service.py +516 -0
  127. backend/tests/test_unicode_sanitization.py +522 -0
  128. backend/tests/test_upload_api.py +256 -0
  129. backend/tests/test_validate.py +156 -0
  130. backend/tests/test_video_worker_orchestrator.py +847 -0
  131. backend/tests/test_worker_log_subcollection.py +509 -0
  132. backend/tests/test_worker_logging.py +365 -0
  133. backend/tests/test_workers.py +1116 -0
  134. backend/tests/test_workers_extended.py +178 -0
  135. backend/tests/test_youtube_service.py +247 -0
  136. backend/tests/test_youtube_upload_service.py +568 -0
  137. backend/utils/test_data.py +27 -0
  138. backend/validate.py +173 -0
  139. backend/version.py +27 -0
  140. backend/workers/README.md +597 -0
  141. backend/workers/__init__.py +11 -0
  142. backend/workers/audio_worker.py +618 -0
  143. backend/workers/lyrics_worker.py +683 -0
  144. backend/workers/render_video_worker.py +483 -0
  145. backend/workers/screens_worker.py +535 -0
  146. backend/workers/style_helper.py +198 -0
  147. backend/workers/video_worker.py +1277 -0
  148. backend/workers/video_worker_orchestrator.py +701 -0
  149. backend/workers/worker_logging.py +278 -0
  150. karaoke_gen/instrumental_review/static/index.html +7 -4
  151. karaoke_gen/karaoke_finalise/karaoke_finalise.py +6 -1
  152. karaoke_gen/utils/__init__.py +163 -8
  153. karaoke_gen/video_background_processor.py +9 -4
  154. {karaoke_gen-0.90.1.dist-info → karaoke_gen-0.99.3.dist-info}/METADATA +1 -1
  155. {karaoke_gen-0.90.1.dist-info → karaoke_gen-0.99.3.dist-info}/RECORD +196 -46
  156. lyrics_transcriber/correction/agentic/agent.py +17 -6
  157. lyrics_transcriber/correction/agentic/providers/config.py +9 -5
  158. lyrics_transcriber/correction/agentic/providers/langchain_bridge.py +96 -93
  159. lyrics_transcriber/correction/agentic/providers/model_factory.py +27 -6
  160. lyrics_transcriber/correction/anchor_sequence.py +151 -37
  161. lyrics_transcriber/correction/corrector.py +192 -130
  162. lyrics_transcriber/correction/handlers/syllables_match.py +44 -2
  163. lyrics_transcriber/correction/operations.py +24 -9
  164. lyrics_transcriber/correction/phrase_analyzer.py +18 -0
  165. lyrics_transcriber/frontend/package-lock.json +2 -2
  166. lyrics_transcriber/frontend/package.json +1 -1
  167. lyrics_transcriber/frontend/src/components/AIFeedbackModal.tsx +1 -1
  168. lyrics_transcriber/frontend/src/components/CorrectedWordWithActions.tsx +11 -7
  169. lyrics_transcriber/frontend/src/components/EditActionBar.tsx +31 -5
  170. lyrics_transcriber/frontend/src/components/EditModal.tsx +28 -10
  171. lyrics_transcriber/frontend/src/components/EditTimelineSection.tsx +123 -27
  172. lyrics_transcriber/frontend/src/components/EditWordList.tsx +112 -60
  173. lyrics_transcriber/frontend/src/components/Header.tsx +90 -76
  174. lyrics_transcriber/frontend/src/components/LyricsAnalyzer.tsx +53 -31
  175. lyrics_transcriber/frontend/src/components/LyricsSynchronizer/SyncControls.tsx +44 -13
  176. lyrics_transcriber/frontend/src/components/LyricsSynchronizer/TimelineCanvas.tsx +66 -50
  177. lyrics_transcriber/frontend/src/components/LyricsSynchronizer/index.tsx +124 -30
  178. lyrics_transcriber/frontend/src/components/ReferenceView.tsx +1 -1
  179. lyrics_transcriber/frontend/src/components/TimelineEditor.tsx +12 -5
  180. lyrics_transcriber/frontend/src/components/TimingOffsetModal.tsx +3 -3
  181. lyrics_transcriber/frontend/src/components/TranscriptionView.tsx +1 -1
  182. lyrics_transcriber/frontend/src/components/WordDivider.tsx +11 -7
  183. lyrics_transcriber/frontend/src/components/shared/components/Word.tsx +4 -2
  184. lyrics_transcriber/frontend/src/hooks/useManualSync.ts +103 -1
  185. lyrics_transcriber/frontend/src/theme.ts +42 -15
  186. lyrics_transcriber/frontend/tsconfig.tsbuildinfo +1 -1
  187. lyrics_transcriber/frontend/vite.config.js +5 -0
  188. lyrics_transcriber/frontend/web_assets/assets/{index-BECn1o8Q.js → index-BSMgOq4Z.js} +6959 -5782
  189. lyrics_transcriber/frontend/web_assets/assets/index-BSMgOq4Z.js.map +1 -0
  190. lyrics_transcriber/frontend/web_assets/index.html +6 -2
  191. lyrics_transcriber/frontend/web_assets/nomad-karaoke-logo.svg +5 -0
  192. lyrics_transcriber/output/generator.py +17 -3
  193. lyrics_transcriber/output/video.py +60 -95
  194. lyrics_transcriber/frontend/web_assets/assets/index-BECn1o8Q.js.map +0 -1
  195. {karaoke_gen-0.90.1.dist-info → karaoke_gen-0.99.3.dist-info}/WHEEL +0 -0
  196. {karaoke_gen-0.90.1.dist-info → karaoke_gen-0.99.3.dist-info}/entry_points.txt +0 -0
  197. {karaoke_gen-0.90.1.dist-info → karaoke_gen-0.99.3.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,198 @@
1
+ """
2
+ Style configuration helper for workers.
3
+
4
+ Downloads and processes style assets from GCS, making them available
5
+ for screen generation, video rendering, and CDG generation.
6
+
7
+ This module uses the unified style_loader from karaoke_gen for
8
+ consistent style handling across local CLI and cloud backend.
9
+ """
10
+ import json
11
+ import logging
12
+ import os
13
+ from pathlib import Path
14
+ from typing import Dict, Any, Optional
15
+
16
+ from backend.services.storage_service import StorageService
17
+
18
+ # Import from the unified style loader module
19
+ from karaoke_gen.style_loader import (
20
+ # Defaults
21
+ DEFAULT_INTRO_STYLE,
22
+ DEFAULT_END_STYLE,
23
+ DEFAULT_KARAOKE_STYLE,
24
+ DEFAULT_CDG_STYLE,
25
+ # Functions
26
+ load_styles_from_gcs,
27
+ update_asset_paths,
28
+ save_style_params,
29
+ get_intro_format,
30
+ get_end_format,
31
+ get_karaoke_format,
32
+ get_cdg_format,
33
+ )
34
+
35
+
36
+ logger = logging.getLogger(__name__)
37
+
38
+
39
+ # Re-export defaults for backwards compatibility with existing code
40
+ DEFAULT_INTRO_FORMAT = DEFAULT_INTRO_STYLE
41
+ DEFAULT_END_FORMAT = DEFAULT_END_STYLE
42
+ DEFAULT_KARAOKE_FORMAT = DEFAULT_KARAOKE_STYLE
43
+
44
+
45
+ class StyleConfig:
46
+ """
47
+ Manages style configuration for a job.
48
+
49
+ Downloads style assets from GCS and provides processed style parameters
50
+ with local file paths for use by video generators.
51
+
52
+ This class wraps the unified style_loader module to provide an
53
+ object-oriented interface for backend workers.
54
+ """
55
+
56
+ def __init__(self, job, storage: StorageService, temp_dir: str):
57
+ """
58
+ Initialize style configuration.
59
+
60
+ Args:
61
+ job: Job object with style_assets and style_params_gcs_path
62
+ storage: Storage service for downloading files
63
+ temp_dir: Temporary directory for downloaded assets
64
+ """
65
+ self.job = job
66
+ self.storage = storage
67
+ self.temp_dir = temp_dir
68
+ self.style_dir = os.path.join(temp_dir, "style")
69
+ os.makedirs(self.style_dir, exist_ok=True)
70
+
71
+ self._style_params: Optional[Dict[str, Any]] = None
72
+ self._local_assets: Dict[str, str] = {}
73
+ self._styles_path: Optional[str] = None
74
+ self._loaded = False
75
+ self._has_custom_styles = False # Track if custom styles were loaded
76
+
77
+ async def load(self) -> None:
78
+ """
79
+ Download and parse style configuration from GCS.
80
+
81
+ Downloads:
82
+ - style_params.json (if exists)
83
+ - All style assets (backgrounds, fonts)
84
+
85
+ After loading, style params will have local file paths.
86
+ """
87
+ if self._loaded:
88
+ return
89
+
90
+ logger.info(f"Loading style configuration for job {self.job.job_id}")
91
+
92
+ # Get style assets from job
93
+ style_assets = getattr(self.job, 'style_assets', {}) or {}
94
+ style_params_gcs_path = getattr(self.job, 'style_params_gcs_path', None)
95
+
96
+ logger.info(f"Job has {len(style_assets)} style assets defined")
97
+ for key, path in style_assets.items():
98
+ logger.info(f" Style asset '{key}': {path}")
99
+
100
+ # Check if we have custom styles before loading
101
+ self._has_custom_styles = bool(style_params_gcs_path)
102
+
103
+ # Use the unified style loader
104
+ self._styles_path, self._style_params = load_styles_from_gcs(
105
+ style_params_gcs_path=style_params_gcs_path,
106
+ style_assets=style_assets,
107
+ temp_dir=self.temp_dir,
108
+ download_func=self.storage.download_file,
109
+ logger=logger,
110
+ )
111
+
112
+ # Track local assets for get_local_asset_path()
113
+ if style_assets:
114
+ for asset_key in style_assets.keys():
115
+ if asset_key == 'style_params':
116
+ self._local_assets['style_params'] = self._styles_path
117
+ else:
118
+ ext = os.path.splitext(style_assets[asset_key])[1] or '.png'
119
+ local_path = os.path.join(self.style_dir, f"{asset_key}{ext}")
120
+ if os.path.exists(local_path):
121
+ self._local_assets[asset_key] = local_path
122
+
123
+ self._loaded = True
124
+ logger.info(f"Successfully loaded style configuration")
125
+
126
+ def get_intro_format(self) -> Dict[str, Any]:
127
+ """Get title/intro screen format, with custom styles if available."""
128
+ if self._style_params:
129
+ return get_intro_format(self._style_params)
130
+ return DEFAULT_INTRO_STYLE.copy()
131
+
132
+ def get_end_format(self) -> Dict[str, Any]:
133
+ """Get end screen format, with custom styles if available."""
134
+ if self._style_params:
135
+ return get_end_format(self._style_params)
136
+ return DEFAULT_END_STYLE.copy()
137
+
138
+ def get_karaoke_format(self) -> Dict[str, Any]:
139
+ """Get karaoke video format, with custom styles if available."""
140
+ if self._style_params:
141
+ return get_karaoke_format(self._style_params)
142
+ return DEFAULT_KARAOKE_STYLE.copy()
143
+
144
+ def get_cdg_styles(self) -> Optional[Dict[str, Any]]:
145
+ """Get CDG generation styles if available, falling back to defaults."""
146
+ if self._style_params:
147
+ cdg_styles = get_cdg_format(self._style_params)
148
+ if cdg_styles:
149
+ return cdg_styles
150
+ # Return default CDG styles if no custom styles
151
+ return DEFAULT_CDG_STYLE.copy()
152
+
153
+ def get_style_params_path(self) -> Optional[str]:
154
+ """
155
+ Get local path to style_params.json with updated asset paths.
156
+
157
+ Returns the styles JSON file path, or None if not loaded.
158
+ """
159
+ return self._styles_path
160
+
161
+ def get_local_asset_path(self, asset_key: str) -> Optional[str]:
162
+ """Get local path for a specific asset."""
163
+ return self._local_assets.get(asset_key)
164
+
165
+ def has_custom_styles(self) -> bool:
166
+ """Check if custom styles were provided (not using defaults)."""
167
+ return self._has_custom_styles
168
+
169
+ @property
170
+ def intro_video_duration(self) -> int:
171
+ """Get intro video duration in seconds."""
172
+ if self._style_params and 'intro' in self._style_params:
173
+ return self._style_params['intro'].get('video_duration', 5)
174
+ return 5
175
+
176
+ @property
177
+ def end_video_duration(self) -> int:
178
+ """Get end video duration in seconds."""
179
+ if self._style_params and 'end' in self._style_params:
180
+ return self._style_params['end'].get('video_duration', 5)
181
+ return 5
182
+
183
+
184
+ async def load_style_config(job, storage: StorageService, temp_dir: str) -> StyleConfig:
185
+ """
186
+ Helper function to load style configuration for a job.
187
+
188
+ Args:
189
+ job: Job object
190
+ storage: Storage service
191
+ temp_dir: Temporary directory
192
+
193
+ Returns:
194
+ Loaded StyleConfig instance
195
+ """
196
+ config = StyleConfig(job, storage, temp_dir)
197
+ await config.load()
198
+ return config