vitorcalvi commited on
Commit
4014343
·
1 Parent(s): b4ace77
Files changed (3) hide show
  1. README.md +1 -12
  2. main.py +112 -0
  3. requirements.txt +7 -0
README.md CHANGED
@@ -1,12 +1 @@
1
- ---
2
- title: Dyagnosysapi
3
- emoji: 🏆
4
- colorFrom: indigo
5
- colorTo: purple
6
- sdk: docker
7
- pinned: false
8
- license: apache-2.0
9
- short_description: API
10
- ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
+ # dyagnosysAPI
 
 
 
 
 
 
 
 
 
 
 
main.py ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # main.py
2
+
3
+ from fastapi import FastAPI, File, UploadFile, HTTPException, Form
4
+ from fastapi.responses import JSONResponse
5
+ from pydantic import BaseModel
6
+ import librosa
7
+ import numpy as np
8
+ import tempfile
9
+ import os
10
+ import warnings
11
+ import re
12
+ import matplotlib.pyplot as plt
13
+
14
+ warnings.filterwarnings("ignore", category=UserWarning, module='librosa')
15
+
16
+ app = FastAPI()
17
+
18
+ def extract_audio_features(audio_file_path):
19
+ # Load the audio file and extract features
20
+ y, sr = librosa.load(audio_file_path, sr=None)
21
+ f0, voiced_flag, voiced_probs = librosa.pyin(y, fmin=75, fmax=600)
22
+ f0 = f0[~np.isnan(f0)]
23
+ energy = librosa.feature.rms(y=y)[0]
24
+ mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)
25
+ onset_env = librosa.onset.onset_strength(y=y, sr=sr)
26
+ tempo, _ = librosa.beat.beat_track(onset_envelope=onset_env, sr=sr)
27
+ speech_rate = tempo / 60
28
+ return f0, energy, speech_rate, mfccs, y, sr
29
+
30
+ def analyze_voice_stress(audio_file_path):
31
+ f0, energy, speech_rate, mfccs, y, sr = extract_audio_features(audio_file_path)
32
+ mean_f0 = np.mean(f0)
33
+ std_f0 = np.std(f0)
34
+ mean_energy = np.mean(energy)
35
+ std_energy = np.std(energy)
36
+ gender = 'male' if mean_f0 < 165 else 'female'
37
+ norm_mean_f0 = 110 if gender == 'male' else 220
38
+ norm_std_f0 = 20
39
+ norm_mean_energy = 0.02
40
+ norm_std_energy = 0.005
41
+ norm_speech_rate = 4.4
42
+ norm_std_speech_rate = 0.5
43
+ z_f0 = (mean_f0 - norm_mean_f0) / norm_std_f0
44
+ z_energy = (mean_energy - norm_mean_energy) / norm_std_energy
45
+ z_speech_rate = (speech_rate - norm_speech_rate) / norm_std_speech_rate
46
+ stress_score = (0.4 * z_f0) + (0.4 * z_speech_rate) + (0.2 * z_energy)
47
+ stress_level = float(1 / (1 + np.exp(-stress_score)) * 100)
48
+ categories = ["Very Low Stress", "Low Stress", "Moderate Stress", "High Stress", "Very High Stress"]
49
+ category_idx = min(int(stress_level / 20), 4)
50
+ stress_category = categories[category_idx]
51
+ return {"stress_level": stress_level, "category": stress_category, "gender": gender}
52
+
53
+ def analyze_text_stress(text: str):
54
+ # Placeholder text stress analysis
55
+ stress_keywords = ["anxious", "nervous", "stress", "panic", "tense"]
56
+ stress_score = sum([1 for word in stress_keywords if word in text.lower()])
57
+
58
+ # Normalize the score for a basic assessment
59
+ stress_level = min(stress_score * 20, 100)
60
+ categories = ["Very Low Stress", "Low Stress", "Moderate Stress", "High Stress", "Very High Stress"]
61
+ category_idx = min(int(stress_level / 20), 4)
62
+ stress_category = categories[category_idx]
63
+
64
+ return {"stress_level": stress_level, "category": stress_category}
65
+
66
+ class StressResponse(BaseModel):
67
+ stress_level: float
68
+ category: str
69
+ gender: str = None # Optional, only for audio analysis
70
+
71
+ @app.post("/analyze-stress/", response_model=StressResponse)
72
+ async def analyze_stress(
73
+ file: UploadFile = File(None),
74
+ file_path: str = Form(None),
75
+ text: str = Form(None)
76
+ ):
77
+ if file is None and file_path is None and text is None:
78
+ raise HTTPException(status_code=400, detail="Either a file, file path, or text input is required.")
79
+
80
+ # Handle audio file analysis
81
+ if file or file_path:
82
+ if file:
83
+ if not file.filename.endswith(".wav"):
84
+ raise HTTPException(status_code=400, detail="Only .wav files are supported.")
85
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as temp_file:
86
+ temp_file.write(await file.read())
87
+ temp_file_path = temp_file.name
88
+ else:
89
+ if not file_path.endswith(".wav"):
90
+ raise HTTPException(status_code=400, detail="Only .wav files are supported.")
91
+ if not os.path.exists(file_path):
92
+ raise HTTPException(status_code=400, detail="File path does not exist.")
93
+ temp_file_path = file_path
94
+
95
+ try:
96
+ result = analyze_voice_stress(temp_file_path)
97
+ return JSONResponse(content=result)
98
+ except Exception as e:
99
+ raise HTTPException(status_code=500, detail=str(e))
100
+ finally:
101
+ if file:
102
+ os.remove(temp_file_path)
103
+
104
+ # Handle text analysis
105
+ elif text:
106
+ result = analyze_text_stress(text)
107
+ return JSONResponse(content=result)
108
+
109
+ if __name__ == "__main__":
110
+ import uvicorn
111
+ port = int(os.getenv("PORT", 8000)) # Use the PORT environment variable for Render compatibility
112
+ uvicorn.run("main:app", host="0.0.0.0", port=port, reload=True)
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ pydantic
4
+ librosa
5
+ numpy
6
+ matplotlib
7
+ python-multipart