dschandra commited on
Commit
a843dd5
·
verified ·
1 Parent(s): 30e1c24

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +112 -66
app.py CHANGED
@@ -1,17 +1,18 @@
1
  from flask import Flask, render_template_string, request, jsonify
2
- from datetime import datetime
3
- import speech_recognition as sr # Import speech recognition
4
  from tempfile import NamedTemporaryFile
5
- import ffmpeg
6
  import os
 
 
 
7
 
 
8
  app = Flask(__name__)
9
 
10
- # Initialize an empty list to store orders
11
- orders = []
12
- user_preferences = {"diet": "all"} # Default to all
13
 
14
- # HTML code for the frontend
15
  html_code = """
16
  <!DOCTYPE html>
17
  <html lang="en">
@@ -75,60 +76,69 @@ html_code = """
75
  <body>
76
  <h1>AI Dining Assistant</h1>
77
  <button class="mic-button" id="mic-button">🎤</button>
78
- <div class="status" id="status">Press the mic button to start listening...</div>
79
  <div class="response" id="response" style="display: none;">Response will appear here...</div>
80
  <script>
81
  const micButton = document.getElementById('mic-button');
82
  const status = document.getElementById('status');
83
  const response = document.getElementById('response');
84
- if (!window.MediaRecorder) {
85
- alert("Your browser does not support audio recording.");
86
- }
87
  let mediaRecorder;
88
  let audioChunks = [];
89
- micButton.addEventListener('click', async () => {
90
- navigator.mediaDevices.getUserMedia({ audio: true })
91
- .then(stream => {
92
- mediaRecorder = new MediaRecorder(stream);
93
- mediaRecorder.start();
94
- status.textContent = 'Listening...';
95
- status.classList.add('listening');
96
- audioChunks = [];
97
- mediaRecorder.ondataavailable = event => {
98
- audioChunks.push(event.data);
99
- };
100
- mediaRecorder.onstop = async () => {
101
- const audioBlob = new Blob(audioChunks, { type: 'audio/wav; codecs=LINEAR16' });
102
- const formData = new FormData();
103
- formData.append('audio', audioBlob);
104
- status.textContent = 'Processing...';
105
- status.classList.remove('listening');
106
- try {
107
- const result = await fetch('/process-audio', {
108
- method: 'POST',
109
- body: formData,
110
- });
111
- const data = await result.json();
112
- response.textContent = data.response;
113
- response.style.display = 'block';
114
- status.textContent = 'Press the mic button to start listening...';
115
- // Use browser text-to-speech
116
- const utterance = new SpeechSynthesisUtterance(data.response);
117
- speechSynthesis.speak(utterance);
118
- } catch (error) {
119
- response.textContent = 'Error occurred. Please try again.';
120
- response.style.display = 'block';
121
- status.textContent = 'Press the mic button to start listening...';
122
- }
123
- };
124
- setTimeout(() => {
125
- mediaRecorder.stop();
126
- }, 5000); // Stop recording after 5 seconds
127
- })
128
- .catch(err => {
129
- status.textContent = 'Microphone access denied.';
130
- });
131
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  </script>
133
  </body>
134
  </html>
@@ -141,37 +151,73 @@ def index():
141
  @app.route('/process-audio', methods=['POST'])
142
  def process_audio():
143
  try:
144
- audio_file = request.files['audio']
145
- # Save the uploaded file temporarily
146
- temp_file = NamedTemporaryFile(delete=False, suffix=".wav")
 
 
 
147
  audio_file.save(temp_file.name)
148
-
149
- # Convert the file to PCM WAV format if necessary
 
 
 
 
150
  converted_file = NamedTemporaryFile(delete=False, suffix=".wav")
151
- ffmpeg.input(temp_file.name).output(converted_file.name, acodec='pcm_s16le', ac=1, ar='16000').run(overwrite_output=True)
 
 
 
 
 
 
 
 
152
 
 
153
  recognizer = sr.Recognizer()
154
  with sr.AudioFile(converted_file.name) as source:
155
  audio_data = recognizer.record(source)
156
  command = recognizer.recognize_google(audio_data)
 
157
  response = process_command(command)
158
 
159
- # Clean up temporary files
160
- os.unlink(temp_file.name)
161
- os.unlink(converted_file.name)
162
  return jsonify({"response": response})
 
 
 
 
 
163
  except Exception as e:
 
164
  return jsonify({"response": f"An error occurred: {str(e)}"})
165
 
 
 
 
 
 
 
 
 
 
 
166
  def process_command(command):
167
  """Process the user's voice command and return a response."""
168
- global orders
169
  command = command.lower()
170
  if "menu" in command:
171
- return "Our menu includes paneer butter masala, fried rice, and cold coffee."
 
 
 
 
 
172
  elif "order" in command:
173
- return "Your order has been placed."
174
- return "Sorry, I didn't understand your request."
 
 
175
 
176
  if __name__ == "__main__":
177
  app.run(host="0.0.0.0", port=7860)
 
1
  from flask import Flask, render_template_string, request, jsonify
2
+ import speech_recognition as sr
 
3
  from tempfile import NamedTemporaryFile
 
4
  import os
5
+ import ffmpeg
6
+ import logging
7
+ from werkzeug.exceptions import BadRequest
8
 
9
+ # Initialize Flask App
10
  app = Flask(__name__)
11
 
12
+ # Set up logging
13
+ logging.basicConfig(level=logging.INFO)
 
14
 
15
+ # HTML Template for Frontend
16
  html_code = """
17
  <!DOCTYPE html>
18
  <html lang="en">
 
76
  <body>
77
  <h1>AI Dining Assistant</h1>
78
  <button class="mic-button" id="mic-button">🎤</button>
79
+ <div class="status" id="status">Press the mic button to start the conversation...</div>
80
  <div class="response" id="response" style="display: none;">Response will appear here...</div>
81
  <script>
82
  const micButton = document.getElementById('mic-button');
83
  const status = document.getElementById('status');
84
  const response = document.getElementById('response');
 
 
 
85
  let mediaRecorder;
86
  let audioChunks = [];
87
+ let isConversationActive = false;
88
+
89
+ micButton.addEventListener('click', () => {
90
+ if (!isConversationActive) {
91
+ isConversationActive = true;
92
+ startConversation();
93
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  });
95
+
96
+ function startConversation() {
97
+ status.textContent = 'Listening...';
98
+ startListening();
99
+ }
100
+
101
+ function startListening() {
102
+ navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {
103
+ mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm;codecs=opus' });
104
+ mediaRecorder.start();
105
+ audioChunks = [];
106
+ mediaRecorder.ondataavailable = event => audioChunks.push(event.data);
107
+ mediaRecorder.onstop = async () => {
108
+ const audioBlob = new Blob(audioChunks, { type: 'audio/webm' });
109
+ const formData = new FormData();
110
+ formData.append('audio', audioBlob);
111
+
112
+ status.textContent = 'Processing...';
113
+ try {
114
+ const result = await fetch('/process-audio', { method: 'POST', body: formData });
115
+ const data = await result.json();
116
+ response.textContent = data.response;
117
+ response.style.display = 'block';
118
+
119
+ const utterance = new SpeechSynthesisUtterance(data.response);
120
+ speechSynthesis.speak(utterance);
121
+
122
+ if (data.response.includes("Goodbye")) {
123
+ status.textContent = 'Conversation ended. Press the mic button to start again.';
124
+ isConversationActive = false;
125
+ } else {
126
+ status.textContent = 'Listening...';
127
+ setTimeout(startListening, 1000); // Continue listening
128
+ }
129
+ } catch (error) {
130
+ response.textContent = 'Error occurred. Please try again.';
131
+ response.style.display = 'block';
132
+ status.textContent = 'Press the mic button to restart the conversation.';
133
+ isConversationActive = false;
134
+ }
135
+ };
136
+ setTimeout(() => mediaRecorder.stop(), 5000); // Stop recording after 5 seconds
137
+ }).catch(() => {
138
+ status.textContent = 'Microphone access denied.';
139
+ isConversationActive = false;
140
+ });
141
+ }
142
  </script>
143
  </body>
144
  </html>
 
151
  @app.route('/process-audio', methods=['POST'])
152
  def process_audio():
153
  try:
154
+ # Validate audio file
155
+ audio_file = request.files.get('audio')
156
+ if not audio_file:
157
+ raise BadRequest("No audio file provided.")
158
+
159
+ temp_file = NamedTemporaryFile(delete=False, suffix=".webm")
160
  audio_file.save(temp_file.name)
161
+ logging.info(f"Saved input audio to {temp_file.name}")
162
+
163
+ if os.path.getsize(temp_file.name) == 0:
164
+ raise BadRequest("Uploaded audio file is empty.")
165
+
166
+ # Convert audio to PCM WAV format
167
  converted_file = NamedTemporaryFile(delete=False, suffix=".wav")
168
+ try:
169
+ ffmpeg.input(temp_file.name).output(
170
+ converted_file.name, acodec='pcm_s16le', ac=1, ar='16000'
171
+ ).run(overwrite_output=True)
172
+ except Exception as ffmpeg_error:
173
+ logging.error(f"FFmpeg conversion error: {str(ffmpeg_error)}")
174
+ return jsonify({"response": "Audio conversion failed. Please try again."})
175
+
176
+ logging.info(f"Converted audio saved to {converted_file.name}")
177
 
178
+ # Recognize speech
179
  recognizer = sr.Recognizer()
180
  with sr.AudioFile(converted_file.name) as source:
181
  audio_data = recognizer.record(source)
182
  command = recognizer.recognize_google(audio_data)
183
+ logging.info(f"Recognized command: {command}")
184
  response = process_command(command)
185
 
 
 
 
186
  return jsonify({"response": response})
187
+
188
+ except BadRequest as br:
189
+ logging.error(f"Bad request error: {br}")
190
+ return jsonify({"response": f"Bad Request: {str(br)}"})
191
+
192
  except Exception as e:
193
+ logging.error(f"Error processing audio: {e}")
194
  return jsonify({"response": f"An error occurred: {str(e)}"})
195
 
196
+ finally:
197
+ # Clean up temporary files
198
+ try:
199
+ if os.path.exists(temp_file.name):
200
+ os.unlink(temp_file.name)
201
+ if os.path.exists(converted_file.name):
202
+ os.unlink(converted_file.name)
203
+ except Exception as cleanup_error:
204
+ logging.error(f"Error cleaning up files: {cleanup_error}")
205
+
206
  def process_command(command):
207
  """Process the user's voice command and return a response."""
 
208
  command = command.lower()
209
  if "menu" in command:
210
+ return (
211
+ "Here is our menu: "
212
+ "South Indian dishes include Idli, Dosa, Vada, Pongal, Biryani, and Sambar Rice. "
213
+ "North Indian dishes include Butter Chicken, Paneer Butter Masala, Naan, Dal Makhani, Chole Bhature, and Rajma Chawal. "
214
+ "What would you like to order?"
215
+ )
216
  elif "order" in command:
217
+ return "Your order has been placed. Would you like anything else?"
218
+ elif "no" in command or "nothing" in command:
219
+ return "Goodbye! Thank you for using AI Dining Assistant."
220
+ return "Sorry, I didn't understand your request. Please ask about the menu or place an order."
221
 
222
  if __name__ == "__main__":
223
  app.run(host="0.0.0.0", port=7860)