audioSentiment / flask_app.py
temp12821's picture
working prototype of the audio processing module
feaf7eb
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
)