karaoke-gen 0.71.17__tar.gz → 0.71.29__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.
Files changed (274) hide show
  1. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/PKG-INFO +1 -1
  2. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/karaoke_finalise/karaoke_finalise.py +26 -2
  3. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/utils/remote_cli.py +325 -78
  4. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/anchor_sequence.py +68 -68
  5. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/pyproject.toml +1 -1
  6. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/LICENSE +0 -0
  7. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/README.md +0 -0
  8. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/__init__.py +0 -0
  9. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/audio_fetcher.py +0 -0
  10. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/audio_processor.py +0 -0
  11. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/config.py +0 -0
  12. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/file_handler.py +0 -0
  13. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/karaoke_finalise/__init__.py +0 -0
  14. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/karaoke_gen.py +0 -0
  15. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/lyrics_processor.py +0 -0
  16. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/metadata.py +0 -0
  17. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/__init__.py +0 -0
  18. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/base.py +0 -0
  19. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/context.py +0 -0
  20. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/executors/__init__.py +0 -0
  21. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/executors/local.py +0 -0
  22. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/executors/remote.py +0 -0
  23. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/stages/__init__.py +0 -0
  24. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/stages/finalize.py +0 -0
  25. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/stages/render.py +0 -0
  26. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/stages/screens.py +0 -0
  27. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/stages/separation.py +0 -0
  28. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/stages/transcription.py +0 -0
  29. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/resources/AvenirNext-Bold.ttf +0 -0
  30. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/resources/Montserrat-Bold.ttf +0 -0
  31. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/resources/Oswald-Bold.ttf +0 -0
  32. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/resources/Oswald-SemiBold.ttf +0 -0
  33. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/resources/Zurich_Cn_BT_Bold.ttf +0 -0
  34. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/style_loader.py +0 -0
  35. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/utils/__init__.py +0 -0
  36. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/utils/bulk_cli.py +0 -0
  37. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/utils/cli_args.py +0 -0
  38. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/utils/gen_cli.py +0 -0
  39. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/video_background_processor.py +0 -0
  40. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/video_generator.py +0 -0
  41. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/__init__.py +0 -0
  42. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/cli/__init__.py +0 -0
  43. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/cli/cli_main.py +0 -0
  44. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/core/__init__.py +0 -0
  45. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/core/config.py +0 -0
  46. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/core/controller.py +0 -0
  47. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/__init__.py +0 -0
  48. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/__init__.py +0 -0
  49. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/adapter.py +0 -0
  50. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/agent.py +0 -0
  51. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/feedback/aggregator.py +0 -0
  52. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/feedback/collector.py +0 -0
  53. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/feedback/retention.py +0 -0
  54. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/feedback/store.py +0 -0
  55. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/__init__.py +0 -0
  56. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/ambiguous.py +0 -0
  57. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/background_vocals.py +0 -0
  58. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/base.py +0 -0
  59. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/complex_multi_error.py +0 -0
  60. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/extra_words.py +0 -0
  61. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/no_error.py +0 -0
  62. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/punctuation.py +0 -0
  63. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/registry.py +0 -0
  64. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/repeated_section.py +0 -0
  65. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/sound_alike.py +0 -0
  66. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/models/__init__.py +0 -0
  67. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/models/ai_correction.py +0 -0
  68. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/models/correction_session.py +0 -0
  69. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/models/enums.py +0 -0
  70. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/models/human_feedback.py +0 -0
  71. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/models/learning_data.py +0 -0
  72. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/models/observability_metrics.py +0 -0
  73. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/models/schemas.py +0 -0
  74. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/models/utils.py +0 -0
  75. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/observability/__init__.py +0 -0
  76. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/observability/langfuse_integration.py +0 -0
  77. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/observability/metrics.py +0 -0
  78. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/observability/performance.py +0 -0
  79. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/prompts/__init__.py +0 -0
  80. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/prompts/classifier.py +0 -0
  81. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/__init__.py +0 -0
  82. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/base.py +0 -0
  83. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/circuit_breaker.py +0 -0
  84. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/config.py +0 -0
  85. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/constants.py +0 -0
  86. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/health.py +0 -0
  87. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/langchain_bridge.py +0 -0
  88. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/model_factory.py +0 -0
  89. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/response_cache.py +0 -0
  90. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/response_parser.py +0 -0
  91. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/retry_executor.py +0 -0
  92. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/router.py +0 -0
  93. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/workflows/__init__.py +0 -0
  94. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/workflows/consensus_workflow.py +0 -0
  95. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/workflows/correction_graph.py +0 -0
  96. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/workflows/feedback_workflow.py +0 -0
  97. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/corrector.py +0 -0
  98. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/feedback/__init__.py +0 -0
  99. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/feedback/schemas.py +0 -0
  100. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/feedback/store.py +0 -0
  101. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/__init__.py +0 -0
  102. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/base.py +0 -0
  103. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/extend_anchor.py +0 -0
  104. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/levenshtein.py +0 -0
  105. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/llm.py +0 -0
  106. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/llm_providers.py +0 -0
  107. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/no_space_punct_match.py +0 -0
  108. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/relaxed_word_count_match.py +0 -0
  109. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/repeat.py +0 -0
  110. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/sound_alike.py +0 -0
  111. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/syllables_match.py +0 -0
  112. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/word_count_match.py +0 -0
  113. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/word_operations.py +0 -0
  114. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/operations.py +0 -0
  115. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/phrase_analyzer.py +0 -0
  116. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/text_utils.py +0 -0
  117. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/.gitignore +0 -0
  118. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/.yarn/releases/yarn-4.7.0.cjs +0 -0
  119. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/.yarnrc.yml +0 -0
  120. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/README.md +0 -0
  121. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/REPLACE_ALL_FUNCTIONALITY.md +0 -0
  122. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/__init__.py +0 -0
  123. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/eslint.config.js +0 -0
  124. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/index.html +0 -0
  125. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/package.json +0 -0
  126. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/public/android-chrome-192x192.png +0 -0
  127. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/public/android-chrome-512x512.png +0 -0
  128. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/public/apple-touch-icon.png +0 -0
  129. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/public/favicon-16x16.png +0 -0
  130. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/public/favicon-32x32.png +0 -0
  131. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/public/favicon.ico +0 -0
  132. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/public/nomad-karaoke-logo.png +0 -0
  133. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/App.tsx +0 -0
  134. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/api.ts +0 -0
  135. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/AIFeedbackModal.tsx +0 -0
  136. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/AddLyricsModal.tsx +0 -0
  137. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/AgenticCorrectionMetrics.tsx +0 -0
  138. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/AudioPlayer.tsx +0 -0
  139. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/CorrectedWordWithActions.tsx +0 -0
  140. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/CorrectionAnnotationModal.tsx +0 -0
  141. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/CorrectionDetailCard.tsx +0 -0
  142. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/CorrectionMetrics.tsx +0 -0
  143. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/DurationTimelineView.tsx +0 -0
  144. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/EditActionBar.tsx +0 -0
  145. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/EditModal.tsx +0 -0
  146. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/EditTimelineSection.tsx +0 -0
  147. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/EditWordList.tsx +0 -0
  148. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/FileUpload.tsx +0 -0
  149. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/FindReplaceModal.tsx +0 -0
  150. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/Header.tsx +0 -0
  151. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/LyricsAnalyzer.tsx +0 -0
  152. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/MetricsDashboard.tsx +0 -0
  153. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/ModeSelector.tsx +0 -0
  154. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/ModelSelector.tsx +0 -0
  155. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/PreviewVideoSection.tsx +0 -0
  156. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/ReferenceView.tsx +0 -0
  157. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/ReplaceAllLyricsModal.tsx +0 -0
  158. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/ReviewChangesModal.tsx +0 -0
  159. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/SegmentDetailsModal.tsx +0 -0
  160. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/TimelineEditor.tsx +0 -0
  161. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/TimingOffsetModal.tsx +0 -0
  162. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/TranscriptionView.tsx +0 -0
  163. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/WordDivider.tsx +0 -0
  164. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/components/HighlightedText.tsx +0 -0
  165. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/components/SourceSelector.tsx +0 -0
  166. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/components/Word.tsx +0 -0
  167. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/constants.ts +0 -0
  168. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/hooks/useWordClick.ts +0 -0
  169. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/styles.ts +0 -0
  170. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/types.js +0 -0
  171. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/types.ts +0 -0
  172. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/utils/keyboardHandlers.ts +0 -0
  173. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/utils/localStorage.ts +0 -0
  174. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/utils/referenceLineCalculator.ts +0 -0
  175. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/utils/segmentOperations.ts +0 -0
  176. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/utils/timingUtils.ts +0 -0
  177. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/utils/wordUtils.ts +0 -0
  178. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/hooks/useManualSync.ts +0 -0
  179. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/main.tsx +0 -0
  180. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/theme.ts +0 -0
  181. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/types/global.d.ts +0 -0
  182. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/types.js +0 -0
  183. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/types.ts +0 -0
  184. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/validation.ts +0 -0
  185. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/vite-env.d.ts +0 -0
  186. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/tsconfig.app.json +0 -0
  187. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/tsconfig.json +0 -0
  188. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/tsconfig.node.json +0 -0
  189. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/tsconfig.tsbuildinfo +0 -0
  190. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/update_version.js +0 -0
  191. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/vite.config.d.ts +0 -0
  192. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/vite.config.js +0 -0
  193. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/vite.config.ts +0 -0
  194. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/web_assets/android-chrome-192x192.png +0 -0
  195. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/web_assets/android-chrome-512x512.png +0 -0
  196. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/web_assets/apple-touch-icon.png +0 -0
  197. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/web_assets/assets/index-DdJTDWH3.js +0 -0
  198. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/web_assets/assets/index-DdJTDWH3.js.map +0 -0
  199. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/web_assets/favicon-16x16.png +0 -0
  200. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/web_assets/favicon-32x32.png +0 -0
  201. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/web_assets/favicon.ico +0 -0
  202. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/web_assets/index.html +0 -0
  203. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/web_assets/nomad-karaoke-logo.png +0 -0
  204. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/yarn.lock +0 -0
  205. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/lyrics/__init__.py +0 -0
  206. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/lyrics/base_lyrics_provider.py +0 -0
  207. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/lyrics/file_provider.py +0 -0
  208. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/lyrics/genius.py +0 -0
  209. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/lyrics/lrclib.py +0 -0
  210. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/lyrics/musixmatch.py +0 -0
  211. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/lyrics/spotify.py +0 -0
  212. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/lyrics/user_input_provider.py +0 -0
  213. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/__init__.py +0 -0
  214. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/__init__.py +0 -0
  215. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/ass.py +0 -0
  216. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/ass_specs.txt +0 -0
  217. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/config.py +0 -0
  218. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/constants.py +0 -0
  219. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/event.py +0 -0
  220. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/formatters.py +0 -0
  221. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/lyrics_line.py +0 -0
  222. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/lyrics_screen.py +0 -0
  223. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/section_detector.py +0 -0
  224. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/section_screen.py +0 -0
  225. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/style.py +0 -0
  226. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdg.py +0 -0
  227. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/__init__.py +0 -0
  228. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/cdg.py +0 -0
  229. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/composer.py +0 -0
  230. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/config.py +0 -0
  231. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/images/instrumental.png +0 -0
  232. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/images/intro.png +0 -0
  233. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/pack.py +0 -0
  234. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/render.py +0 -0
  235. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/centertexttoplogobottomtext.png +0 -0
  236. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/circlein.png +0 -0
  237. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/circleout.png +0 -0
  238. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/fizzle.png +0 -0
  239. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/largecentertexttoplogo.png +0 -0
  240. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/rectangle.png +0 -0
  241. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/spiral.png +0 -0
  242. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/topleftmusicalnotes.png +0 -0
  243. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/wipein.png +0 -0
  244. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/wipeleft.png +0 -0
  245. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/wipeout.png +0 -0
  246. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/wiperight.png +0 -0
  247. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/utils.py +0 -0
  248. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/countdown_processor.py +0 -0
  249. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/fonts/AvenirNext-Bold.ttf +0 -0
  250. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/fonts/DMSans-VariableFont_opsz,wght.ttf +0 -0
  251. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/fonts/DMSerifDisplay-Regular.ttf +0 -0
  252. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/fonts/Oswald-SemiBold.ttf +0 -0
  253. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/fonts/Zurich_Cn_BT_Bold.ttf +0 -0
  254. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/fonts/arial.ttf +0 -0
  255. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/fonts/georgia.ttf +0 -0
  256. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/fonts/verdana.ttf +0 -0
  257. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/generator.py +0 -0
  258. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/lrc_to_cdg.py +0 -0
  259. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/lyrics_file.py +0 -0
  260. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/plain_text.py +0 -0
  261. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/segment_resizer.py +0 -0
  262. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/subtitles.py +0 -0
  263. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/video.py +0 -0
  264. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/review/__init__.py +0 -0
  265. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/review/server.py +0 -0
  266. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/storage/__init__.py +0 -0
  267. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/storage/dropbox.py +0 -0
  268. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/transcribers/__init__.py +0 -0
  269. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/transcribers/audioshake.py +0 -0
  270. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/transcribers/base_transcriber.py +0 -0
  271. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/transcribers/whisper.py +0 -0
  272. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/types.py +0 -0
  273. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/utils/__init__.py +0 -0
  274. {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/utils/word_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: karaoke-gen
3
- Version: 0.71.17
3
+ Version: 0.71.29
4
4
  Summary: Generate karaoke videos with synchronized lyrics. Handles the entire process from downloading audio and lyrics to creating the final video with title screens.
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -860,7 +860,7 @@ class KaraokeFinalise:
860
860
  return env_mov_input, ffmpeg_filter
861
861
 
862
862
  def remux_and_encode_output_video_files(self, with_vocals_file, input_files, output_files):
863
- self.logger.info(f"Remuxing and encoding output video files...")
863
+ self.logger.info(f"Remuxing and encoding output video files (4 formats, ~15-20 minutes total)...")
864
864
 
865
865
  # Check if output files already exist
866
866
  if os.path.isfile(output_files["final_karaoke_lossless_mp4"]) and os.path.isfile(output_files["final_karaoke_lossless_mkv"]):
@@ -871,16 +871,20 @@ class KaraokeFinalise:
871
871
  return
872
872
 
873
873
  # Create karaoke version with instrumental audio
874
+ self.logger.info(f"[Step 1/6] Remuxing video with instrumental audio...")
874
875
  self.remux_with_instrumental(with_vocals_file, input_files["instrumental_audio"], output_files["karaoke_mp4"])
875
876
 
876
877
  # Convert the with vocals video to MP4 if needed
877
878
  if not with_vocals_file.endswith(".mp4"):
879
+ self.logger.info(f"[Step 2/6] Converting karaoke video to MP4...")
878
880
  self.convert_mov_to_mp4(with_vocals_file, output_files["with_vocals_mp4"])
879
881
 
880
882
  # Delete the with vocals mov after successfully converting it to mp4
881
883
  if not self.dry_run and os.path.isfile(with_vocals_file):
882
884
  self.logger.info(f"Deleting with vocals MOV file: {with_vocals_file}")
883
885
  os.remove(with_vocals_file)
886
+ else:
887
+ self.logger.info(f"[Step 2/6] Skipped - video already in MP4 format")
884
888
 
885
889
  # Quote file paths to handle special characters
886
890
  title_mov_file = shlex.quote(os.path.abspath(input_files["title_mov"]))
@@ -889,10 +893,17 @@ class KaraokeFinalise:
889
893
  # Prepare concat filter for combining videos
890
894
  env_mov_input, ffmpeg_filter = self.prepare_concat_filter(input_files)
891
895
 
892
- # Create all output versions
896
+ # Create all output versions with progress logging
897
+ self.logger.info(f"[Step 3/6] Encoding lossless 4K MP4 (title + karaoke + end, ~5 minutes)...")
893
898
  self.encode_lossless_mp4(title_mov_file, karaoke_mp4_file, env_mov_input, ffmpeg_filter, output_files["final_karaoke_lossless_mp4"])
899
+
900
+ self.logger.info(f"[Step 4/6] Encoding lossy 4K MP4 with AAC audio (~1 minute)...")
894
901
  self.encode_lossy_mp4(output_files["final_karaoke_lossless_mp4"], output_files["final_karaoke_lossy_mp4"])
902
+
903
+ self.logger.info(f"[Step 5/6] Creating MKV with FLAC audio for YouTube (~1 minute)...")
895
904
  self.encode_lossless_mkv(output_files["final_karaoke_lossless_mp4"], output_files["final_karaoke_lossless_mkv"])
905
+
906
+ self.logger.info(f"[Step 6/6] Encoding 720p version (~3 minutes)...")
896
907
  self.encode_720p_version(output_files["final_karaoke_lossless_mp4"], output_files["final_karaoke_lossy_720p_mp4"])
897
908
 
898
909
  # Skip user confirmation in non-interactive mode for Modal deployment
@@ -1668,11 +1679,17 @@ class KaraokeFinalise:
1668
1679
  if self.dry_run:
1669
1680
  self.logger.warning("Dry run enabled. No actions will be performed.")
1670
1681
 
1682
+ self.logger.info("=" * 60)
1683
+ self.logger.info("Starting KaraokeFinalise processing pipeline")
1684
+ self.logger.info("=" * 60)
1685
+
1671
1686
  # Check required input files and parameters exist, get user to confirm features before proceeding
1672
1687
  self.validate_input_parameters_for_features()
1673
1688
 
1674
1689
  with_vocals_file = self.find_with_vocals_file()
1675
1690
  base_name, artist, title = self.get_names_from_withvocals(with_vocals_file)
1691
+
1692
+ self.logger.info(f"Processing: {artist} - {title}")
1676
1693
 
1677
1694
  # Use the selected instrumental file if provided, otherwise search for one
1678
1695
  if self.selected_instrumental_file:
@@ -1688,13 +1705,20 @@ class KaraokeFinalise:
1688
1705
  output_files = self.prepare_output_filenames(base_name)
1689
1706
 
1690
1707
  if self.enable_cdg:
1708
+ self.logger.info("Creating CDG package...")
1691
1709
  self.create_cdg_zip_file(input_files, output_files, artist, title)
1710
+ self.logger.info("CDG package created successfully")
1692
1711
 
1693
1712
  if self.enable_txt:
1713
+ self.logger.info("Creating TXT package...")
1694
1714
  self.create_txt_zip_file(input_files, output_files)
1715
+ self.logger.info("TXT package created successfully")
1695
1716
 
1717
+ self.logger.info("Starting video encoding (this is the longest step, ~15-20 minutes)...")
1696
1718
  self.remux_and_encode_output_video_files(with_vocals_file, input_files, output_files)
1719
+ self.logger.info("Video encoding completed successfully")
1697
1720
 
1721
+ self.logger.info("Executing distribution features (YouTube, Dropbox, Discord)...")
1698
1722
  self.execute_optional_features(artist, title, base_name, input_files, output_files, replace_existing)
1699
1723
 
1700
1724
  result = {
@@ -143,6 +143,70 @@ class RemoteKaraokeClient:
143
143
  response = self.session.request(method, url, **kwargs)
144
144
  return response
145
145
 
146
+ def _upload_file_to_signed_url(self, signed_url: str, file_path: str, content_type: str) -> bool:
147
+ """
148
+ Upload a file directly to GCS using a signed URL.
149
+
150
+ Args:
151
+ signed_url: The signed URL from the backend
152
+ file_path: Local path to the file to upload
153
+ content_type: MIME type for the Content-Type header
154
+
155
+ Returns:
156
+ True if upload succeeded, False otherwise
157
+ """
158
+ try:
159
+ with open(file_path, 'rb') as f:
160
+ # Use a fresh requests session (not self.session) because
161
+ # signed URLs should not have our auth headers
162
+ response = requests.put(
163
+ signed_url,
164
+ data=f,
165
+ headers={'Content-Type': content_type},
166
+ timeout=600 # 10 minutes for large files
167
+ )
168
+
169
+ if response.status_code in (200, 201):
170
+ return True
171
+ else:
172
+ self.logger.error(f"Failed to upload to signed URL: HTTP {response.status_code} - {response.text}")
173
+ return False
174
+ except Exception as e:
175
+ self.logger.error(f"Error uploading to signed URL: {e}")
176
+ return False
177
+
178
+ def _get_content_type(self, file_path: str) -> str:
179
+ """Get the MIME content type for a file based on its extension."""
180
+ ext = Path(file_path).suffix.lower()
181
+
182
+ content_types = {
183
+ # Audio
184
+ '.mp3': 'audio/mpeg',
185
+ '.wav': 'audio/wav',
186
+ '.flac': 'audio/flac',
187
+ '.m4a': 'audio/mp4',
188
+ '.ogg': 'audio/ogg',
189
+ '.aac': 'audio/aac',
190
+ # Images
191
+ '.png': 'image/png',
192
+ '.jpg': 'image/jpeg',
193
+ '.jpeg': 'image/jpeg',
194
+ '.gif': 'image/gif',
195
+ '.webp': 'image/webp',
196
+ # Fonts
197
+ '.ttf': 'font/ttf',
198
+ '.otf': 'font/otf',
199
+ '.woff': 'font/woff',
200
+ '.woff2': 'font/woff2',
201
+ # Other
202
+ '.json': 'application/json',
203
+ '.txt': 'text/plain',
204
+ '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
205
+ '.rtf': 'application/rtf',
206
+ }
207
+
208
+ return content_types.get(ext, 'application/octet-stream')
209
+
146
210
  def _parse_style_params(self, style_params_path: str) -> Dict[str, str]:
147
211
  """
148
212
  Parse style_params.json and extract file paths that need to be uploaded.
@@ -199,10 +263,26 @@ class RemoteKaraokeClient:
199
263
  # Native API distribution (uses server-side credentials)
200
264
  dropbox_path: Optional[str] = None,
201
265
  gdrive_folder_id: Optional[str] = None,
266
+ # Lyrics configuration
267
+ lyrics_artist: Optional[str] = None,
268
+ lyrics_title: Optional[str] = None,
269
+ lyrics_file: Optional[str] = None,
270
+ subtitle_offset_ms: int = 0,
271
+ # Audio separation model configuration
272
+ clean_instrumental_model: Optional[str] = None,
273
+ backing_vocals_models: Optional[list] = None,
274
+ other_stems_models: Optional[list] = None,
275
+ # Existing instrumental (Batch 3)
276
+ existing_instrumental: Optional[str] = None,
202
277
  ) -> Dict[str, Any]:
203
278
  """
204
279
  Submit a new karaoke generation job with optional style configuration.
205
280
 
281
+ Uses signed URL upload flow to bypass Cloud Run's 32MB request body limit:
282
+ 1. Create job and get signed upload URLs from backend
283
+ 2. Upload files directly to GCS using signed URLs
284
+ 3. Notify backend that uploads are complete to start processing
285
+
206
286
  Args:
207
287
  filepath: Path to audio file
208
288
  artist: Artist name
@@ -217,6 +297,14 @@ class RemoteKaraokeClient:
217
297
  enable_youtube_upload: Enable YouTube upload
218
298
  dropbox_path: Dropbox folder path for organized output (native API)
219
299
  gdrive_folder_id: Google Drive folder ID for public share (native API)
300
+ lyrics_artist: Override artist name for lyrics search
301
+ lyrics_title: Override title for lyrics search
302
+ lyrics_file: Path to user-provided lyrics file
303
+ subtitle_offset_ms: Subtitle timing offset in milliseconds
304
+ clean_instrumental_model: Model for clean instrumental separation
305
+ backing_vocals_models: List of models for backing vocals separation
306
+ other_stems_models: List of models for other stems (bass, drums, etc.)
307
+ existing_instrumental: Path to existing instrumental file to use instead of AI separation
220
308
  """
221
309
  file_path = Path(filepath)
222
310
 
@@ -230,95 +318,168 @@ class RemoteKaraokeClient:
230
318
  f"Allowed: {', '.join(self.ALLOWED_AUDIO_EXTENSIONS)}"
231
319
  )
232
320
 
233
- self.logger.info(f"Uploading audio file: {filepath}")
321
+ # Step 1: Build list of files to upload
322
+ files_info = []
323
+ local_files = {} # file_type -> local_path
324
+
325
+ # Main audio file
326
+ audio_content_type = self._get_content_type(filepath)
327
+ files_info.append({
328
+ 'filename': file_path.name,
329
+ 'content_type': audio_content_type,
330
+ 'file_type': 'audio'
331
+ })
332
+ local_files['audio'] = filepath
333
+ self.logger.info(f"Will upload audio: {filepath}")
334
+
335
+ # Parse style params and find referenced files
336
+ style_assets = {}
337
+ if style_params_path and os.path.isfile(style_params_path):
338
+ self.logger.info(f"Parsing style configuration: {style_params_path}")
339
+ style_assets = self._parse_style_params(style_params_path)
340
+
341
+ # Add style_params.json
342
+ files_info.append({
343
+ 'filename': Path(style_params_path).name,
344
+ 'content_type': 'application/json',
345
+ 'file_type': 'style_params'
346
+ })
347
+ local_files['style_params'] = style_params_path
348
+ self.logger.info(f" Will upload style_params.json")
349
+
350
+ # Add each style asset file
351
+ for asset_key, asset_path in style_assets.items():
352
+ if os.path.isfile(asset_path):
353
+ content_type = self._get_content_type(asset_path)
354
+ files_info.append({
355
+ 'filename': Path(asset_path).name,
356
+ 'content_type': content_type,
357
+ 'file_type': asset_key # e.g., 'style_intro_background'
358
+ })
359
+ local_files[asset_key] = asset_path
360
+ self.logger.info(f" Will upload {asset_key}: {asset_path}")
361
+
362
+ # Add lyrics file if provided
363
+ if lyrics_file and os.path.isfile(lyrics_file):
364
+ content_type = self._get_content_type(lyrics_file)
365
+ files_info.append({
366
+ 'filename': Path(lyrics_file).name,
367
+ 'content_type': content_type,
368
+ 'file_type': 'lyrics_file'
369
+ })
370
+ local_files['lyrics_file'] = lyrics_file
371
+ self.logger.info(f"Will upload lyrics file: {lyrics_file}")
372
+
373
+ # Add existing instrumental file if provided (Batch 3)
374
+ if existing_instrumental and os.path.isfile(existing_instrumental):
375
+ content_type = self._get_content_type(existing_instrumental)
376
+ files_info.append({
377
+ 'filename': Path(existing_instrumental).name,
378
+ 'content_type': content_type,
379
+ 'file_type': 'existing_instrumental'
380
+ })
381
+ local_files['existing_instrumental'] = existing_instrumental
382
+ self.logger.info(f"Will upload existing instrumental: {existing_instrumental}")
383
+
384
+ # Step 2: Create job and get signed upload URLs
385
+ self.logger.info(f"Creating job at {self.config.service_url}/api/jobs/create-with-upload-urls")
386
+
387
+ create_request = {
388
+ 'artist': artist,
389
+ 'title': title,
390
+ 'files': files_info,
391
+ 'enable_cdg': enable_cdg,
392
+ 'enable_txt': enable_txt,
393
+ }
234
394
 
235
- # Prepare files dict for multipart upload
236
- files_to_upload = {}
237
- files_to_close = []
395
+ if brand_prefix:
396
+ create_request['brand_prefix'] = brand_prefix
397
+ if discord_webhook_url:
398
+ create_request['discord_webhook_url'] = discord_webhook_url
399
+ if youtube_description:
400
+ create_request['youtube_description'] = youtube_description
401
+ if enable_youtube_upload:
402
+ create_request['enable_youtube_upload'] = enable_youtube_upload
403
+ if dropbox_path:
404
+ create_request['dropbox_path'] = dropbox_path
405
+ if gdrive_folder_id:
406
+ create_request['gdrive_folder_id'] = gdrive_folder_id
407
+ if organised_dir_rclone_root:
408
+ create_request['organised_dir_rclone_root'] = organised_dir_rclone_root
409
+ if lyrics_artist:
410
+ create_request['lyrics_artist'] = lyrics_artist
411
+ if lyrics_title:
412
+ create_request['lyrics_title'] = lyrics_title
413
+ if subtitle_offset_ms != 0:
414
+ create_request['subtitle_offset_ms'] = subtitle_offset_ms
415
+ if clean_instrumental_model:
416
+ create_request['clean_instrumental_model'] = clean_instrumental_model
417
+ if backing_vocals_models:
418
+ create_request['backing_vocals_models'] = backing_vocals_models
419
+ if other_stems_models:
420
+ create_request['other_stems_models'] = other_stems_models
421
+
422
+ response = self._request('POST', '/api/jobs/create-with-upload-urls', json=create_request)
238
423
 
239
- try:
240
- # Main audio file
241
- audio_file = open(filepath, 'rb')
242
- files_to_close.append(audio_file)
243
- files_to_upload['file'] = (file_path.name, audio_file)
244
-
245
- # Parse style params and find referenced files
246
- style_assets = {}
247
- if style_params_path and os.path.isfile(style_params_path):
248
- self.logger.info(f"Parsing style configuration: {style_params_path}")
249
- style_assets = self._parse_style_params(style_params_path)
250
-
251
- # Upload style_params.json
252
- style_file = open(style_params_path, 'rb')
253
- files_to_close.append(style_file)
254
- files_to_upload['style_params'] = (Path(style_params_path).name, style_file, 'application/json')
255
- self.logger.info(f" Will upload style_params.json")
256
-
257
- # Upload each style asset file
258
- for asset_key, asset_path in style_assets.items():
259
- if os.path.isfile(asset_path):
260
- asset_file = open(asset_path, 'rb')
261
- files_to_close.append(asset_file)
262
- # Determine content type
263
- ext = Path(asset_path).suffix.lower()
264
- if ext in self.ALLOWED_IMAGE_EXTENSIONS:
265
- content_type = f'image/{ext[1:]}'
266
- elif ext in self.ALLOWED_FONT_EXTENSIONS:
267
- content_type = 'font/ttf'
268
- else:
269
- content_type = 'application/octet-stream'
270
- files_to_upload[asset_key] = (Path(asset_path).name, asset_file, content_type)
271
- self.logger.info(f" Will upload {asset_key}: {asset_path}")
272
-
273
- # Prepare form data
274
- data = {
275
- 'artist': artist,
276
- 'title': title,
277
- 'enable_cdg': str(enable_cdg).lower(),
278
- 'enable_txt': str(enable_txt).lower(),
279
- }
280
-
281
- if brand_prefix:
282
- data['brand_prefix'] = brand_prefix
283
- if discord_webhook_url:
284
- data['discord_webhook_url'] = discord_webhook_url
285
- if youtube_description:
286
- data['youtube_description'] = youtube_description
287
- if enable_youtube_upload:
288
- data['enable_youtube_upload'] = str(enable_youtube_upload).lower()
289
-
290
- # Native API distribution (preferred for remote CLI)
291
- if dropbox_path:
292
- data['dropbox_path'] = dropbox_path
293
- if gdrive_folder_id:
294
- data['gdrive_folder_id'] = gdrive_folder_id
424
+ if response.status_code != 200:
425
+ try:
426
+ error_detail = response.json()
427
+ except Exception:
428
+ error_detail = response.text
429
+ raise RuntimeError(f"Error creating job: {error_detail}")
430
+
431
+ create_result = response.json()
432
+ if create_result.get('status') != 'success':
433
+ raise RuntimeError(f"Error creating job: {create_result}")
434
+
435
+ job_id = create_result['job_id']
436
+ upload_urls = create_result['upload_urls']
437
+
438
+ self.logger.info(f"Job {job_id} created. Uploading {len(upload_urls)} files directly to storage...")
439
+
440
+ # Step 3: Upload each file directly to GCS using signed URLs
441
+ uploaded_files = []
442
+ for url_info in upload_urls:
443
+ file_type = url_info['file_type']
444
+ signed_url = url_info['upload_url']
445
+ content_type = url_info['content_type']
446
+ local_path = local_files.get(file_type)
295
447
 
296
- # Legacy rclone distribution (deprecated)
297
- if organised_dir_rclone_root:
298
- data['organised_dir_rclone_root'] = organised_dir_rclone_root
448
+ if not local_path:
449
+ self.logger.warning(f"No local file found for file_type: {file_type}")
450
+ continue
299
451
 
300
- self.logger.info(f"Submitting job to {self.config.service_url}/api/jobs/upload")
452
+ # Calculate file size for logging
453
+ file_size = os.path.getsize(local_path)
454
+ file_size_mb = file_size / (1024 * 1024)
455
+ self.logger.info(f" Uploading {file_type} ({file_size_mb:.1f} MB)...")
301
456
 
302
- response = self._request('POST', '/api/jobs/upload', files=files_to_upload, data=data)
457
+ success = self._upload_file_to_signed_url(signed_url, local_path, content_type)
458
+ if not success:
459
+ raise RuntimeError(f"Failed to upload {file_type} to storage")
303
460
 
304
- finally:
305
- # Close all opened files
306
- for f in files_to_close:
307
- try:
308
- f.close()
309
- except:
310
- pass
461
+ uploaded_files.append(file_type)
462
+ self.logger.info(f" ✓ Uploaded {file_type}")
463
+
464
+ # Step 4: Notify backend that uploads are complete
465
+ self.logger.info(f"Notifying backend that uploads are complete...")
466
+
467
+ complete_request = {
468
+ 'uploaded_files': uploaded_files
469
+ }
470
+
471
+ response = self._request('POST', f'/api/jobs/{job_id}/uploads-complete', json=complete_request)
311
472
 
312
473
  if response.status_code != 200:
313
474
  try:
314
475
  error_detail = response.json()
315
476
  except Exception:
316
477
  error_detail = response.text
317
- raise RuntimeError(f"Error submitting job: {error_detail}")
478
+ raise RuntimeError(f"Error completing uploads: {error_detail}")
318
479
 
319
480
  result = response.json()
320
481
  if result.get('status') != 'success':
321
- raise RuntimeError(f"Error submitting job: {result}")
482
+ raise RuntimeError(f"Error completing uploads: {result}")
322
483
 
323
484
  # Log distribution services info if available
324
485
  if 'distribution_services' in result:
@@ -610,6 +771,40 @@ class JobMonitor:
610
771
  self._last_timeline_index = 0
611
772
  self._last_log_index = 0
612
773
  self._show_worker_logs = True # Enable worker log display
774
+ self._polls_without_updates = 0 # Track polling activity for heartbeat
775
+ self._heartbeat_interval = 6 # Show heartbeat every N polls without updates (~30s with 5s poll)
776
+
777
+ # Status descriptions for user-friendly logging
778
+ STATUS_DESCRIPTIONS = {
779
+ 'pending': 'Job queued, waiting to start',
780
+ 'downloading': 'Downloading and preparing input files',
781
+ 'separating_stage1': 'AI audio separation (stage 1 of 2)',
782
+ 'separating_stage2': 'AI audio separation (stage 2 of 2)',
783
+ 'audio_complete': 'Audio separation complete',
784
+ 'transcribing': 'Transcribing lyrics from audio',
785
+ 'correcting': 'Auto-correcting lyrics against reference sources',
786
+ 'lyrics_complete': 'Lyrics processing complete',
787
+ 'generating_screens': 'Creating title and end screens',
788
+ 'applying_padding': 'Adding intro/outro padding',
789
+ 'awaiting_review': 'Waiting for lyrics review',
790
+ 'in_review': 'Lyrics review in progress',
791
+ 'review_complete': 'Review complete, preparing video render',
792
+ 'rendering_video': 'Rendering karaoke video with lyrics',
793
+ 'awaiting_instrumental_selection': 'Waiting for instrumental selection',
794
+ 'instrumental_selected': 'Instrumental selected, preparing final encoding',
795
+ 'generating_video': 'Downloading files for final video encoding',
796
+ 'encoding': 'Encoding final videos (15-20 min, 4 formats)',
797
+ 'packaging': 'Creating CDG/TXT packages',
798
+ 'uploading': 'Uploading to distribution services',
799
+ 'notifying': 'Sending notifications',
800
+ 'complete': 'All processing complete',
801
+ 'failed': 'Job failed',
802
+ 'cancelled': 'Job cancelled',
803
+ }
804
+
805
+ def _get_status_description(self, status: str) -> str:
806
+ """Get user-friendly description for a status."""
807
+ return self.STATUS_DESCRIPTIONS.get(status, status)
613
808
 
614
809
  def open_browser(self, url: str) -> None:
615
810
  """Open URL in the default browser."""
@@ -1101,6 +1296,7 @@ class JobMonitor:
1101
1296
 
1102
1297
  self.logger.info(f"Monitoring job: {job_id}")
1103
1298
  self.logger.info(f"Service URL: {self.config.service_url}")
1299
+ self.logger.info(f"Polling every {self.config.poll_interval} seconds...")
1104
1300
  self.logger.info("")
1105
1301
 
1106
1302
  while True:
@@ -1111,16 +1307,40 @@ class JobMonitor:
1111
1307
  artist = job_data.get('artist', '')
1112
1308
  title = job_data.get('title', '')
1113
1309
 
1310
+ # Track whether we got any new updates this poll
1311
+ had_updates = False
1312
+ prev_timeline_index = self._last_timeline_index
1313
+ prev_log_index = self._last_log_index
1314
+
1114
1315
  # Log timeline updates (shows status changes and progress)
1115
1316
  self.log_timeline_updates(job_data)
1317
+ if self._last_timeline_index > prev_timeline_index:
1318
+ had_updates = True
1116
1319
 
1117
1320
  # Log worker logs (shows detailed worker output for debugging)
1118
1321
  self.log_worker_logs(job_id)
1322
+ if self._last_log_index > prev_log_index:
1323
+ had_updates = True
1119
1324
 
1120
- # Log status changes
1325
+ # Log status changes with user-friendly descriptions
1121
1326
  if status != last_status:
1122
- self.logger.info(f"Status changed: {last_status} -> {status}")
1327
+ description = self._get_status_description(status)
1328
+ if last_status:
1329
+ self.logger.info(f"Status: {status} - {description}")
1330
+ else:
1331
+ self.logger.info(f"Current status: {status} - {description}")
1123
1332
  last_status = status
1333
+ had_updates = True
1334
+
1335
+ # Heartbeat: if no updates for a while, show we're still alive
1336
+ if had_updates:
1337
+ self._polls_without_updates = 0
1338
+ else:
1339
+ self._polls_without_updates += 1
1340
+ if self._polls_without_updates >= self._heartbeat_interval:
1341
+ description = self._get_status_description(status)
1342
+ self.logger.info(f" [Still processing: {description}]")
1343
+ self._polls_without_updates = 0
1124
1344
 
1125
1345
  # Handle human interaction points
1126
1346
  if status in ['awaiting_review', 'in_review']:
@@ -1559,8 +1779,6 @@ def main():
1559
1779
  ignored_features.append("--skip-transcription")
1560
1780
  if args.lyrics_only:
1561
1781
  ignored_features.append("--lyrics-only")
1562
- if args.existing_instrumental:
1563
- ignored_features.append("--existing_instrumental")
1564
1782
  if args.background_video:
1565
1783
  ignored_features.append("--background_video")
1566
1784
  if getattr(args, 'auto_download', False):
@@ -1655,6 +1873,24 @@ def main():
1655
1873
  logger.info(f"Dropbox (rclone): {args.organised_dir_rclone_root}")
1656
1874
  if args.discord_webhook_url:
1657
1875
  logger.info(f"Discord: enabled")
1876
+ # Lyrics configuration
1877
+ if getattr(args, 'lyrics_artist', None):
1878
+ logger.info(f"Lyrics Artist Override: {args.lyrics_artist}")
1879
+ if getattr(args, 'lyrics_title', None):
1880
+ logger.info(f"Lyrics Title Override: {args.lyrics_title}")
1881
+ if getattr(args, 'lyrics_file', None):
1882
+ logger.info(f"Lyrics File: {args.lyrics_file}")
1883
+ if getattr(args, 'subtitle_offset_ms', 0):
1884
+ logger.info(f"Subtitle Offset: {args.subtitle_offset_ms}ms")
1885
+ # Audio model configuration
1886
+ if getattr(args, 'clean_instrumental_model', None):
1887
+ logger.info(f"Clean Instrumental Model: {args.clean_instrumental_model}")
1888
+ if getattr(args, 'backing_vocals_models', None):
1889
+ logger.info(f"Backing Vocals Models: {args.backing_vocals_models}")
1890
+ if getattr(args, 'other_stems_models', None):
1891
+ logger.info(f"Other Stems Models: {args.other_stems_models}")
1892
+ if getattr(args, 'existing_instrumental', None):
1893
+ logger.info(f"Existing Instrumental: {args.existing_instrumental}")
1658
1894
  logger.info(f"Service URL: {config.service_url}")
1659
1895
  logger.info(f"Review UI: {config.review_ui_url}")
1660
1896
  if config.non_interactive:
@@ -1688,6 +1924,17 @@ def main():
1688
1924
  # Native API distribution (preferred for remote CLI)
1689
1925
  dropbox_path=getattr(args, 'dropbox_path', None),
1690
1926
  gdrive_folder_id=getattr(args, 'gdrive_folder_id', None),
1927
+ # Lyrics configuration
1928
+ lyrics_artist=getattr(args, 'lyrics_artist', None),
1929
+ lyrics_title=getattr(args, 'lyrics_title', None),
1930
+ lyrics_file=getattr(args, 'lyrics_file', None),
1931
+ subtitle_offset_ms=getattr(args, 'subtitle_offset_ms', 0) or 0,
1932
+ # Audio separation model configuration
1933
+ clean_instrumental_model=getattr(args, 'clean_instrumental_model', None),
1934
+ backing_vocals_models=getattr(args, 'backing_vocals_models', None),
1935
+ other_stems_models=getattr(args, 'other_stems_models', None),
1936
+ # Existing instrumental (Batch 3)
1937
+ existing_instrumental=getattr(args, 'existing_instrumental', None),
1691
1938
  )
1692
1939
  job_id = result.get('job_id')
1693
1940
  style_assets = result.get('style_assets_uploaded', [])