Spaces:
Sleeping
Sleeping
File size: 5,706 Bytes
8b4cd24 feaf7eb 40f2bca 8b4cd24 40f2bca 8b4cd24 feaf7eb 8b4cd24 40f2bca 8b4cd24 40f2bca 8b4cd24 feaf7eb 8b4cd24 feaf7eb 8b4cd24 feaf7eb 8b4cd24 feaf7eb 8b4cd24 feaf7eb 8b4cd24 feaf7eb 8b4cd24 feaf7eb 8b4cd24 40f2bca 8b4cd24 feaf7eb 8b4cd24 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | from flask import Flask, request, jsonify
from flask_cors import CORS
import uuid
import os
from datetime import datetime
from config import config
from concurrent.futures import ThreadPoolExecutor
import threading
from audio_processor import get_processor
app = Flask(__name__)
CORS(app) # Enable CORS for Streamlit
# Thread pool for background processing
executor = ThreadPoolExecutor(max_workers=4)
# In-memory storage for job status
jobs = {}
jobs_lock = threading.Lock()
# Preload model on startup
print("=" * 60)
print("INITIALIZING APPLICATION...")
print("=" * 60)
try:
print("Preloading emotion detection model...")
processor = get_processor()
processor.load_model()
print("✅ Model preloaded successfully!")
print("=" * 60)
except Exception as e:
print(f"⚠️ Warning: Failed to preload model: {e}")
print("Model will be loaded on first request.")
print("=" * 60)
# Upload folder for temporary audio files
UPLOAD_FOLDER = 'uploads'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 50 * 1024 * 1024 # 50MB max file size
# Allowed audio extensions
ALLOWED_EXTENSIONS = {'wav', 'mp3', 'ogg', 'flac', 'm4a'}
def allowed_file(filename):
"""Check if file extension is allowed"""
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/health', methods=['GET'])
def health_check():
"""Health check endpoint"""
return jsonify({
"status": "healthy",
"timestamp": datetime.now().isoformat(),
"model": config.MODEL_NAME,
"version": "1.0.0"
})
@app.route('/config', methods=['GET'])
def get_config():
"""Get current configuration"""
return jsonify({
"model_name": config.MODEL_NAME,
"chunk_duration": config.CHUNK_DURATION,
"sample_rate": config.SAMPLE_RATE,
"emotions": config.EMOTIONS
})
@app.route('/upload', methods=['POST'])
def upload_audio():
"""
Upload audio file and start processing
Returns job_id for tracking progress
"""
# Check if file is present in request
if 'file' not in request.files:
return jsonify({"error": "No file provided"}), 400
file = request.files['file']
# Check if file is selected
if file.filename == '':
return jsonify({"error": "No file selected"}), 400
# Check if file type is allowed
if not allowed_file(file.filename):
return jsonify({
"error": f"Invalid file type. Allowed: {', '.join(ALLOWED_EXTENSIONS)}"
}), 400
# Generate unique job ID
job_id = str(uuid.uuid4())
# Save file
filename = f"{job_id}_{file.filename}"
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(filepath)
# Initialize job status
with jobs_lock:
jobs[job_id] = {
"status": "queued",
"progress": 0,
"message": "Audio file uploaded, waiting to process...",
"filename": file.filename,
"filepath": filepath,
"created_at": datetime.now().isoformat()
}
# Submit background processing task
executor.submit(process_audio, job_id, filepath)
return jsonify({
"job_id": job_id,
"message": "File uploaded successfully, processing started"
}), 202
@app.route('/status/<job_id>', methods=['GET'])
def get_status(job_id):
"""
Get processing status for a job
Returns progress and results when complete
"""
if job_id not in jobs:
return jsonify({"error": "Job not found"}), 404
job = jobs[job_id]
response = {
"job_id": job_id,
"status": job["status"],
"progress": job["progress"],
"message": job["message"]
}
# If completed, include results
if job["status"] == "completed":
response["results"] = job.get("results", {})
# If failed, include error
if job["status"] == "failed":
response["error"] = job.get("error", "Unknown error")
return jsonify(response)
def process_audio(job_id, filepath):
"""
Process audio file and extract emotions
This runs in a background thread
"""
try:
# Get audio processor
processor = get_processor()
# Progress callback function
def update_progress(progress, message):
with jobs_lock:
jobs[job_id]["progress"] = progress
jobs[job_id]["message"] = message
# Update status to processing
with jobs_lock:
jobs[job_id]["status"] = "processing"
# Process audio file with real ML model
results = processor.process_audio_file(filepath, progress_callback=update_progress)
# Mark as completed
with jobs_lock:
jobs[job_id]["progress"] = 100
jobs[job_id]["status"] = "completed"
jobs[job_id]["message"] = "Analysis complete!"
jobs[job_id]["results"] = results
# Clean up uploaded file after processing
try:
os.remove(filepath)
except:
pass
except Exception as e:
with jobs_lock:
jobs[job_id]["status"] = "failed"
jobs[job_id]["progress"] = 0
jobs[job_id]["message"] = f"Processing failed"
jobs[job_id]["error"] = str(e)
if __name__ == '__main__':
app.run(
debug=config.FLASK_DEBUG,
host=config.FLASK_HOST,
port=config.FLASK_PORT,
use_reloader=False # Disable auto-reload to prevent socket errors
)
|