Spaces:
Sleeping
Sleeping
File size: 5,007 Bytes
9b4e272 | 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 | """
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
@app.route("/health", methods=["GET"])
def health():
"""Health check endpoint."""
return jsonify({"status": "healthy", "service": "baby-cry-ai"})
@app.route("/analyze-cry", methods=["POST"])
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)
@app.errorhandler(413)
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=7861)
|