karaoke-gen 0.75.16__py3-none-any.whl → 0.75.53__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.
- karaoke_gen/audio_fetcher.py +766 -33
- karaoke_gen/audio_processor.py +4 -0
- karaoke_gen/instrumental_review/static/index.html +37 -14
- karaoke_gen/karaoke_finalise/karaoke_finalise.py +25 -1
- karaoke_gen/karaoke_gen.py +18 -14
- karaoke_gen/lyrics_processor.py +97 -6
- karaoke_gen/utils/cli_args.py +6 -5
- karaoke_gen/utils/gen_cli.py +30 -5
- karaoke_gen/utils/remote_cli.py +269 -15
- {karaoke_gen-0.75.16.dist-info → karaoke_gen-0.75.53.dist-info}/METADATA +106 -4
- {karaoke_gen-0.75.16.dist-info → karaoke_gen-0.75.53.dist-info}/RECORD +24 -24
- lyrics_transcriber/core/controller.py +76 -2
- lyrics_transcriber/frontend/package.json +1 -1
- lyrics_transcriber/frontend/src/App.tsx +6 -4
- lyrics_transcriber/frontend/src/api.ts +25 -10
- lyrics_transcriber/frontend/web_assets/assets/{index-COYImAcx.js → index-BECn1o8Q.js} +38 -22
- lyrics_transcriber/frontend/web_assets/assets/{index-COYImAcx.js.map → index-BECn1o8Q.js.map} +1 -1
- lyrics_transcriber/frontend/web_assets/index.html +1 -1
- lyrics_transcriber/output/countdown_processor.py +39 -0
- lyrics_transcriber/transcribers/audioshake.py +96 -7
- lyrics_transcriber/types.py +14 -12
- {karaoke_gen-0.75.16.dist-info → karaoke_gen-0.75.53.dist-info}/WHEEL +0 -0
- {karaoke_gen-0.75.16.dist-info → karaoke_gen-0.75.53.dist-info}/entry_points.txt +0 -0
- {karaoke_gen-0.75.16.dist-info → karaoke_gen-0.75.53.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
karaoke_gen/__init__.py,sha256=wHpDbURJxmJAMNZ0uQjISv5MIT7KD9RWYi15xlYgEhU,1351
|
|
2
|
-
karaoke_gen/audio_fetcher.py,sha256=
|
|
3
|
-
karaoke_gen/audio_processor.py,sha256=
|
|
2
|
+
karaoke_gen/audio_fetcher.py,sha256=A1c7HxUbV4inhGuj9SySr3zkOSGKfAFovXu2TKzodSA,63811
|
|
3
|
+
karaoke_gen/audio_processor.py,sha256=YCMsxh-OSzC6h1Oqht8gh48j4KaRDuRIMUUsNNQxJeY,39913
|
|
4
4
|
karaoke_gen/config.py,sha256=LBZKpvwSgta8YoVX2GFFW-4CP22AyRtqsBn-KCeh8eg,2499
|
|
5
5
|
karaoke_gen/file_handler.py,sha256=jnPc4kFtG-PX-IVPHYWa7maXd4lNmbkKd1HogDNzgN8,16674
|
|
6
6
|
karaoke_gen/instrumental_review/__init__.py,sha256=91K9wPWfQnOqbINuhxtErPnXyY0gijdiF-69n-p3334,1382
|
|
@@ -8,12 +8,12 @@ karaoke_gen/instrumental_review/analyzer.py,sha256=Heg8TbrwM4g5IV7bavmO6EfVD4M0U
|
|
|
8
8
|
karaoke_gen/instrumental_review/editor.py,sha256=_DGTjKMk5WhoGtLGtTvHzU522LJyQQ_DSY1r8fULuiA,11568
|
|
9
9
|
karaoke_gen/instrumental_review/models.py,sha256=cUSb_JheJK0cGdKx9f59-9sRvRrhrgdTdKBzQN3lHto,5226
|
|
10
10
|
karaoke_gen/instrumental_review/server.py,sha256=Ick90X77t2EeMRwtx2U08sSybadQyWH7G0tDG-4JqP4,19377
|
|
11
|
-
karaoke_gen/instrumental_review/static/index.html,sha256=
|
|
11
|
+
karaoke_gen/instrumental_review/static/index.html,sha256=EjMFxCQJOUSrsgwIXAW3R4bN6hYxDLmL4MHzoXxI4f0,59362
|
|
12
12
|
karaoke_gen/instrumental_review/waveform.py,sha256=Q6LBPZrJAD6mzZ7TmRf3Tf4gwYhUYTHumJKytLs3hSg,12940
|
|
13
13
|
karaoke_gen/karaoke_finalise/__init__.py,sha256=HqZ7TIhgt_tYZ-nb_NNCaejWAcF_aK-7wJY5TaW_keM,46
|
|
14
|
-
karaoke_gen/karaoke_finalise/karaoke_finalise.py,sha256=
|
|
15
|
-
karaoke_gen/karaoke_gen.py,sha256=
|
|
16
|
-
karaoke_gen/lyrics_processor.py,sha256=
|
|
14
|
+
karaoke_gen/karaoke_finalise/karaoke_finalise.py,sha256=Wn1KcdRyINT63UxKUPT9uB-bsrFVih0Im_cjXtequS0,93534
|
|
15
|
+
karaoke_gen/karaoke_gen.py,sha256=tfoywlSEI9qOi1krHTBafumXl3bcWxn6w0AN2vQ1nHs,57048
|
|
16
|
+
karaoke_gen/lyrics_processor.py,sha256=JrbTLmMR_jvcpuxsPihLXlCBKkFNKqYHvraw3_3KCPI,23263
|
|
17
17
|
karaoke_gen/metadata.py,sha256=SZW6TuUpkGGU98gRdjPfrR8F4vWXjnfCSGry2XD5_A4,6689
|
|
18
18
|
karaoke_gen/pipeline/__init__.py,sha256=-MZnba4qobr1qGDamG9CieLl2pWCZMEB5_Yur62RKeM,2106
|
|
19
19
|
karaoke_gen/pipeline/base.py,sha256=yg4LIm7Mc9ER0zCmZcUv4huEkotSSXK_0OAFio-TSNI,6235
|
|
@@ -35,9 +35,9 @@ karaoke_gen/resources/Zurich_Cn_BT_Bold.ttf,sha256=WNG5LOQ-uGUF_WWT5aQHzVbyWvQqG
|
|
|
35
35
|
karaoke_gen/style_loader.py,sha256=13010BVxwVgamRn8K8Z9fNgLBdPs9LFmWMRMLyBdits,17908
|
|
36
36
|
karaoke_gen/utils/__init__.py,sha256=FpOHyeBRB06f3zMoLBUJHTDZACrabg-DoyBTxNKYyNY,722
|
|
37
37
|
karaoke_gen/utils/bulk_cli.py,sha256=s2SXTnnQf7TM8Fk8yz9Cfd3Xl08uHBnve_rTkf4wE5g,19337
|
|
38
|
-
karaoke_gen/utils/cli_args.py,sha256=
|
|
39
|
-
karaoke_gen/utils/gen_cli.py,sha256=
|
|
40
|
-
karaoke_gen/utils/remote_cli.py,sha256=
|
|
38
|
+
karaoke_gen/utils/cli_args.py,sha256=Td8fE1FisY1fcQuOoKlAQ6B3NF4bxGvSPDaQlpfY3T0,18172
|
|
39
|
+
karaoke_gen/utils/gen_cli.py,sha256=ahoVp_n298O8yUmFOBDsm4mLXgTuEb80mBnz4_mo4SM,44137
|
|
40
|
+
karaoke_gen/utils/remote_cli.py,sha256=l1iHUz_hrsbAfTvGDhA4gzr2g1CFBFc9np0nQ1jk1tQ,144629
|
|
41
41
|
karaoke_gen/video_background_processor.py,sha256=p3sryMxmkori4Uy2MYgmlk5_QQ7Uh9IoVJLAdkdLIUI,15124
|
|
42
42
|
karaoke_gen/video_generator.py,sha256=B7BQBrjkyvk3L3sctnPXnvr1rzkw0NYx5UCAl0ZiVx0,18464
|
|
43
43
|
lyrics_transcriber/__init__.py,sha256=g9ZbJg9U1qo7XzrC25J3bTKcNzzwUJWDVdi_7-hjcM4,412
|
|
@@ -45,7 +45,7 @@ lyrics_transcriber/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
|
|
|
45
45
|
lyrics_transcriber/cli/cli_main.py,sha256=F72ENLTj934bXjHAUbRm0toCK73qnuJhwEm9agBVKHQ,11596
|
|
46
46
|
lyrics_transcriber/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
47
47
|
lyrics_transcriber/core/config.py,sha256=AM6RZKll8tzdZtMLgvHRQb1SxiXVPek0q4vmSWVUvEo,1368
|
|
48
|
-
lyrics_transcriber/core/controller.py,sha256=
|
|
48
|
+
lyrics_transcriber/core/controller.py,sha256=laeUakqT-0CoIyoBWYvv7kWxX-_wefWRwg2xrz84gRg,29432
|
|
49
49
|
lyrics_transcriber/correction/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
50
50
|
lyrics_transcriber/correction/agentic/__init__.py,sha256=p7PHiebuvRs8RDlPDs-9gLZKzXG5KfWg3fFCdDhY6pE,222
|
|
51
51
|
lyrics_transcriber/correction/agentic/adapter.py,sha256=Z0JBTAA7xlSdctCHqO9nBMl78C4XmqsLKKtS6BvNZNI,2912
|
|
@@ -125,7 +125,7 @@ lyrics_transcriber/frontend/REPLACE_ALL_FUNCTIONALITY.md,sha256=iRZbicW5satHel9g
|
|
|
125
125
|
lyrics_transcriber/frontend/__init__.py,sha256=nW8acRSWTjXoRwGqcTU4w-__X7tMAE0iXL0uihBN3CU,836
|
|
126
126
|
lyrics_transcriber/frontend/eslint.config.js,sha256=3ADH23ANA4NNBKFy6nCVk65e8bx1DrVd_FIaYNnhuqA,734
|
|
127
127
|
lyrics_transcriber/frontend/index.html,sha256=u1m7042a1kLWZVIElYQ9y-lzfIAdYJGtQE-i4Zjc3xY,806
|
|
128
|
-
lyrics_transcriber/frontend/package.json,sha256=
|
|
128
|
+
lyrics_transcriber/frontend/package.json,sha256=5krvXBc9deVYXREN9Pxw5N6ohiAsSCnPXnXlcb6p-U0,1182
|
|
129
129
|
lyrics_transcriber/frontend/public/android-chrome-192x192.png,sha256=lg-6aPF5mGLiuG7LyftZk_0RI41srmpA8wj-NkaaQms,17632
|
|
130
130
|
lyrics_transcriber/frontend/public/android-chrome-512x512.png,sha256=x-zuKT3NYsTqAWzhKRTZeD4-0uYoUjqMPZpKTChqNJ8,123447
|
|
131
131
|
lyrics_transcriber/frontend/public/apple-touch-icon.png,sha256=6y5vGra54w5oc8VP6sn2JjoQtN9hWTKn0YPhmdlmfU0,16188
|
|
@@ -133,8 +133,8 @@ lyrics_transcriber/frontend/public/favicon-16x16.png,sha256=2wy_7ZmVS4d7umByJVHQ
|
|
|
133
133
|
lyrics_transcriber/frontend/public/favicon-32x32.png,sha256=6TyrRMIw6G8dpG4_QWVTY8DMxo0bIGzc_9aOJrkiJKM,1297
|
|
134
134
|
lyrics_transcriber/frontend/public/favicon.ico,sha256=ZK7QvdBuZp0QxPkluCW4IKxfleFmFLp1KkG_d5xmx7E,15406
|
|
135
135
|
lyrics_transcriber/frontend/public/nomad-karaoke-logo.png,sha256=jTTBFXV6hGJGolZYQ-dIjgQQbMsehk5XGtsllhLrdzg,212641
|
|
136
|
-
lyrics_transcriber/frontend/src/App.tsx,sha256=
|
|
137
|
-
lyrics_transcriber/frontend/src/api.ts,sha256=
|
|
136
|
+
lyrics_transcriber/frontend/src/App.tsx,sha256=XI93-pX2p76ID45XUQTitDclUZHZ1kxhZZB2VriMV8k,6747
|
|
137
|
+
lyrics_transcriber/frontend/src/api.ts,sha256=GcjbOrlU7EdUpZ7MUPFqE1rtH-ckdw8wHtgyQxWateY,8648
|
|
138
138
|
lyrics_transcriber/frontend/src/components/AIFeedbackModal.tsx,sha256=N-M8LNKE3nCjrSkWTf8ObWSdBqD0Cv3Xiz_wVv9OtFo,3133
|
|
139
139
|
lyrics_transcriber/frontend/src/components/AddLyricsModal.tsx,sha256=ubJwQewryjUrXwpBkITQNu4POhoUtDbNA93cqa-yJKY,3416
|
|
140
140
|
lyrics_transcriber/frontend/src/components/AgenticCorrectionMetrics.tsx,sha256=Yg6FG0LtrneRfAYeBu3crt_RdN-_o7FojtYhDMDKi0o,8595
|
|
@@ -202,12 +202,12 @@ lyrics_transcriber/frontend/vite.config.ts,sha256=8FdW0dN8zDFqfhQSxX5h7sIu72X2pi
|
|
|
202
202
|
lyrics_transcriber/frontend/web_assets/android-chrome-192x192.png,sha256=lg-6aPF5mGLiuG7LyftZk_0RI41srmpA8wj-NkaaQms,17632
|
|
203
203
|
lyrics_transcriber/frontend/web_assets/android-chrome-512x512.png,sha256=x-zuKT3NYsTqAWzhKRTZeD4-0uYoUjqMPZpKTChqNJ8,123447
|
|
204
204
|
lyrics_transcriber/frontend/web_assets/apple-touch-icon.png,sha256=6y5vGra54w5oc8VP6sn2JjoQtN9hWTKn0YPhmdlmfU0,16188
|
|
205
|
-
lyrics_transcriber/frontend/web_assets/assets/index-
|
|
206
|
-
lyrics_transcriber/frontend/web_assets/assets/index-
|
|
205
|
+
lyrics_transcriber/frontend/web_assets/assets/index-BECn1o8Q.js,sha256=yNW-EWYuyaj_16fGDyvCGkb2BGoCufHlpKquqOxzQac,1421945
|
|
206
|
+
lyrics_transcriber/frontend/web_assets/assets/index-BECn1o8Q.js.map,sha256=aY17CfmBvSG6FgnuQLzgc9V02xfaOimIIAo8l4fiAJk,3004853
|
|
207
207
|
lyrics_transcriber/frontend/web_assets/favicon-16x16.png,sha256=2wy_7ZmVS4d7umByJVHQ37DBB_8xrU9xfT1_konSXQI,604
|
|
208
208
|
lyrics_transcriber/frontend/web_assets/favicon-32x32.png,sha256=6TyrRMIw6G8dpG4_QWVTY8DMxo0bIGzc_9aOJrkiJKM,1297
|
|
209
209
|
lyrics_transcriber/frontend/web_assets/favicon.ico,sha256=ZK7QvdBuZp0QxPkluCW4IKxfleFmFLp1KkG_d5xmx7E,15406
|
|
210
|
-
lyrics_transcriber/frontend/web_assets/index.html,sha256=
|
|
210
|
+
lyrics_transcriber/frontend/web_assets/index.html,sha256=qqHYlM3VAy_3YJn3QgETGjR94XTWL3Ci_S-5_lHYgxw,830
|
|
211
211
|
lyrics_transcriber/frontend/web_assets/nomad-karaoke-logo.png,sha256=jTTBFXV6hGJGolZYQ-dIjgQQbMsehk5XGtsllhLrdzg,212641
|
|
212
212
|
lyrics_transcriber/frontend/yarn.lock,sha256=wtImLsCO1P1Lpkhc1jAN6IiHQ0As4xn39n0cwKoh4LM,131996
|
|
213
213
|
lyrics_transcriber/lyrics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -253,7 +253,7 @@ lyrics_transcriber/output/cdgmaker/transitions/wipeleft.png,sha256=7jY6Z-mdY94PE
|
|
|
253
253
|
lyrics_transcriber/output/cdgmaker/transitions/wipeout.png,sha256=YSLdv2RCGeSilOGt7PYTLAOlBfL4bofu8Vpj-PcskZo,9995
|
|
254
254
|
lyrics_transcriber/output/cdgmaker/transitions/wiperight.png,sha256=Dw3N6cqJaSwL3owDqyAM4W573EmdNnkjdiXhoxWC4yk,8443
|
|
255
255
|
lyrics_transcriber/output/cdgmaker/utils.py,sha256=TNcOnccegpxT3OogWQCexy8BrDqfihLAShMvqeM81cw,2945
|
|
256
|
-
lyrics_transcriber/output/countdown_processor.py,sha256=
|
|
256
|
+
lyrics_transcriber/output/countdown_processor.py,sha256=EsUmnamNiG3SRfqPsZjSH3BH81a9AUg7wIdtfDkW57s,10848
|
|
257
257
|
lyrics_transcriber/output/fonts/AvenirNext-Bold.ttf,sha256=YxgKz2OP46lwLPCpIZhVa8COi_9KRDSXw4n8dIHHQSs,327048
|
|
258
258
|
"lyrics_transcriber/output/fonts/DMSans-VariableFont_opsz,wght.ttf",sha256=7uav75vmxRukpMx8wqtPeNvaxqOzlBljO400geBzYYI,238984
|
|
259
259
|
lyrics_transcriber/output/fonts/DMSerifDisplay-Regular.ttf,sha256=mMHMLr3CMjEQgJ5cKlYEn8YSsHwSnDtxT-Qjn_n8ffM,72220
|
|
@@ -274,14 +274,14 @@ lyrics_transcriber/review/server.py,sha256=_05ul0MsddKf8iTIg-NASVYkl9kBRo0M3WhWB
|
|
|
274
274
|
lyrics_transcriber/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
275
275
|
lyrics_transcriber/storage/dropbox.py,sha256=Dyam1ULTkoxD1X5trkZ5dGp5XhBGCn998moC8IS9-68,9804
|
|
276
276
|
lyrics_transcriber/transcribers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
277
|
-
lyrics_transcriber/transcribers/audioshake.py,sha256=
|
|
277
|
+
lyrics_transcriber/transcribers/audioshake.py,sha256=RihuLKzhhHfX7m5cjKISwIuTQkGWapCS29D6Qk3hR4U,15869
|
|
278
278
|
lyrics_transcriber/transcribers/base_transcriber.py,sha256=T3m4ZCwZ9Bpv6Jvb2hNcnllk-lmeNmADDJlSySBtP1Q,6480
|
|
279
279
|
lyrics_transcriber/transcribers/whisper.py,sha256=YcCB1ic9H6zL1GS0jD0emu8-qlcH0QVEjjjYB4aLlIQ,13260
|
|
280
|
-
lyrics_transcriber/types.py,sha256=
|
|
280
|
+
lyrics_transcriber/types.py,sha256=UJjaxhVd2o14AG4G8ToU598p0JeYdiTFjpG38jGCoYQ,27917
|
|
281
281
|
lyrics_transcriber/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
282
282
|
lyrics_transcriber/utils/word_utils.py,sha256=-cMGpj9UV4F6IsoDKAV2i1aiqSO8eI91HMAm_igtVMk,958
|
|
283
|
-
karaoke_gen-0.75.
|
|
284
|
-
karaoke_gen-0.75.
|
|
285
|
-
karaoke_gen-0.75.
|
|
286
|
-
karaoke_gen-0.75.
|
|
287
|
-
karaoke_gen-0.75.
|
|
283
|
+
karaoke_gen-0.75.53.dist-info/METADATA,sha256=DR2eCSIs1DM9Xudkimpy66AgxZRfYSYyzpBX-sxkhgE,20662
|
|
284
|
+
karaoke_gen-0.75.53.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
285
|
+
karaoke_gen-0.75.53.dist-info/entry_points.txt,sha256=xIyLe7K84ZyjO8L0_AmNectz93QjGSs5AkApMtlAd4g,160
|
|
286
|
+
karaoke_gen-0.75.53.dist-info/licenses/LICENSE,sha256=81R_4XwMZDODHD7JcZeUR8IiCU8AD7Ajl6bmwR9tYDk,1074
|
|
287
|
+
karaoke_gen-0.75.53.dist-info/RECORD,,
|
|
@@ -307,6 +307,37 @@ class LyricsTranscriber:
|
|
|
307
307
|
self.results.transcription_corrected = CorrectionResult.from_dict(corrections_data)
|
|
308
308
|
self.logger.info("Successfully loaded existing corrections data")
|
|
309
309
|
|
|
310
|
+
# Check if the loaded corrections have countdown padding applied
|
|
311
|
+
# This is important because the video needs to use padded audio to sync
|
|
312
|
+
# with the countdown-adjusted timestamps in the ASS subtitles
|
|
313
|
+
if self.output_config.add_countdown:
|
|
314
|
+
from lyrics_transcriber.output.countdown_processor import CountdownProcessor
|
|
315
|
+
|
|
316
|
+
countdown_processor = CountdownProcessor(
|
|
317
|
+
cache_dir=self.output_config.cache_dir,
|
|
318
|
+
logger=self.logger,
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
if countdown_processor.has_countdown(self.results.transcription_corrected):
|
|
322
|
+
self.logger.info(
|
|
323
|
+
"Loaded corrections have countdown - creating padded audio for video sync"
|
|
324
|
+
)
|
|
325
|
+
# Create padded audio file to match the countdown-adjusted timestamps
|
|
326
|
+
padded_audio_path = countdown_processor.create_padded_audio_only(self.audio_filepath)
|
|
327
|
+
self.audio_filepath = padded_audio_path
|
|
328
|
+
|
|
329
|
+
# Set countdown padding attributes on results
|
|
330
|
+
self.results.countdown_padding_added = True
|
|
331
|
+
self.results.countdown_padding_seconds = countdown_processor.COUNTDOWN_PADDING_SECONDS
|
|
332
|
+
self.results.padded_audio_filepath = padded_audio_path
|
|
333
|
+
|
|
334
|
+
self.logger.info(
|
|
335
|
+
f"Countdown padding applied: {countdown_processor.COUNTDOWN_PADDING_SECONDS}s. "
|
|
336
|
+
f"Using padded audio: {padded_audio_path}"
|
|
337
|
+
)
|
|
338
|
+
else:
|
|
339
|
+
self.logger.info("Loaded corrections do not have countdown - no padding needed")
|
|
340
|
+
|
|
310
341
|
# Skip to output generation
|
|
311
342
|
self.generate_outputs()
|
|
312
343
|
self.logger.info("Processing completed successfully using existing corrections")
|
|
@@ -363,7 +394,24 @@ class LyricsTranscriber:
|
|
|
363
394
|
|
|
364
395
|
def transcribe(self) -> None:
|
|
365
396
|
"""Run transcription using all available transcribers."""
|
|
366
|
-
|
|
397
|
+
provider_names = list(self.transcribers.keys())
|
|
398
|
+
|
|
399
|
+
if not provider_names:
|
|
400
|
+
self.logger.warning(
|
|
401
|
+
"Starting transcription with providers: [] - NO TRANSCRIPTION PROVIDERS CONFIGURED!\n"
|
|
402
|
+
"\n"
|
|
403
|
+
"This means no word-level timing data will be generated, and synchronized karaoke "
|
|
404
|
+
"lyrics cannot be created. The output will lack the '(With Vocals).mkv' video file.\n"
|
|
405
|
+
"\n"
|
|
406
|
+
"To enable transcription, configure at least one provider:\n"
|
|
407
|
+
" - AudioShake: Set AUDIOSHAKE_API_TOKEN environment variable\n"
|
|
408
|
+
" - Whisper/RunPod: Set RUNPOD_API_KEY and WHISPER_RUNPOD_ID environment variables\n"
|
|
409
|
+
"\n"
|
|
410
|
+
"See README.md 'Transcription Providers' section for detailed setup instructions."
|
|
411
|
+
)
|
|
412
|
+
else:
|
|
413
|
+
self.logger.info(f"Starting transcription with providers: {provider_names}")
|
|
414
|
+
self._log_provider_configuration_status()
|
|
367
415
|
|
|
368
416
|
for name, transcriber_info in self.transcribers.items():
|
|
369
417
|
self.logger.info(f"Running transcription with {name}")
|
|
@@ -376,7 +424,33 @@ class LyricsTranscriber:
|
|
|
376
424
|
self.logger.debug(f"Transcription completed for {name}")
|
|
377
425
|
|
|
378
426
|
if not self.results.transcription_results:
|
|
379
|
-
self.logger.warning(
|
|
427
|
+
self.logger.warning(
|
|
428
|
+
"No successful transcriptions from any provider. "
|
|
429
|
+
"Check that your API tokens are valid and the services are accessible."
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
def _log_provider_configuration_status(self) -> None:
|
|
433
|
+
"""Log detailed configuration status for each potential transcription provider."""
|
|
434
|
+
self.logger.debug("Transcription provider configuration status:")
|
|
435
|
+
|
|
436
|
+
# AudioShake status
|
|
437
|
+
if self.transcriber_config.audioshake_api_token:
|
|
438
|
+
self.logger.debug(" - AudioShake: CONFIGURED (API token provided)")
|
|
439
|
+
else:
|
|
440
|
+
self.logger.debug(" - AudioShake: NOT CONFIGURED (missing AUDIOSHAKE_API_TOKEN)")
|
|
441
|
+
|
|
442
|
+
# Whisper/RunPod status
|
|
443
|
+
has_runpod_key = bool(self.transcriber_config.runpod_api_key)
|
|
444
|
+
has_whisper_id = bool(self.transcriber_config.whisper_runpod_id)
|
|
445
|
+
|
|
446
|
+
if has_runpod_key and has_whisper_id:
|
|
447
|
+
self.logger.debug(" - Whisper (RunPod): CONFIGURED (API key and endpoint ID provided)")
|
|
448
|
+
elif has_runpod_key:
|
|
449
|
+
self.logger.debug(" - Whisper (RunPod): PARTIALLY CONFIGURED (missing WHISPER_RUNPOD_ID)")
|
|
450
|
+
elif has_whisper_id:
|
|
451
|
+
self.logger.debug(" - Whisper (RunPod): PARTIALLY CONFIGURED (missing RUNPOD_API_KEY)")
|
|
452
|
+
else:
|
|
453
|
+
self.logger.debug(" - Whisper (RunPod): NOT CONFIGURED (missing RUNPOD_API_KEY and WHISPER_RUNPOD_ID)")
|
|
380
454
|
|
|
381
455
|
def correct_lyrics(self) -> None:
|
|
382
456
|
"""Run lyrics correction using transcription and internet lyrics."""
|
|
@@ -19,25 +19,27 @@ export default function App() {
|
|
|
19
19
|
const params = new URLSearchParams(window.location.search)
|
|
20
20
|
const encodedApiUrl = params.get('baseApiUrl')
|
|
21
21
|
const audioHashParam = params.get('audioHash')
|
|
22
|
+
const reviewTokenParam = params.get('reviewToken')
|
|
22
23
|
|
|
23
24
|
if (encodedApiUrl) {
|
|
24
25
|
const baseApiUrl = decodeURIComponent(encodedApiUrl)
|
|
25
|
-
|
|
26
|
+
// Pass reviewToken to LiveApiClient for authentication
|
|
27
|
+
setApiClient(new LiveApiClient(baseApiUrl, reviewTokenParam || undefined))
|
|
26
28
|
setIsReadOnly(false)
|
|
27
29
|
if (audioHashParam) {
|
|
28
30
|
setAudioHash(audioHashParam)
|
|
29
31
|
}
|
|
30
32
|
// Fetch initial data
|
|
31
|
-
fetchData(baseApiUrl)
|
|
33
|
+
fetchData(baseApiUrl, reviewTokenParam || undefined)
|
|
32
34
|
} else {
|
|
33
35
|
setApiClient(new FileOnlyClient())
|
|
34
36
|
setIsReadOnly(true)
|
|
35
37
|
}
|
|
36
38
|
}, [])
|
|
37
39
|
|
|
38
|
-
const fetchData = async (baseUrl: string) => {
|
|
40
|
+
const fetchData = async (baseUrl: string, reviewToken?: string) => {
|
|
39
41
|
try {
|
|
40
|
-
const client = new LiveApiClient(baseUrl)
|
|
42
|
+
const client = new LiveApiClient(baseUrl, reviewToken)
|
|
41
43
|
const data = await client.getCorrectionData()
|
|
42
44
|
// console.log('Full correction data from API:', data)
|
|
43
45
|
setData(data)
|
|
@@ -35,14 +35,29 @@ interface AddLyricsRequest {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
export class LiveApiClient implements ApiClient {
|
|
38
|
-
|
|
38
|
+
private reviewToken?: string;
|
|
39
|
+
|
|
40
|
+
constructor(private baseUrl: string, reviewToken?: string) {
|
|
39
41
|
this.baseUrl = baseUrl.replace(/\/$/, '')
|
|
42
|
+
this.reviewToken = reviewToken
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
public isUpdatingHandlers = false;
|
|
43
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Build URL with reviewToken query parameter if available
|
|
49
|
+
*/
|
|
50
|
+
private buildUrl(path: string): string {
|
|
51
|
+
const url = `${this.baseUrl}${path}`
|
|
52
|
+
if (this.reviewToken) {
|
|
53
|
+
const separator = url.includes('?') ? '&' : '?'
|
|
54
|
+
return `${url}${separator}review_token=${encodeURIComponent(this.reviewToken)}`
|
|
55
|
+
}
|
|
56
|
+
return url
|
|
57
|
+
}
|
|
58
|
+
|
|
44
59
|
async getCorrectionData(): Promise<CorrectionData> {
|
|
45
|
-
const response = await fetch(
|
|
60
|
+
const response = await fetch(this.buildUrl('/correction-data'));
|
|
46
61
|
if (!response.ok) {
|
|
47
62
|
throw new Error(`API error: ${response.statusText}`);
|
|
48
63
|
}
|
|
@@ -64,7 +79,7 @@ export class LiveApiClient implements ApiClient {
|
|
|
64
79
|
corrected_segments: data.corrected_segments
|
|
65
80
|
};
|
|
66
81
|
|
|
67
|
-
const response = await fetch(
|
|
82
|
+
const response = await fetch(this.buildUrl('/complete'), {
|
|
68
83
|
method: 'POST',
|
|
69
84
|
headers: {
|
|
70
85
|
'Content-Type': 'application/json',
|
|
@@ -78,7 +93,7 @@ export class LiveApiClient implements ApiClient {
|
|
|
78
93
|
}
|
|
79
94
|
|
|
80
95
|
getAudioUrl(audioHash: string): string {
|
|
81
|
-
return
|
|
96
|
+
return this.buildUrl(`/audio/${audioHash}`)
|
|
82
97
|
}
|
|
83
98
|
|
|
84
99
|
async generatePreviewVideo(data: CorrectionData): Promise<PreviewVideoResponse> {
|
|
@@ -88,7 +103,7 @@ export class LiveApiClient implements ApiClient {
|
|
|
88
103
|
corrected_segments: data.corrected_segments
|
|
89
104
|
};
|
|
90
105
|
|
|
91
|
-
const response = await fetch(
|
|
106
|
+
const response = await fetch(this.buildUrl('/preview-video'), {
|
|
92
107
|
method: 'POST',
|
|
93
108
|
headers: {
|
|
94
109
|
'Content-Type': 'application/json',
|
|
@@ -107,7 +122,7 @@ export class LiveApiClient implements ApiClient {
|
|
|
107
122
|
}
|
|
108
123
|
|
|
109
124
|
getPreviewVideoUrl(previewHash: string): string {
|
|
110
|
-
return
|
|
125
|
+
return this.buildUrl(`/preview-video/${previewHash}`);
|
|
111
126
|
}
|
|
112
127
|
|
|
113
128
|
async updateHandlers(enabledHandlers: string[]): Promise<CorrectionData> {
|
|
@@ -116,7 +131,7 @@ export class LiveApiClient implements ApiClient {
|
|
|
116
131
|
console.log('API: Set isUpdatingHandlers to', this.isUpdatingHandlers);
|
|
117
132
|
|
|
118
133
|
try {
|
|
119
|
-
const response = await fetch(
|
|
134
|
+
const response = await fetch(this.buildUrl('/handlers'), {
|
|
120
135
|
method: 'POST',
|
|
121
136
|
headers: {
|
|
122
137
|
'Content-Type': 'application/json',
|
|
@@ -147,7 +162,7 @@ export class LiveApiClient implements ApiClient {
|
|
|
147
162
|
lyrics
|
|
148
163
|
};
|
|
149
164
|
|
|
150
|
-
const response = await fetch(
|
|
165
|
+
const response = await fetch(this.buildUrl('/add-lyrics'), {
|
|
151
166
|
method: 'POST',
|
|
152
167
|
headers: {
|
|
153
168
|
'Content-Type': 'application/json',
|
|
@@ -170,7 +185,7 @@ export class LiveApiClient implements ApiClient {
|
|
|
170
185
|
async submitAnnotations(annotations: Omit<CorrectionAnnotation, 'annotation_id' | 'timestamp'>[]): Promise<void> {
|
|
171
186
|
// Submit each annotation to the backend
|
|
172
187
|
for (const annotation of annotations) {
|
|
173
|
-
const response = await fetch(
|
|
188
|
+
const response = await fetch(this.buildUrl('/v1/annotations'), {
|
|
174
189
|
method: 'POST',
|
|
175
190
|
headers: {
|
|
176
191
|
'Content-Type': 'application/json',
|
|
@@ -186,7 +201,7 @@ export class LiveApiClient implements ApiClient {
|
|
|
186
201
|
}
|
|
187
202
|
|
|
188
203
|
async getAnnotationStats(): Promise<any> {
|
|
189
|
-
const response = await fetch(
|
|
204
|
+
const response = await fetch(this.buildUrl('/v1/annotations/stats'));
|
|
190
205
|
if (!response.ok) {
|
|
191
206
|
throw new Error(`API error: ${response.statusText}`);
|
|
192
207
|
}
|
|
@@ -34056,13 +34056,26 @@ function validateCorrectionData(data) {
|
|
|
34056
34056
|
return CorrectionDataSchema.parse(data);
|
|
34057
34057
|
}
|
|
34058
34058
|
class LiveApiClient {
|
|
34059
|
-
constructor(baseUrl) {
|
|
34059
|
+
constructor(baseUrl, reviewToken) {
|
|
34060
|
+
__publicField(this, "reviewToken");
|
|
34060
34061
|
__publicField(this, "isUpdatingHandlers", false);
|
|
34061
34062
|
this.baseUrl = baseUrl;
|
|
34062
34063
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
34064
|
+
this.reviewToken = reviewToken;
|
|
34065
|
+
}
|
|
34066
|
+
/**
|
|
34067
|
+
* Build URL with reviewToken query parameter if available
|
|
34068
|
+
*/
|
|
34069
|
+
buildUrl(path) {
|
|
34070
|
+
const url = `${this.baseUrl}${path}`;
|
|
34071
|
+
if (this.reviewToken) {
|
|
34072
|
+
const separator = url.includes("?") ? "&" : "?";
|
|
34073
|
+
return `${url}${separator}review_token=${encodeURIComponent(this.reviewToken)}`;
|
|
34074
|
+
}
|
|
34075
|
+
return url;
|
|
34063
34076
|
}
|
|
34064
34077
|
async getCorrectionData() {
|
|
34065
|
-
const response = await fetch(
|
|
34078
|
+
const response = await fetch(this.buildUrl("/correction-data"));
|
|
34066
34079
|
if (!response.ok) {
|
|
34067
34080
|
throw new Error(`API error: ${response.statusText}`);
|
|
34068
34081
|
}
|
|
@@ -34079,7 +34092,7 @@ class LiveApiClient {
|
|
|
34079
34092
|
corrections: data.corrections,
|
|
34080
34093
|
corrected_segments: data.corrected_segments
|
|
34081
34094
|
};
|
|
34082
|
-
const response = await fetch(
|
|
34095
|
+
const response = await fetch(this.buildUrl("/complete"), {
|
|
34083
34096
|
method: "POST",
|
|
34084
34097
|
headers: {
|
|
34085
34098
|
"Content-Type": "application/json"
|
|
@@ -34091,14 +34104,14 @@ class LiveApiClient {
|
|
|
34091
34104
|
}
|
|
34092
34105
|
}
|
|
34093
34106
|
getAudioUrl(audioHash) {
|
|
34094
|
-
return
|
|
34107
|
+
return this.buildUrl(`/audio/${audioHash}`);
|
|
34095
34108
|
}
|
|
34096
34109
|
async generatePreviewVideo(data) {
|
|
34097
34110
|
const updatePayload = {
|
|
34098
34111
|
corrections: data.corrections,
|
|
34099
34112
|
corrected_segments: data.corrected_segments
|
|
34100
34113
|
};
|
|
34101
|
-
const response = await fetch(
|
|
34114
|
+
const response = await fetch(this.buildUrl("/preview-video"), {
|
|
34102
34115
|
method: "POST",
|
|
34103
34116
|
headers: {
|
|
34104
34117
|
"Content-Type": "application/json"
|
|
@@ -34114,14 +34127,14 @@ class LiveApiClient {
|
|
|
34114
34127
|
return await response.json();
|
|
34115
34128
|
}
|
|
34116
34129
|
getPreviewVideoUrl(previewHash) {
|
|
34117
|
-
return
|
|
34130
|
+
return this.buildUrl(`/preview-video/${previewHash}`);
|
|
34118
34131
|
}
|
|
34119
34132
|
async updateHandlers(enabledHandlers) {
|
|
34120
34133
|
console.log("API: Starting handler update...");
|
|
34121
34134
|
this.isUpdatingHandlers = true;
|
|
34122
34135
|
console.log("API: Set isUpdatingHandlers to", this.isUpdatingHandlers);
|
|
34123
34136
|
try {
|
|
34124
|
-
const response = await fetch(
|
|
34137
|
+
const response = await fetch(this.buildUrl("/handlers"), {
|
|
34125
34138
|
method: "POST",
|
|
34126
34139
|
headers: {
|
|
34127
34140
|
"Content-Type": "application/json"
|
|
@@ -34147,7 +34160,7 @@ class LiveApiClient {
|
|
|
34147
34160
|
source,
|
|
34148
34161
|
lyrics
|
|
34149
34162
|
};
|
|
34150
|
-
const response = await fetch(
|
|
34163
|
+
const response = await fetch(this.buildUrl("/add-lyrics"), {
|
|
34151
34164
|
method: "POST",
|
|
34152
34165
|
headers: {
|
|
34153
34166
|
"Content-Type": "application/json"
|
|
@@ -34165,7 +34178,7 @@ class LiveApiClient {
|
|
|
34165
34178
|
}
|
|
34166
34179
|
async submitAnnotations(annotations) {
|
|
34167
34180
|
for (const annotation of annotations) {
|
|
34168
|
-
const response = await fetch(
|
|
34181
|
+
const response = await fetch(this.buildUrl("/v1/annotations"), {
|
|
34169
34182
|
method: "POST",
|
|
34170
34183
|
headers: {
|
|
34171
34184
|
"Content-Type": "application/json"
|
|
@@ -34178,7 +34191,7 @@ class LiveApiClient {
|
|
|
34178
34191
|
}
|
|
34179
34192
|
}
|
|
34180
34193
|
async getAnnotationStats() {
|
|
34181
|
-
const response = await fetch(
|
|
34194
|
+
const response = await fetch(this.buildUrl("/v1/annotations/stats"));
|
|
34182
34195
|
if (!response.ok) {
|
|
34183
34196
|
throw new Error(`API error: ${response.statusText}`);
|
|
34184
34197
|
}
|
|
@@ -38943,10 +38956,12 @@ const TimelineCanvas = reactExports.memo(function TimelineCanvas2({
|
|
|
38943
38956
|
const deltaTime = time - dragStartRef.current.time;
|
|
38944
38957
|
const updates = [];
|
|
38945
38958
|
for (const [wordId, originalTimes] of dragOriginalTimesRef.current) {
|
|
38959
|
+
const newStartTime = Math.max(0, originalTimes.start + deltaTime);
|
|
38960
|
+
const newEndTime = Math.max(newStartTime + 0.05, originalTimes.end + deltaTime);
|
|
38946
38961
|
updates.push({
|
|
38947
38962
|
wordId,
|
|
38948
|
-
newStartTime
|
|
38949
|
-
newEndTime
|
|
38963
|
+
newStartTime,
|
|
38964
|
+
newEndTime
|
|
38950
38965
|
});
|
|
38951
38966
|
}
|
|
38952
38967
|
if (updates.length > 0) {
|
|
@@ -39275,7 +39290,7 @@ const LyricsSynchronizer = reactExports.memo(function LyricsSynchronizer2({
|
|
|
39275
39290
|
);
|
|
39276
39291
|
const allWords = reactExports.useMemo(() => getAllWords(workingSegments), [workingSegments]);
|
|
39277
39292
|
const audioDuration = reactExports.useMemo(() => {
|
|
39278
|
-
if (window.getAudioDuration) {
|
|
39293
|
+
if (typeof window.getAudioDuration === "function") {
|
|
39279
39294
|
const duration2 = window.getAudioDuration();
|
|
39280
39295
|
return duration2 > 0 ? duration2 : 300;
|
|
39281
39296
|
}
|
|
@@ -39347,7 +39362,7 @@ const LyricsSynchronizer = reactExports.memo(function LyricsSynchronizer2({
|
|
|
39347
39362
|
const [isPlaying, setIsPlaying] = reactExports.useState(false);
|
|
39348
39363
|
reactExports.useEffect(() => {
|
|
39349
39364
|
const checkPlaying = () => {
|
|
39350
|
-
setIsPlaying(window.isAudioPlaying
|
|
39365
|
+
setIsPlaying(typeof window.isAudioPlaying === "boolean" ? window.isAudioPlaying : false);
|
|
39351
39366
|
};
|
|
39352
39367
|
checkPlaying();
|
|
39353
39368
|
const interval = setInterval(checkPlaying, 100);
|
|
@@ -39359,7 +39374,7 @@ const LyricsSynchronizer = reactExports.memo(function LyricsSynchronizer2({
|
|
|
39359
39374
|
}
|
|
39360
39375
|
}, [onPlaySegment]);
|
|
39361
39376
|
const handleStopAudio = reactExports.useCallback(() => {
|
|
39362
|
-
if (window.toggleAudioPlayback && window.isAudioPlaying) {
|
|
39377
|
+
if (typeof window.toggleAudioPlayback === "function" && window.isAudioPlaying) {
|
|
39363
39378
|
window.toggleAudioPlayback();
|
|
39364
39379
|
}
|
|
39365
39380
|
if (isManualSyncing) {
|
|
@@ -39616,7 +39631,7 @@ const LyricsSynchronizer = reactExports.memo(function LyricsSynchronizer2({
|
|
|
39616
39631
|
if (onPlaySegment) {
|
|
39617
39632
|
onPlaySegment(time);
|
|
39618
39633
|
setTimeout(() => {
|
|
39619
|
-
if (window.toggleAudioPlayback && window.isAudioPlaying) {
|
|
39634
|
+
if (typeof window.toggleAudioPlayback === "function" && window.isAudioPlaying) {
|
|
39620
39635
|
window.toggleAudioPlayback();
|
|
39621
39636
|
}
|
|
39622
39637
|
}, 50);
|
|
@@ -42923,22 +42938,23 @@ function App() {
|
|
|
42923
42938
|
const params = new URLSearchParams(window.location.search);
|
|
42924
42939
|
const encodedApiUrl = params.get("baseApiUrl");
|
|
42925
42940
|
const audioHashParam = params.get("audioHash");
|
|
42941
|
+
const reviewTokenParam = params.get("reviewToken");
|
|
42926
42942
|
if (encodedApiUrl) {
|
|
42927
42943
|
const baseApiUrl = decodeURIComponent(encodedApiUrl);
|
|
42928
|
-
setApiClient(new LiveApiClient(baseApiUrl));
|
|
42944
|
+
setApiClient(new LiveApiClient(baseApiUrl, reviewTokenParam || void 0));
|
|
42929
42945
|
setIsReadOnly(false);
|
|
42930
42946
|
if (audioHashParam) {
|
|
42931
42947
|
setAudioHash(audioHashParam);
|
|
42932
42948
|
}
|
|
42933
|
-
fetchData(baseApiUrl);
|
|
42949
|
+
fetchData(baseApiUrl, reviewTokenParam || void 0);
|
|
42934
42950
|
} else {
|
|
42935
42951
|
setApiClient(new FileOnlyClient());
|
|
42936
42952
|
setIsReadOnly(true);
|
|
42937
42953
|
}
|
|
42938
42954
|
}, []);
|
|
42939
|
-
const fetchData = async (baseUrl) => {
|
|
42955
|
+
const fetchData = async (baseUrl, reviewToken) => {
|
|
42940
42956
|
try {
|
|
42941
|
-
const client2 = new LiveApiClient(baseUrl);
|
|
42957
|
+
const client2 = new LiveApiClient(baseUrl, reviewToken);
|
|
42942
42958
|
const data2 = await client2.getCorrectionData();
|
|
42943
42959
|
setData(data2);
|
|
42944
42960
|
} catch (err) {
|
|
@@ -43258,7 +43274,7 @@ const theme = createTheme({
|
|
|
43258
43274
|
spacing: (factor) => `${0.6 * factor}rem`
|
|
43259
43275
|
// Further reduced from 0.8 * factor
|
|
43260
43276
|
});
|
|
43261
|
-
const version = "0.
|
|
43277
|
+
const version = "0.83.0";
|
|
43262
43278
|
const packageJson = {
|
|
43263
43279
|
version
|
|
43264
43280
|
};
|
|
@@ -43269,4 +43285,4 @@ ReactDOM$1.createRoot(document.getElementById("root")).render(
|
|
|
43269
43285
|
/* @__PURE__ */ jsxRuntimeExports.jsx(App, {})
|
|
43270
43286
|
] })
|
|
43271
43287
|
);
|
|
43272
|
-
//# sourceMappingURL=index-
|
|
43288
|
+
//# sourceMappingURL=index-BECn1o8Q.js.map
|