Spaces:
Sleeping
Sleeping
| """ | |
| Baby Cry Analysis - Flask API for Hugging Face Spaces | |
| Exposes REST endpoint for audio-based baby cry classification. | |
| Wrapped with Gradio to keep the Space alive. | |
| """ | |
| from flask import Flask, request, jsonify | |
| import tempfile | |
| import os | |
| import logging | |
| import threading | |
| # Configure logging | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| # Import inference module (model loads at import time) | |
| from inference import analyze_cry, preload_model | |
| # Preload model at startup | |
| preload_model() | |
| app = Flask(__name__) | |
| # Maximum file size: 16MB | |
| app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 | |
| # Allowed audio extensions | |
| ALLOWED_EXTENSIONS = {'wav', 'mp3', 'ogg', 'flac', 'm4a', 'webm'} | |
| def allowed_file(filename: str) -> bool: | |
| """Check if file extension is allowed.""" | |
| return '.' in filename and \ | |
| filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS | |
| def health(): | |
| """Health check endpoint.""" | |
| return jsonify({"status": "healthy", "service": "baby-cry-ai"}) | |
| def analyze(): | |
| """ | |
| Analyze baby cry audio file. | |
| Expects multipart/form-data with 'audio' file field. | |
| Returns: | |
| JSON with cry analysis results: | |
| - cry_detected: boolean | |
| - top_reason: string (hunger, belly_pain, tired, discomfort, burping) | |
| - scores: object with confidence scores per label | |
| - disclaimer: legal disclaimer string | |
| """ | |
| # Validate request has audio file | |
| if "audio" not in request.files: | |
| return jsonify({ | |
| "error": "No audio file provided", | |
| "message": "Please upload an audio file with key 'audio'" | |
| }), 400 | |
| audio = request.files["audio"] | |
| # Validate filename exists | |
| if audio.filename == '': | |
| return jsonify({ | |
| "error": "Empty filename", | |
| "message": "No file selected" | |
| }), 400 | |
| # Validate file extension | |
| if not allowed_file(audio.filename): | |
| return jsonify({ | |
| "error": "Invalid file type", | |
| "message": f"Allowed types: {', '.join(ALLOWED_EXTENSIONS)}" | |
| }), 400 | |
| # Get original extension for temp file | |
| ext = audio.filename.rsplit('.', 1)[1].lower() | |
| try: | |
| # Save to temporary file for processing | |
| with tempfile.NamedTemporaryFile(delete=False, suffix=f".{ext}") as tmp: | |
| audio.save(tmp.name) | |
| temp_path = tmp.name | |
| logger.info(f"Processing audio file: {temp_path}") | |
| # Run inference | |
| result = analyze_cry(temp_path) | |
| # Add disclaimer | |
| result["disclaimer"] = "AI-generated suggestion, not a medical diagnosis. Please consult a healthcare professional for medical advice." | |
| logger.info(f"Analysis successful: {result['top_reason']}") | |
| return jsonify(result) | |
| except Exception as e: | |
| logger.error(f"Analysis failed: {str(e)}", exc_info=True) | |
| return jsonify({ | |
| "error": "Analysis failed", | |
| "message": str(e) | |
| }), 500 | |
| finally: | |
| # Clean up temp file | |
| if 'temp_path' in locals() and os.path.exists(temp_path): | |
| os.unlink(temp_path) | |
| def too_large(e): | |
| """Handle file too large error.""" | |
| return jsonify({ | |
| "error": "File too large", | |
| "message": "Maximum file size is 16MB" | |
| }), 413 | |
| def run_flask(): | |
| """Run Flask app in background thread.""" | |
| app.run(host="0.0.0.0", port=7860, debug=False, use_reloader=False) | |
| # Start Flask in background thread | |
| flask_thread = threading.Thread(target=run_flask, daemon=True) | |
| flask_thread.start() | |
| # Gradio UI to keep the Space alive | |
| import gradio as gr | |
| with gr.Blocks() as demo: | |
| gr.Markdown(""" | |
| # 👶 Baby Cry Analysis API | |
| This Space hosts a REST API for analyzing baby cries using machine learning. | |
| ## 🔗 API Endpoints | |
| ### Health Check | |
| ``` | |
| GET /health | |
| ``` | |
| ### Analyze Cry | |
| ``` | |
| POST /analyze-cry | |
| Content-Type: multipart/form-data | |
| Body: audio=<file> | |
| ``` | |
| **Supported formats:** WAV, MP3, OGG, FLAC, M4A, WebM | |
| ## 📡 Example Usage | |
| ```python | |
| import requests | |
| with open("baby_cry.wav", "rb") as f: | |
| response = requests.post( | |
| "https://YOUR-SPACE.hf.space/analyze-cry", | |
| files={"audio": f} | |
| ) | |
| print(response.json()) | |
| ``` | |
| ## 📊 Response Format | |
| ```json | |
| { | |
| "cry_detected": true, | |
| "top_reason": "hunger", | |
| "scores": { | |
| "hunger": 0.45, | |
| "belly_pain": 0.20, | |
| "tired": 0.15, | |
| "discomfort": 0.12, | |
| "burping": 0.08 | |
| }, | |
| "disclaimer": "AI-generated suggestion..." | |
| } | |
| ``` | |
| --- | |
| ⚠️ *This is an AI-generated suggestion, not a medical diagnosis.* | |
| """) | |
| demo.launch(server_name="0.0.0.0", server_port=7865) | |