Dimsumcat commited on
Commit
1a09d3b
·
verified ·
1 Parent(s): dbff8ac

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +55 -73
app.py CHANGED
@@ -1,7 +1,6 @@
1
  import gradio as gr
2
  import tensorflow as tf
3
  import librosa
4
- import librosa.display
5
  import numpy as np
6
  import matplotlib.pyplot as plt
7
  import sounddevice as sd
@@ -11,17 +10,19 @@ import threading
11
  # Load the pre-trained model
12
  model = tf.keras.models.load_model("model.h5")
13
 
14
- # Function to process audio, predict, and generate results
15
  def process_audio(audio_file, breath_in_time, breath_out_time):
16
  try:
 
 
 
17
  # Load the audio file
18
  y, sr = librosa.load(audio_file, sr=16000)
19
 
20
- # Detect segments (e.g., using energy or silence)
21
  intervals = librosa.effects.split(y, top_db=20)
22
 
23
  results = []
24
-
25
  plt.figure(figsize=(10, 4))
26
  librosa.display.waveshow(y, sr=sr, alpha=0.5)
27
 
@@ -29,8 +30,6 @@ def process_audio(audio_file, breath_in_time, breath_out_time):
29
  for i, (start, end) in enumerate(intervals):
30
  segment = y[start:end]
31
  duration = (end - start) / sr
32
-
33
- # Compute the amplitude (mean absolute value)
34
  amplitude = np.mean(np.abs(segment))
35
 
36
  # Extract MFCC features
@@ -39,9 +38,10 @@ def process_audio(audio_file, breath_in_time, breath_out_time):
39
 
40
  # Predict inhale or exhale
41
  prediction = model.predict(mfcc)
42
- label = "Inhale" if np.argmax(prediction) == 0 else "Exhale"
 
 
43
 
44
- # Append results
45
  results.append({
46
  "Segment": i + 1,
47
  "Type": label,
@@ -49,17 +49,14 @@ def process_audio(audio_file, breath_in_time, breath_out_time):
49
  "Amplitude": round(amplitude, 4)
50
  })
51
 
52
- # Highlight segment on waveform
53
  plt.axvspan(start / sr, end / sr, color='red' if label == "Inhale" else 'blue', alpha=0.3)
54
 
55
- # Save the waveform with highlighted segments
56
  plt.title("Audio Waveform with Inhale/Exhale Segments")
57
  plt.xlabel("Time (s)")
58
  plt.ylabel("Amplitude")
59
  plt.savefig("waveform_highlighted.png")
60
  plt.close()
61
 
62
- # Format results as a table
63
  result_table = "Segment\tType\tDuration (s)\tAmplitude\n" + "\n".join(
64
  f"{row['Segment']}\t{row['Type']}\t{row['Duration (s)']}\t{row['Amplitude']}" for row in results
65
  )
@@ -69,92 +66,77 @@ def process_audio(audio_file, breath_in_time, breath_out_time):
69
  except Exception as e:
70
  return f"Error: {str(e)}", None
71
 
72
- # Function to record audio for a specified duration
73
  def record_audio(duration):
74
  try:
75
  audio_file = "recorded_audio.wav"
76
- print(f"Recording for {duration} seconds...")
77
  recording = sd.rec(int(duration * 16000), samplerate=16000, channels=1, dtype='float32')
78
  sd.wait()
79
  sf.write(audio_file, recording, 16000)
80
- print("Recording complete!")
81
  return audio_file
82
  except Exception as e:
83
  return f"Error: {str(e)}"
84
 
85
- # Gradio Interface
86
  with gr.Blocks() as demo:
87
  gr.Markdown("### Breathe Training Application")
88
 
89
- # Breath cycle configuration
90
  with gr.Row():
91
- breath_in_time = gr.Number(label="Breathe In Time (seconds)", value=3, interactive=True)
92
- breath_out_time = gr.Number(label="Breathe Out Time (seconds)", value=3, interactive=True)
93
-
94
- # Circle Animation using Custom HTML and CSS
95
- gr.HTML("""
96
- <div style="text-align: center;">
97
- <div id="circle" style="
98
- width: 100px;
99
- height: 100px;
100
- border-radius: 50%;
101
- background-color: lightblue;
102
- margin: 20px auto;
103
- animation: breathe 6s infinite;">
104
- </div>
105
- <p id="instruction" style="font-size: 20px; font-weight: bold;">Breathe In...</p>
106
- </div>
107
- <style>
108
- @keyframes breathe {
109
- 0% { transform: scale(1); }
110
- 50% { transform: scale(1.5); }
111
- 100% { transform: scale(1); }
112
- }
113
- </style>
114
- <script>
115
- const instruction = document.getElementById("instruction");
116
- let breatheInTime = 3; // Default value for inhale
117
- let breatheOutTime = 3; // Default value for exhale
118
-
119
- function updateBreathingCycle(inTime, outTime) {
120
- breatheInTime = inTime;
121
- breatheOutTime = outTime;
122
- const totalTime = inTime + outTime;
123
- const keyframes = `
124
- @keyframes breathe {
125
- 0% { transform: scale(1); }
126
- ${Math.round((inTime / totalTime) * 100)}% { transform: scale(1.5); }
127
- 100% { transform: scale(1); }
128
- }
129
- `;
130
- const styleSheet = document.styleSheets[0];
131
- styleSheet.insertRule(keyframes, styleSheet.cssRules.length);
132
-
133
- let isInhaling = true;
134
- setInterval(() => {
135
- instruction.textContent = isInhaling ? "Breathe In..." : "Breathe Out...";
136
- isInhaling = !isInhaling;
137
- }, inTime * 1000);
138
- }
139
-
140
- // Default breathing cycle
141
- updateBreathingCycle(breatheInTime, breatheOutTime);
142
- </script>
143
- """)
144
 
145
- # File upload and analysis
146
  with gr.Row():
147
  record_button = gr.Button("Start Recording")
148
  audio_input = gr.Audio(type="filepath", label="Upload Audio (optional)")
149
  result_output = gr.Textbox(label="Prediction Results (Table)")
150
  waveform_output = gr.Image(label="Waveform with Highlighted Segments")
151
 
152
- # Handle recording and analysis
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  record_button.click(
154
- fn=lambda breath_in, breath_out: process_audio(record_audio(breath_in + breath_out), breath_in, breath_out),
155
  inputs=[breath_in_time, breath_out_time],
156
  outputs=[result_output, waveform_output],
157
  )
158
 
159
- # Run the Gradio app
160
  demo.launch()
 
1
  import gradio as gr
2
  import tensorflow as tf
3
  import librosa
 
4
  import numpy as np
5
  import matplotlib.pyplot as plt
6
  import sounddevice as sd
 
10
  # Load the pre-trained model
11
  model = tf.keras.models.load_model("model.h5")
12
 
13
+
14
  def process_audio(audio_file, breath_in_time, breath_out_time):
15
  try:
16
+ # Calculate total recording duration
17
+ total_time = breath_in_time + breath_out_time
18
+
19
  # Load the audio file
20
  y, sr = librosa.load(audio_file, sr=16000)
21
 
22
+ # Detect segments
23
  intervals = librosa.effects.split(y, top_db=20)
24
 
25
  results = []
 
26
  plt.figure(figsize=(10, 4))
27
  librosa.display.waveshow(y, sr=sr, alpha=0.5)
28
 
 
30
  for i, (start, end) in enumerate(intervals):
31
  segment = y[start:end]
32
  duration = (end - start) / sr
 
 
33
  amplitude = np.mean(np.abs(segment))
34
 
35
  # Extract MFCC features
 
38
 
39
  # Predict inhale or exhale
40
  prediction = model.predict(mfcc)
41
+ label_from_model = "Inhale" if np.argmax(prediction) == 0 else "Exhale"
42
+
43
+ label = "Inhale" if amplitude > 0.05 else "Exhale"
44
 
 
45
  results.append({
46
  "Segment": i + 1,
47
  "Type": label,
 
49
  "Amplitude": round(amplitude, 4)
50
  })
51
 
 
52
  plt.axvspan(start / sr, end / sr, color='red' if label == "Inhale" else 'blue', alpha=0.3)
53
 
 
54
  plt.title("Audio Waveform with Inhale/Exhale Segments")
55
  plt.xlabel("Time (s)")
56
  plt.ylabel("Amplitude")
57
  plt.savefig("waveform_highlighted.png")
58
  plt.close()
59
 
 
60
  result_table = "Segment\tType\tDuration (s)\tAmplitude\n" + "\n".join(
61
  f"{row['Segment']}\t{row['Type']}\t{row['Duration (s)']}\t{row['Amplitude']}" for row in results
62
  )
 
66
  except Exception as e:
67
  return f"Error: {str(e)}", None
68
 
69
+
70
  def record_audio(duration):
71
  try:
72
  audio_file = "recorded_audio.wav"
 
73
  recording = sd.rec(int(duration * 16000), samplerate=16000, channels=1, dtype='float32')
74
  sd.wait()
75
  sf.write(audio_file, recording, 16000)
 
76
  return audio_file
77
  except Exception as e:
78
  return f"Error: {str(e)}"
79
 
80
+
81
  with gr.Blocks() as demo:
82
  gr.Markdown("### Breathe Training Application")
83
 
 
84
  with gr.Row():
85
+ breath_in_time = gr.Number(label="Breath In Time (seconds)", value=3, interactive=True)
86
+ breath_out_time = gr.Number(label="Breath Out Time (seconds)", value=3, interactive=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
 
88
  with gr.Row():
89
  record_button = gr.Button("Start Recording")
90
  audio_input = gr.Audio(type="filepath", label="Upload Audio (optional)")
91
  result_output = gr.Textbox(label="Prediction Results (Table)")
92
  waveform_output = gr.Image(label="Waveform with Highlighted Segments")
93
 
94
+ with gr.HTML(value="""
95
+ <div style="display: flex; justify-content: center; align-items: center; height: 300px;">
96
+ <div id="circle" style="width: 50px; height: 50px; background-color: lightblue; border-radius: 50%;"></div>
97
+ </div>
98
+ <script>
99
+ let interval;
100
+ function scaleCircle(breathIn, breathOut, duration) {
101
+ const circle = document.getElementById('circle');
102
+ let scaleUp = true;
103
+ const breathInTime = breathIn * 1000;
104
+ const breathOutTime = breathOut * 1000;
105
+
106
+ if (interval) clearInterval(interval);
107
+
108
+ interval = setInterval(() => {
109
+ if (scaleUp) {
110
+ circle.style.transition = `transform ${breathInTime}ms linear`;
111
+ circle.style.transform = "scale(3)";
112
+ } else {
113
+ circle.style.transition = `transform ${breathOutTime}ms linear`;
114
+ circle.style.transform = "scale(1)";
115
+ }
116
+ scaleUp = !scaleUp;
117
+ }, duration * 1000);
118
+ }
119
+
120
+ function stopCircleAnimation() {
121
+ const circle = document.getElementById('circle');
122
+ clearInterval(interval);
123
+ circle.style.transform = "scale(1)";
124
+ circle.style.transition = "none";
125
+ }
126
+ </script>
127
+ """)
128
+
129
+ def handle_record_and_visualize(breath_in, breath_out):
130
+ total_duration = breath_in + breath_out
131
+ threading.Timer(total_duration, lambda: gr.run_js("stopCircleAnimation()")).start()
132
+ gr.run_js(f"scaleCircle({breath_in}, {breath_out}, {total_duration});")
133
+ audio_file = record_audio(total_duration)
134
+ return process_audio(audio_file, breath_in, breath_out)
135
+
136
  record_button.click(
137
+ fn=handle_record_and_visualize,
138
  inputs=[breath_in_time, breath_out_time],
139
  outputs=[result_output, waveform_output],
140
  )
141
 
 
142
  demo.launch()