Skip to content

Commit 53b29a0

Browse files
committed
TTS
1 parent 2543a20 commit 53b29a0

File tree

2 files changed

+60
-3
lines changed

2 files changed

+60
-3
lines changed

templates/index.html

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -997,16 +997,52 @@ <h1>Yuhasa History Tutor</h1>
997997
alert('Attachment functionality is not yet implemented.');
998998
});
999999

1000-
speakerButton.addEventListener('click', () => {
1001-
alert('Text-to-speech functionality is not yet implemented.');
1002-
});
1000+
// speakerButton.addEventListener('click', () => {
1001+
// alert('Text-to-speech functionality is not yet implemented.');
1002+
// });
10031003

10041004
// --- Initial Setup ---
10051005
loadChatHistoryList(true); // Load the list of chats and select latest on page load
10061006
userInput.focus();
10071007
autoResizeTextarea();
10081008
});
10091009
</script>
1010+
1011+
<script>
1012+
document.getElementById('speakerButton').addEventListener('click', async function() {
1013+
// Find all bot messages in the chat
1014+
const botMessages = Array.from(document.querySelectorAll('.bot-message .message-bubble'));
1015+
if (botMessages.length === 0) {
1016+
alert('No bot message to speak!');
1017+
return;
1018+
}
1019+
// Get the last bot message's text
1020+
const lastBotMsg = botMessages[botMessages.length - 1].innerText.trim();
1021+
if (!lastBotMsg) {
1022+
alert('Bot message is empty!');
1023+
return;
1024+
}
1025+
try {
1026+
// Send the text to the /tts endpoint
1027+
const response = await fetch('/tts', {
1028+
method: 'POST',
1029+
headers: { 'Content-Type': 'application/json' },
1030+
body: JSON.stringify({ text: lastBotMsg })
1031+
});
1032+
if (!response.ok) {
1033+
throw new Error('TTS failed');
1034+
}
1035+
const blob = await response.blob();
1036+
// Play the audio using an Audio element
1037+
const audioUrl = URL.createObjectURL(blob);
1038+
const audio = new Audio(audioUrl);
1039+
audio.play();
1040+
} catch (err) {
1041+
alert('Failed to speak: ' + err.message);
1042+
}
1043+
});
1044+
</script>
1045+
10101046
</body>
10111047

10121048
</html>

web.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
import time
77
from agents.orchestrator import OrchestratorAgent
88
import traceback
9+
from gtts import gTTS
10+
from flask import send_file
11+
import io
912

1013
# --- Logging Setup ---
1114
logging.basicConfig(level=logging.INFO,
@@ -174,6 +177,24 @@ def api_delete_chat(chat_id):
174177
os.remove(path)
175178
return jsonify({'success': True})
176179

180+
@app.route('/tts', methods=['POST'])
181+
def text_to_speech():
182+
data = request.get_json()
183+
text = data.get('text', '')
184+
if not text:
185+
return jsonify({'error': 'No text provided'}), 400
186+
try:
187+
# Generate speech using gTTS
188+
tts = gTTS(text=text, lang='en')
189+
mp3_fp = io.BytesIO()
190+
tts.write_to_fp(mp3_fp)
191+
mp3_fp.seek(0)
192+
# Return the audio file as response
193+
return send_file(mp3_fp, mimetype='audio/mpeg', as_attachment=False, download_name='speech.mp3')
194+
except Exception as e:
195+
logger.error(f"Error generating speech: {e}", exc_info=True)
196+
return jsonify({'error': 'Failed to generate speech'}), 500
197+
177198
if __name__ == '__main__':
178199
if orchestrator:
179200
logger.info("Starting Flask development server...")

0 commit comments

Comments
 (0)