AIVoice / app.py
geethareddy's picture
Update app.py
d91f3c0 verified
from flask import Flask, render_template_string, request, jsonify
import speech_recognition as sr
from tempfile import NamedTemporaryFile
import os
import ffmpeg
import logging
from werkzeug.exceptions import BadRequest
app = Flask(__name__)
logging.basicConfig(level=logging.INFO)
# Global variables
cart = [] # To store items and prices
MENU = {
"Biryani": {"Chicken Biryani": 150, "Veg Biryani": 120},
"Starters": {"Chicken Wings": 180, "Paneer Tikka": 160},
"Breads": {"Butter Naan": 40, "Roti": 30},
"Curries": {"Butter Chicken": 200, "Dal Fry": 150},
}
suggested_category = None # To track ongoing category suggestions
# HTML Template for Frontend
html_code = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Dining Assistant</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
background-color: #f4f4f9;
}
h1 {
color: #333;
}
.mic-button {
width: 80px;
height: 80px;
border-radius: 50%;
background-color: #007bff;
color: white;
font-size: 24px;
border: none;
cursor: pointer;
}
.status, .response {
margin-top: 20px;
}
</style>
</head>
<body>
<h1>AI Dining Assistant</h1>
<button class="mic-button" id="mic-button">🎤</button>
<div class="status" id="status">Press the mic button to start...</div>
<div class="response" id="response" style="display: none;">Response will appear here...</div>
<script>
const micButton = document.getElementById('mic-button');
const status = document.getElementById('status');
const response = document.getElementById('response');
let isListening = false;
micButton.addEventListener('click', () => {
if (!isListening) {
isListening = true;
startConversation();
}
});
function startConversation() {
const utterance = new SpeechSynthesisUtterance("Listening...");
speechSynthesis.speak(utterance);
utterance.onend = () => {
status.textContent = "Listening...";
startListening();
};
}
async function startListening() {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const mediaRecorder = new MediaRecorder(stream, { mimeType: "audio/webm;codecs=opus" });
const audioChunks = [];
mediaRecorder.ondataavailable = (event) => audioChunks.push(event.data);
mediaRecorder.onstop = async () => {
const audioBlob = new Blob(audioChunks, { type: "audio/webm" });
const formData = new FormData();
formData.append("audio", audioBlob);
status.textContent = "Processing...";
try {
const result = await fetch("/process-audio", { method: "POST", body: formData });
const data = await result.json();
response.textContent = data.response;
response.style.display = "block";
const utterance = new SpeechSynthesisUtterance(data.response);
speechSynthesis.speak(utterance);
utterance.onend = () => {
if (!data.response.includes("Goodbye") && !data.response.includes("final order")) {
startConversation(); // Continue listening
} else {
status.textContent = "Conversation ended.";
isListening = false;
}
};
} catch (error) {
response.textContent = "Error processing your request. Please try again.";
status.textContent = "Press the mic button to restart.";
isListening = false;
}
};
mediaRecorder.start();
setTimeout(() => mediaRecorder.stop(), 5000); // Stop recording after 5 seconds
}
</script>
</body>
</html>
"""
@app.route("/")
def index():
return render_template_string(html_code)
@app.route("/process-audio", methods=["POST"])
def process_audio():
global suggested_category
try:
audio_file = request.files.get("audio")
if not audio_file:
raise BadRequest("No audio file provided.")
temp_file = NamedTemporaryFile(delete=False, suffix=".webm")
audio_file.save(temp_file.name)
if os.path.getsize(temp_file.name) == 0:
raise BadRequest("Uploaded audio file is empty.")
converted_file = NamedTemporaryFile(delete=False, suffix=".wav")
ffmpeg.input(temp_file.name).output(
converted_file.name, acodec="pcm_s16le", ac=1, ar="16000"
).run(overwrite_output=True)
recognizer = sr.Recognizer()
with sr.AudioFile(converted_file.name) as source:
audio_data = recognizer.record(source)
try:
command = recognizer.recognize_google(audio_data)
response = process_command(command)
except sr.UnknownValueError:
response = "Sorry, I could not understand. Please try again."
return jsonify({"response": response})
except BadRequest as br:
return jsonify({"response": f"Bad Request: {str(br)}"}), 400
except Exception as e:
return jsonify({"response": f"An error occurred: {str(e)}"}), 500
finally:
os.unlink(temp_file.name)
os.unlink(converted_file.name)
def process_command(command):
global cart, MENU, suggested_category
command = command.lower()
all_items = {item.lower(): (category, price) for category, items in MENU.items() for item, price in items.items()}
# Handle ongoing suggestion
if suggested_category:
if command in [item.lower() for item in MENU[suggested_category].keys()]:
item = command.title()
price = MENU[suggested_category][item]
cart.append((item, price))
total = sum(item[1] for item in cart)
cart_summary = ", ".join([f"{i[0]} (₹{i[1]})" for i in cart])
suggested_category = None # Reset category suggestion
return f"{item} added to your cart for ₹{price}. Your cart: {cart_summary}. Total: ₹{total}. Do you want to order anything else?"
# Handle category suggestion
categories = {category.lower(): category for category in MENU.keys()}
if any(cat in command for cat in categories.keys()):
suggested_category = categories[next(cat for cat in categories.keys() if cat in command)]
items = ", ".join(MENU[suggested_category].keys())
return f"{suggested_category.capitalize()} options are: {items}. Which one would you like?"
# Handle final order
elif "final order" in command or "submit" in command:
if cart:
items = ", ".join([f"{item[0]} (₹{item[1]})" for item in cart])
total = sum(item[1] for item in cart)
cart.clear()
return f"Your final order is: {items}. Total price: ₹{total}. Thank you for ordering!"
else:
return "Your cart is empty. Please add items first."
# Handle goodbye
elif "no" in command or "nothing" in command or "goodbye" in command:
cart.clear()
return "Goodbye! Thank you for using AI Dining Assistant."
return "Sorry, I didn't understand that. Please try again."
if __name__ == "__main__":
app.run(host="0.0.0.0", port=7860)