Spaces:
Sleeping
Sleeping
| import os | |
| import json | |
| import subprocess | |
| import re | |
| import time | |
| import logging | |
| import numpy as np | |
| # Apply all compatibility patches early (NumPy, SciPy, madmom, librosa) | |
| from compat import apply_all as apply_compat_patches | |
| apply_compat_patches() | |
| from dotenv import load_dotenv | |
| from flask import Flask, request, jsonify, render_template | |
| from flask_cors import CORS | |
| from flask_limiter import Limiter | |
| from flask_limiter.util import get_remote_address | |
| import tempfile | |
| # import soundfile as sf # Optional dependency | |
| import traceback | |
| import sys | |
| from pathlib import Path | |
| import requests | |
| import random | |
| # Import the new app factory and utilities | |
| from app_factory import create_app | |
| from utils.logging import log_info, log_error, log_debug | |
| from utils.import_utils import lazy_import_librosa | |
| from utils.model_utils import ( | |
| check_spleeter_availability, check_beat_transformer_availability, | |
| check_chord_cnn_lstm_availability, check_genius_availability, | |
| check_btc_availability | |
| ) | |
| # Configure logging for production (will be overridden by app_factory) | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' | |
| ) | |
| logger = logging.getLogger(__name__) | |
| # Set production mode based on environment | |
| PRODUCTION_MODE = os.environ.get('FLASK_ENV', 'production') == 'production' or os.environ.get('PORT') is not None | |
| # import aiotube # Removed - not needed for cloud deployment | |
| # import quicktube # Removed - QuickTube is a Ruby web app, not a Python package | |
| # Load environment variables from .env file | |
| try: | |
| dotenv_path = Path(__file__).with_name('.env') | |
| if dotenv_path.is_file(): | |
| load_dotenv(dotenv_path=dotenv_path) | |
| log_debug("Loaded environment variables from backend/.env") | |
| except ImportError: | |
| log_debug("python-dotenv not available, using system environment variables only") | |
| # Audio processing utilities moved to utils/audio_utils.py | |
| # Music theory utilities moved to utils/music_theory_utils.py | |
| # Defer heavy imports until needed | |
| # Import utilities moved to utils/import_utils.py | |
| # Add the model directories to the Python path | |
| BEAT_TRANSFORMER_DIR = Path(__file__).parent / "models" / "Beat-Transformer" | |
| CHORD_CNN_LSTM_DIR = Path(__file__).parent / "models" / "Chord-CNN-LSTM" | |
| AUDIO_DIR = Path(__file__).parent.parent / "public" / "audio" | |
| log_debug(f"Audio directory path: {AUDIO_DIR}") | |
| sys.path.insert(0, str(BEAT_TRANSFORMER_DIR)) | |
| sys.path.insert(0, str(CHORD_CNN_LSTM_DIR)) | |
| # Import the unified beat transformer implementation | |
| try: | |
| from models.beat_transformer import BeatTransformerDetector, run_beat_tracking_wrapper | |
| log_debug("Using unified beat_transformer implementation") | |
| # Create a simple wrapper function for the detect_beats endpoint | |
| def run_beat_tracking(audio_file): | |
| detector = BeatTransformerDetector() | |
| return detector.detect_beats(audio_file) | |
| except ImportError as e: | |
| log_error(f"Warning: beat_transformer not found: {e}, beat tracking will be disabled") | |
| def run_beat_tracking(audio_file): | |
| return {"beats": [], "downbeats": [], "bpm": 120.0, "time_signature": 4} | |
| run_beat_tracking_wrapper = None | |
| # Create Flask app using the application factory | |
| app = create_app() | |
| # Get the limiter from extensions for use in route decorators | |
| from extensions import limiter | |
| # Fix for Python 3.10+ compatibility with madmom | |
| # MUST come before any madmom imports | |
| try: | |
| import collections | |
| import collections.abc | |
| collections.MutableSequence = collections.abc.MutableSequence | |
| log_debug("Applied collections.MutableSequence patch for madmom compatibility") | |
| except Exception as e: | |
| log_error(f"Failed to apply madmom compatibility patch: {e}") | |
| # Fix for NumPy 1.20+ compatibility | |
| # These attributes are deprecated in newer NumPy versions | |
| try: | |
| np.float = float # Use built-in float instead | |
| np.int = int # Use built-in int instead | |
| log_debug("Applied NumPy compatibility fixes for np.float and np.int") | |
| except Exception as e: | |
| log_debug(f"Note: NumPy compatibility patch not needed: {e}") | |
| # Defer all heavy checks to runtime - just assume everything is available for startup | |
| SPLEETER_AVAILABLE = True # Will check at runtime | |
| USE_BEAT_TRANSFORMER = True # Will check at runtime | |
| USE_CHORD_CNN_LSTM = True # Will check at runtime | |
| GENIUS_AVAILABLE = True # Will check at runtime | |
| log_debug("Deferred model availability checks to runtime for faster startup") | |
| # Runtime model availability checks | |
| # Model availability check functions moved to utils/model_utils.py | |
| # Root route moved to health blueprint | |
| # Debug endpoints moved to debug blueprint | |
| # Health route moved to health blueprint | |
| # Beat detection route moved to beats blueprint | |
| # Chord recognition route moved to chords blueprint | |
| # BTC chord recognition functions moved to chords blueprint | |
| # BTC chord recognition function moved to chords blueprint | |
| # BTC chord recognition routes moved to chords blueprint | |
| # Check if BTC models are available | |
| # BTC availability check function moved to utils/model_utils.py | |
| # Global BTC availability check | |
| BTC_AVAILABILITY = check_btc_availability() | |
| USE_BTC_SL = BTC_AVAILABILITY['sl_available'] | |
| USE_BTC_PL = BTC_AVAILABILITY['pl_available'] | |
| # Model info route moved to beats blueprint | |
| # Lyrics routes moved to lyrics blueprint | |
| # Documentation routes moved to docs blueprint | |
| # BTC debug endpoints moved to debug blueprint | |
| # BTC import test endpoints moved to debug blueprint | |
| # Beat detection test routes moved to beats blueprint | |
| # Test madmom route moved to beats blueprint | |
| # Chord-CNN-LSTM test endpoints moved to debug blueprint | |
| # All remaining debug and test endpoints moved to debug blueprint | |
| # Test DBN isolation route moved to beats blueprint | |
| # Test all models route moved to beats blueprint | |
| # YouTube search routes moved to youtube blueprint | |
| # Audio extraction routes moved to audio blueprint | |
| # Detect beats Firebase route moved to beats blueprint | |
| # Firebase chord recognition route moved to chords blueprint | |
| if __name__ == '__main__': | |
| # Get port from environment variable or default to 5001 for localhost to avoid macOS AirTunes/AirPlay conflicts | |
| # Production deployments (Cloud Run) will override this with PORT environment variable | |
| port = int(os.environ.get('PORT', 5001)) | |
| log_info(f"Starting Flask app on port {port}") | |
| log_info("App is ready to serve requests") | |
| app.run(host='0.0.0.0', port=port, debug=False, load_dotenv=False) | |