File size: 2,251 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
"""
Baby Cry Analysis - Inference Module
Optimized for Hugging Face Spaces with eager model loading.
"""

import logging

logger = logging.getLogger(__name__)

# Model loaded at module level for single load
_model = None

# Supported cry reason labels
LABELS = ["hunger", "belly_pain", "tired", "discomfort", "burping"]


def preload_model():
    """
    Eagerly load the model at startup.
    Called once when the app starts to avoid cold start delays.
    """
    global _model
    if _model is None:
        logger.info("🔄 Loading baby cry classification model at startup...")
        from transformers import pipeline
        _model = pipeline(
            "audio-classification",
            model="Wiam/baby-cry-classification-finetuned-babycry-v4"
        )
        logger.info("✅ Model loaded successfully!")
    return _model


def get_model():
    """Get the loaded model instance."""
    global _model
    if _model is None:
        return preload_model()
    return _model


def analyze_cry(audio_path: str) -> dict:
    """
    Analyze a baby cry audio file using the supervised classification model.
    
    Args:
        audio_path: Path to the audio file (WAV format preferred)
        
    Returns:
        Dictionary containing:
        - cry_detected: boolean indicating if a cry was detected
        - top_reason: the most likely reason for crying
        - scores: confidence scores for each label
    """
    # Get preloaded model
    model = get_model()
    
    # Get supervised model predictions
    results = model(audio_path)
    
    # Build scores dictionary from model output
    scores = {}
    for r in results:
        label = r["label"]
        if label in LABELS:
            scores[label] = round(r["score"], 4)
    
    # Ensure all labels have a score (default 0 if missing)
    for label in LABELS:
        if label not in scores:
            scores[label] = 0.0
    
    # Determine top prediction
    top_label = max(scores, key=scores.get)
    top_confidence = scores[top_label]
    
    # Cry detection threshold
    cry_detected = top_confidence >= 0.1
    
    return {
        "cry_detected": cry_detected,
        "top_reason": top_label if cry_detected else None,
        "scores": scores
    }