csprojectworkspace commited on
Commit
c01d934
·
verified ·
1 Parent(s): 0007a53

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +84 -30
app.py CHANGED
@@ -4,9 +4,56 @@ import numpy as np
4
  import librosa
5
  import io
6
  import os
 
 
7
 
8
  app = Flask(__name__)
9
- CORS(app, resources={r"/api/*": {"origins": "*"}})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  @app.after_request
12
  def after_request(response):
@@ -17,7 +64,7 @@ def after_request(response):
17
 
18
  @app.route('/', methods=['GET'])
19
  def home():
20
- return jsonify({'message': 'AcoustiTrack API - CNN-1D VAD + GCC-PHAT DOA', 'status': 'running'})
21
 
22
  @app.route('/api/health', methods=['GET', 'OPTIONS'])
23
  def health():
@@ -34,42 +81,48 @@ def analyze():
34
  return jsonify({'error': 'Aucun fichier audio'}), 400
35
 
36
  audio_file = request.files['audio']
37
- audio_bytes = audio_file.read()
38
-
39
- y, sr = librosa.load(io.BytesIO(audio_bytes), sr=16000, mono=False)
40
 
 
41
  if y.ndim == 1:
 
42
  y = np.tile(y, (4, 1))
 
 
43
 
44
  n_channels = y.shape[0] if y.ndim > 1 else 1
45
  duration = y.shape[-1] / sr
 
46
 
47
- # ============================================
48
- # VOTRE MODELE CNN-1D ICI
49
- # Chargez votre modele et faites l'inference
50
- # ============================================
51
- vad_prediction = "voice"
52
- vad_confidence = 0.962
53
- doa_angle = -25.5
54
 
55
- n_frames = max(1, int(duration * 10))
 
56
  vad_timeline = []
57
  for i in range(n_frames):
 
 
 
 
 
 
 
 
 
 
58
  vad_timeline.append({
59
  'start': round(i * 0.1, 2),
60
  'end': round((i + 1) * 0.1, 2),
61
- 'label': 'voice' if np.random.random() > 0.3 else 'silence',
62
- 'confidence': round(0.85 + np.random.random() * 0.15, 3)
63
  })
64
 
65
- doa_trajectory = []
66
- for i in range(n_frames):
67
- doa_trajectory.append({
68
- 'time': round(i * 0.1, 2),
69
- 'angle': round(doa_angle + np.random.randn() * 5, 1)
70
- })
71
 
72
- voice_frames = sum(1 for f in vad_timeline if f['label'] == 'voice')
73
 
74
  return jsonify({
75
  'success': True,
@@ -80,24 +133,25 @@ def analyze():
80
  'samples': int(y.shape[-1])
81
  },
82
  'vad': {
83
- 'prediction': vad_prediction,
84
- 'confidence': vad_confidence,
85
  'timeline': vad_timeline
86
  },
87
  'doa': {
88
- 'angle': doa_angle,
89
  'confidence': 0.89,
90
  'trajectory': doa_trajectory
91
  },
92
  'metrics': {
93
- 'snr': 18.5,
94
- 'voiceRatio': round(voice_frames / len(vad_timeline), 2),
95
- 'meanDoa': round(float(np.mean([d['angle'] for d in doa_trajectory])), 1)
96
  }
97
  })
98
  except Exception as e:
 
 
99
  return jsonify({'error': str(e)}), 500
100
 
101
  if __name__ == '__main__':
102
- port = int(os.environ.get('PORT', 7860))
103
- app.run(host='0.0.0.0', port=port)
 
4
  import librosa
5
  import io
6
  import os
7
+ import gdown
8
+ import tensorflow as tf
9
 
10
  app = Flask(__name__)
11
+ CORS(app)
12
+
13
+ # Telecharger et charger le modele au demarrage
14
+ MODEL_URL = "https://drive.google.com/uc?id=1_eUJwfSSab9bQFW5Ow4kL54OMr6cGaO0"
15
+ MODEL_PATH = "/app/model.h5"
16
+
17
+ print("Telechargement du modele CNN-1D...")
18
+ gdown.download(MODEL_URL, MODEL_PATH, quiet=False)
19
+ print("Chargement du modele...")
20
+ model = tf.keras.models.load_model(MODEL_PATH)
21
+ print("Modele charge avec succes!")
22
+ print(f"Input shape: {model.input_shape}")
23
+ print(f"Output shape: {model.output_shape}")
24
+
25
+ def extract_mfcc(audio, sr, n_mfcc=13):
26
+ """Extrait les MFCC du signal audio"""
27
+ mfccs = librosa.feature.mfcc(y=audio, sr=sr, n_mfcc=n_mfcc)
28
+ # Normaliser
29
+ mfccs = (mfccs - np.mean(mfccs)) / (np.std(mfccs) + 1e-8)
30
+ return mfccs
31
+
32
+ def predict_vad(audio, sr):
33
+ """Prediction VAD avec le modele CNN-1D"""
34
+ # Extraire MFCC
35
+ mfccs = extract_mfcc(audio, sr, n_mfcc=13)
36
+
37
+ # Adapter la forme pour le modele (ajuster selon votre modele)
38
+ # Shape typique: (batch, time_steps, n_mfcc) ou (batch, n_mfcc, time_steps)
39
+ features = mfccs.T # (time_steps, n_mfcc)
40
+ features = np.expand_dims(features, axis=0) # (1, time_steps, n_mfcc)
41
+
42
+ # Prediction
43
+ prediction = model.predict(features, verbose=0)
44
+
45
+ # Interpreter la sortie (ajuster selon votre modele)
46
+ if prediction.shape[-1] == 2:
47
+ # Classification binaire avec softmax
48
+ confidence = float(np.max(prediction))
49
+ label = "voice" if np.argmax(prediction) == 1 else "silence"
50
+ else:
51
+ # Classification binaire avec sigmoid
52
+ confidence = float(prediction[0][0])
53
+ label = "voice" if confidence > 0.5 else "silence"
54
+ confidence = confidence if label == "voice" else 1 - confidence
55
+
56
+ return label, confidence
57
 
58
  @app.after_request
59
  def after_request(response):
 
64
 
65
  @app.route('/', methods=['GET'])
66
  def home():
67
+ return jsonify({'message': 'AcoustiTrack API', 'status': 'running', 'model': 'CNN-1D VAD'})
68
 
69
  @app.route('/api/health', methods=['GET', 'OPTIONS'])
70
  def health():
 
81
  return jsonify({'error': 'Aucun fichier audio'}), 400
82
 
83
  audio_file = request.files['audio']
84
+ y, sr = librosa.load(io.BytesIO(audio_file.read()), sr=16000, mono=False)
 
 
85
 
86
+ # Gerer mono/multi-canal
87
  if y.ndim == 1:
88
+ y_mono = y
89
  y = np.tile(y, (4, 1))
90
+ else:
91
+ y_mono = np.mean(y, axis=0)
92
 
93
  n_channels = y.shape[0] if y.ndim > 1 else 1
94
  duration = y.shape[-1] / sr
95
+ n_frames = max(1, int(duration * 10))
96
 
97
+ # Prediction VAD avec le modele CNN-1D
98
+ vad_label, vad_confidence = predict_vad(y_mono, sr)
 
 
 
 
 
99
 
100
+ # Generer timeline VAD frame par frame
101
+ frame_length = len(y_mono) // n_frames
102
  vad_timeline = []
103
  for i in range(n_frames):
104
+ start_sample = i * frame_length
105
+ end_sample = min((i + 1) * frame_length, len(y_mono))
106
+ frame_audio = y_mono[start_sample:end_sample]
107
+
108
+ if len(frame_audio) > sr * 0.05: # Au moins 50ms
109
+ frame_label, frame_conf = predict_vad(frame_audio, sr)
110
+ else:
111
+ frame_label = vad_label
112
+ frame_conf = vad_confidence
113
+
114
  vad_timeline.append({
115
  'start': round(i * 0.1, 2),
116
  'end': round((i + 1) * 0.1, 2),
117
+ 'label': frame_label,
118
+ 'confidence': round(frame_conf, 3)
119
  })
120
 
121
+ # DOA estimation (simulation - remplacer par GCC-PHAT reel si disponible)
122
+ doa_angle = -25.5 + np.random.randn() * 10
123
+ doa_trajectory = [{'time': round(i*0.1,2), 'angle': round(doa_angle + np.random.randn()*3, 1)} for i in range(n_frames)]
 
 
 
124
 
125
+ voice_ratio = sum(1 for f in vad_timeline if f['label'] == 'voice') / len(vad_timeline)
126
 
127
  return jsonify({
128
  'success': True,
 
133
  'samples': int(y.shape[-1])
134
  },
135
  'vad': {
136
+ 'prediction': vad_label,
137
+ 'confidence': round(vad_confidence, 3),
138
  'timeline': vad_timeline
139
  },
140
  'doa': {
141
+ 'angle': round(doa_angle, 1),
142
  'confidence': 0.89,
143
  'trajectory': doa_trajectory
144
  },
145
  'metrics': {
146
+ 'snr': round(10 * np.log10(np.mean(y_mono**2) / 1e-10), 1),
147
+ 'voiceRatio': round(voice_ratio, 2),
148
+ 'meanDoa': round(np.mean([d['angle'] for d in doa_trajectory]), 1)
149
  }
150
  })
151
  except Exception as e:
152
+ import traceback
153
+ traceback.print_exc()
154
  return jsonify({'error': str(e)}), 500
155
 
156
  if __name__ == '__main__':
157
+ app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 7860)))