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.
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/PKG-INFO +1 -1
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/karaoke_finalise/karaoke_finalise.py +26 -2
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/utils/remote_cli.py +325 -78
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/anchor_sequence.py +68 -68
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/pyproject.toml +1 -1
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/LICENSE +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/README.md +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/audio_fetcher.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/audio_processor.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/config.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/file_handler.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/karaoke_finalise/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/karaoke_gen.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/lyrics_processor.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/metadata.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/base.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/context.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/executors/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/executors/local.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/executors/remote.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/stages/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/stages/finalize.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/stages/render.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/stages/screens.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/stages/separation.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/pipeline/stages/transcription.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/resources/AvenirNext-Bold.ttf +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/resources/Montserrat-Bold.ttf +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/resources/Oswald-Bold.ttf +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/resources/Oswald-SemiBold.ttf +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/resources/Zurich_Cn_BT_Bold.ttf +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/style_loader.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/utils/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/utils/bulk_cli.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/utils/cli_args.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/utils/gen_cli.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/video_background_processor.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/video_generator.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/cli/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/cli/cli_main.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/core/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/core/config.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/core/controller.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/adapter.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/agent.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/feedback/aggregator.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/feedback/collector.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/feedback/retention.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/feedback/store.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/ambiguous.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/background_vocals.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/base.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/complex_multi_error.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/extra_words.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/no_error.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/punctuation.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/registry.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/repeated_section.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/handlers/sound_alike.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/models/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/models/ai_correction.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/models/correction_session.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/models/enums.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/models/human_feedback.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/models/learning_data.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/models/observability_metrics.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/models/schemas.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/models/utils.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/observability/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/observability/langfuse_integration.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/observability/metrics.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/observability/performance.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/prompts/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/prompts/classifier.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/base.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/circuit_breaker.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/config.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/constants.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/health.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/langchain_bridge.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/model_factory.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/response_cache.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/response_parser.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/providers/retry_executor.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/router.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/workflows/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/workflows/consensus_workflow.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/workflows/correction_graph.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/agentic/workflows/feedback_workflow.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/corrector.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/feedback/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/feedback/schemas.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/feedback/store.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/base.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/extend_anchor.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/levenshtein.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/llm.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/llm_providers.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/no_space_punct_match.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/relaxed_word_count_match.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/repeat.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/sound_alike.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/syllables_match.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/word_count_match.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/handlers/word_operations.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/operations.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/phrase_analyzer.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/correction/text_utils.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/.gitignore +0 -0
- {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
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/.yarnrc.yml +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/README.md +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/REPLACE_ALL_FUNCTIONALITY.md +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/eslint.config.js +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/index.html +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/package.json +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/public/android-chrome-192x192.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/public/android-chrome-512x512.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/public/apple-touch-icon.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/public/favicon-16x16.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/public/favicon-32x32.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/public/favicon.ico +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/public/nomad-karaoke-logo.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/App.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/api.ts +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/AIFeedbackModal.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/AddLyricsModal.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/AgenticCorrectionMetrics.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/AudioPlayer.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/CorrectedWordWithActions.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/CorrectionAnnotationModal.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/CorrectionDetailCard.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/CorrectionMetrics.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/DurationTimelineView.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/EditActionBar.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/EditModal.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/EditTimelineSection.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/EditWordList.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/FileUpload.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/FindReplaceModal.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/Header.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/LyricsAnalyzer.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/MetricsDashboard.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/ModeSelector.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/ModelSelector.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/PreviewVideoSection.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/ReferenceView.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/ReplaceAllLyricsModal.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/ReviewChangesModal.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/SegmentDetailsModal.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/TimelineEditor.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/TimingOffsetModal.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/TranscriptionView.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/WordDivider.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/components/HighlightedText.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/components/SourceSelector.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/components/Word.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/constants.ts +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/hooks/useWordClick.ts +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/styles.ts +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/types.js +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/types.ts +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/utils/keyboardHandlers.ts +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/utils/localStorage.ts +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/utils/referenceLineCalculator.ts +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/utils/segmentOperations.ts +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/utils/timingUtils.ts +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/components/shared/utils/wordUtils.ts +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/hooks/useManualSync.ts +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/main.tsx +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/theme.ts +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/types/global.d.ts +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/types.js +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/types.ts +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/validation.ts +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/src/vite-env.d.ts +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/tsconfig.app.json +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/tsconfig.json +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/tsconfig.node.json +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/tsconfig.tsbuildinfo +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/update_version.js +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/vite.config.d.ts +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/vite.config.js +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/vite.config.ts +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/web_assets/android-chrome-192x192.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/web_assets/android-chrome-512x512.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/web_assets/apple-touch-icon.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/web_assets/assets/index-DdJTDWH3.js +0 -0
- {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
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/web_assets/favicon-16x16.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/web_assets/favicon-32x32.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/web_assets/favicon.ico +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/web_assets/index.html +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/web_assets/nomad-karaoke-logo.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/frontend/yarn.lock +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/lyrics/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/lyrics/base_lyrics_provider.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/lyrics/file_provider.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/lyrics/genius.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/lyrics/lrclib.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/lyrics/musixmatch.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/lyrics/spotify.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/lyrics/user_input_provider.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/ass.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/ass_specs.txt +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/config.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/constants.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/event.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/formatters.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/lyrics_line.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/lyrics_screen.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/section_detector.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/section_screen.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/ass/style.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdg.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/cdg.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/composer.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/config.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/images/instrumental.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/images/intro.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/pack.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/render.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/centertexttoplogobottomtext.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/circlein.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/circleout.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/fizzle.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/largecentertexttoplogo.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/rectangle.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/spiral.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/topleftmusicalnotes.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/wipein.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/wipeleft.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/wipeout.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/transitions/wiperight.png +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/cdgmaker/utils.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/countdown_processor.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/fonts/AvenirNext-Bold.ttf +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/fonts/DMSans-VariableFont_opsz,wght.ttf +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/fonts/DMSerifDisplay-Regular.ttf +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/fonts/Oswald-SemiBold.ttf +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/fonts/Zurich_Cn_BT_Bold.ttf +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/fonts/arial.ttf +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/fonts/georgia.ttf +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/fonts/verdana.ttf +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/generator.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/lrc_to_cdg.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/lyrics_file.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/plain_text.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/segment_resizer.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/subtitles.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/output/video.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/review/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/review/server.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/storage/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/storage/dropbox.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/transcribers/__init__.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/transcribers/audioshake.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/transcribers/base_transcriber.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/transcribers/whisper.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/types.py +0 -0
- {karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/lyrics_transcriber_temp/lyrics_transcriber/utils/__init__.py +0 -0
- {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.
|
|
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
|
{karaoke_gen-0.71.17 → karaoke_gen-0.71.29}/karaoke_gen/karaoke_finalise/karaoke_finalise.py
RENAMED
|
@@ -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
|
-
|
|
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
|
-
|
|
236
|
-
|
|
237
|
-
|
|
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
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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
|
-
|
|
297
|
-
|
|
298
|
-
|
|
448
|
+
if not local_path:
|
|
449
|
+
self.logger.warning(f"No local file found for file_type: {file_type}")
|
|
450
|
+
continue
|
|
299
451
|
|
|
300
|
-
|
|
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
|
-
|
|
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
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
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
|
|
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
|
|
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.
|
|
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', [])
|