Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import tensorflow as tf | |
| import librosa | |
| import librosa.display | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| import sounddevice as sd | |
| import soundfile as sf | |
| import threading | |
| # Load the pre-trained model | |
| model = tf.keras.models.load_model("model.h5") | |
| # Function to process audio, predict, and generate results | |
| def process_audio(audio_file, breath_in_time, breath_out_time): | |
| try: | |
| # Calculate total recording duration | |
| total_time = breath_in_time + breath_out_time | |
| # Load the audio file | |
| y, sr = librosa.load(audio_file, sr=16000) | |
| # Detect segments (e.g., using energy or silence) | |
| intervals = librosa.effects.split(y, top_db=20) | |
| results = [] | |
| plt.figure(figsize=(10, 4)) | |
| librosa.display.waveshow(y, sr=sr, alpha=0.5) | |
| # Process each segment | |
| for i, (start, end) in enumerate(intervals): | |
| segment = y[start:end] | |
| duration = (end - start) / sr | |
| # Compute the amplitude (mean absolute value) | |
| amplitude = np.mean(np.abs(segment)) | |
| # Extract MFCC features | |
| mfcc = librosa.feature.mfcc(y=segment, sr=sr, n_mfcc=13) | |
| mfcc = np.mean(mfcc, axis=1).reshape(1, -1) | |
| # Predict inhale or exhale | |
| prediction = model.predict(mfcc) | |
| label_from_model = "Inhale" if np.argmax(prediction) == 0 else "Exhale" | |
| # Assign label based on amplitude | |
| label = "Inhale" if amplitude > 0.05 else "Exhale" # Threshold for exhale | |
| # Append results | |
| results.append({ | |
| "Segment": i + 1, | |
| "Type": label, | |
| "Duration (s)": round(duration, 2), | |
| "Amplitude": round(amplitude, 4) | |
| }) | |
| # Highlight segment on waveform with swapped colors | |
| plt.axvspan(start / sr, end / sr, color='red' if label == "Inhale" else 'blue', alpha=0.3) | |
| # Save the waveform with highlighted segments | |
| plt.title("Audio Waveform with Inhale/Exhale Segments") | |
| plt.xlabel("Time (s)") | |
| plt.ylabel("Amplitude") | |
| plt.savefig("waveform_highlighted.png") | |
| plt.close() | |
| # Format results as a table | |
| result_table = "Segment\tType\tDuration (s)\tAmplitude\n" + "\n".join( | |
| f"{row['Segment']}\t{row['Type']}\t{row['Duration (s)']}\t{row['Amplitude']}" for row in results | |
| ) | |
| return result_table, "waveform_highlighted.png" | |
| except Exception as e: | |
| return f"Error: {str(e)}", None | |
| # Function to record audio for a specified duration | |
| def record_audio(duration): | |
| try: | |
| # Define the file name | |
| audio_file = "recorded_audio.wav" | |
| # Record audio | |
| print(f"Recording for {duration} seconds...") | |
| recording = sd.rec(int(duration * 16000), samplerate=16000, channels=1, dtype='float32') | |
| sd.wait() # Wait until recording is finished | |
| sf.write(audio_file, recording, 16000) | |
| print("Recording complete!") | |
| return audio_file | |
| except Exception as e: | |
| return f"Error: {str(e)}" | |
| # Function to animate the scaling circle (during recording) | |
| def create_circle_animation(duration): | |
| # HTML and CSS to create the animated circle | |
| circle_animation = f""" | |
| <div id="circle-container" style="text-align:center; margin-top: 50px;"> | |
| <div id="circle" style="width: 50px; height: 50px; border-radius: 50%; background-color: #3498db; animation: scale-up-down {duration}s infinite;"></div> | |
| </div> | |
| <style> | |
| @keyframes scale-up-down {{ | |
| 0% {{ transform: scale(1); }} | |
| 50% {{ transform: scale(1.5); }} | |
| 100% {{ transform: scale(1); }} | |
| }} | |
| </style> | |
| """ | |
| return circle_animation | |
| # Define Gradio interface | |
| with gr.Blocks() as demo: | |
| gr.Markdown("### Breathe Training Application") | |
| with gr.Row(): | |
| breath_in_time = gr.Number(label="Breath In Time (seconds)", value=0, interactive=True) | |
| breath_out_time = gr.Number(label="Breath Out Time (seconds)", value=0, interactive=True) | |
| with gr.Row(): | |
| audio_input = gr.Audio(type="filepath", label="Upload Audio (optional)") | |
| result_output = gr.Textbox(label="Prediction Results (Table)") | |
| waveform_output = gr.Image(label="Waveform with Highlighted Segments") | |
| circle_output = gr.HTML(label="Breath Circle Animation") | |
| submit_button = gr.Button("Analyze") | |
| def handle_record_and_analyze(breath_in, breath_out): | |
| total_duration = breath_in + breath_out | |
| circle_animation = create_circle_animation(total_duration) | |
| audio_file = record_audio(total_duration) | |
| result_table, waveform_image = process_audio(audio_file, breath_in, breath_out) | |
| return circle_animation, result_table, waveform_image | |
| submit_button.click( | |
| fn=process_audio, | |
| inputs=[audio_input, breath_in_time, breath_out_time], | |
| outputs=[result_output, waveform_output], | |
| ) | |
| # Run the Gradio app | |
| demo.launch() | |
| # re load |