Update app.py
Browse files
app.py
CHANGED
@@ -17,6 +17,7 @@ import streamlit.components.v1 as components
|
|
17 |
import edge_tts
|
18 |
from audio_recorder_streamlit import audio_recorder
|
19 |
import nest_asyncio
|
|
|
20 |
|
21 |
# Patch for nested async - sneaky fix! πβ¨
|
22 |
nest_asyncio.apply()
|
@@ -134,14 +135,24 @@ def log_action(username, action):
|
|
134 |
f.write(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] {username}: {action}\n")
|
135 |
user_log[action] = current_time
|
136 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
# Chat saver - words locked tight! π¬π
|
138 |
async def save_chat_entry(username, message):
|
139 |
await asyncio.to_thread(log_action, username, "π¬π - Chat saver - words locked tight!")
|
140 |
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
141 |
entry = f"[{timestamp}] {username}: {message}"
|
142 |
await asyncio.to_thread(lambda: open(CHAT_FILE, 'a').write(f"{entry}\n"))
|
143 |
-
voice = FUN_USERNAMES.get(username, "en-US-AriaNeural")
|
144 |
-
|
|
|
145 |
if audio_file:
|
146 |
with open(HISTORY_FILE, 'a') as f:
|
147 |
f.write(f"[{timestamp}] {username}: Audio generated - {audio_file}\n")
|
@@ -229,8 +240,13 @@ async def async_edge_tts_generate(text, voice, rate=0, pitch=0, file_format="mp3
|
|
229 |
timestamp = format_timestamp_prefix()
|
230 |
filename = os.path.join(AUDIO_DIR, f"audio_{timestamp}_{random.randint(1000, 9999)}.mp3")
|
231 |
communicate = edge_tts.Communicate(text, voice, rate=f"{rate:+d}%", pitch=f"{pitch:+d}Hz")
|
232 |
-
|
233 |
-
|
|
|
|
|
|
|
|
|
|
|
234 |
|
235 |
# Audio player - tunes blast off! ππ
|
236 |
def play_and_download_audio(file_path):
|
@@ -385,7 +401,8 @@ def create_streamlit_interface():
|
|
385 |
if cache_key in st.session_state.audio_cache:
|
386 |
audio_file = st.session_state.audio_cache[cache_key]
|
387 |
else:
|
388 |
-
|
|
|
389 |
st.session_state.audio_cache[cache_key] = audio_file
|
390 |
if audio_file:
|
391 |
play_and_download_audio(audio_file)
|
@@ -418,7 +435,14 @@ def create_streamlit_interface():
|
|
418 |
if filename:
|
419 |
markdown_response += f"\n- **Image**: "
|
420 |
st.session_state.pasted_image_data = None
|
421 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
422 |
loop.run_until_complete(process_quote())
|
423 |
del st.session_state.quote_line
|
424 |
st.session_state.message_text = ''
|
|
|
17 |
import edge_tts
|
18 |
from audio_recorder_streamlit import audio_recorder
|
19 |
import nest_asyncio
|
20 |
+
import re
|
21 |
|
22 |
# Patch for nested async - sneaky fix! πβ¨
|
23 |
nest_asyncio.apply()
|
|
|
135 |
f.write(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] {username}: {action}\n")
|
136 |
user_log[action] = current_time
|
137 |
|
138 |
+
# Clean text - strip the fancy stuff! π§Ήπ
|
139 |
+
def clean_text_for_tts(text):
|
140 |
+
# Remove Markdown formatting (e.g., #, *, [], ![])
|
141 |
+
cleaned = re.sub(r'[#*!\[\]]+', '', text)
|
142 |
+
# Replace newlines with spaces and strip extra whitespace
|
143 |
+
cleaned = ' '.join(cleaned.split())
|
144 |
+
# Ensure some text exists, max 200 chars to avoid edgeTTS limits
|
145 |
+
return cleaned[:200] if cleaned else "No text to speak"
|
146 |
+
|
147 |
# Chat saver - words locked tight! π¬π
|
148 |
async def save_chat_entry(username, message):
|
149 |
await asyncio.to_thread(log_action, username, "π¬π - Chat saver - words locked tight!")
|
150 |
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
151 |
entry = f"[{timestamp}] {username}: {message}"
|
152 |
await asyncio.to_thread(lambda: open(CHAT_FILE, 'a').write(f"{entry}\n"))
|
153 |
+
voice = FUN_USERNAMES.get(username, "en-US-AriaNeural")
|
154 |
+
cleaned_message = clean_text_for_tts(message)
|
155 |
+
audio_file = await async_edge_tts_generate(cleaned_message, voice)
|
156 |
if audio_file:
|
157 |
with open(HISTORY_FILE, 'a') as f:
|
158 |
f.write(f"[{timestamp}] {username}: Audio generated - {audio_file}\n")
|
|
|
240 |
timestamp = format_timestamp_prefix()
|
241 |
filename = os.path.join(AUDIO_DIR, f"audio_{timestamp}_{random.randint(1000, 9999)}.mp3")
|
242 |
communicate = edge_tts.Communicate(text, voice, rate=f"{rate:+d}%", pitch=f"{pitch:+d}Hz")
|
243 |
+
try:
|
244 |
+
await communicate.save(filename)
|
245 |
+
return filename if os.path.exists(filename) else None
|
246 |
+
except edge_tts.exceptions.NoAudioReceived:
|
247 |
+
with open(HISTORY_FILE, 'a') as f:
|
248 |
+
f.write(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] {username}: Audio failed - No audio received for '{text}'\n")
|
249 |
+
return None
|
250 |
|
251 |
# Audio player - tunes blast off! ππ
|
252 |
def play_and_download_audio(file_path):
|
|
|
401 |
if cache_key in st.session_state.audio_cache:
|
402 |
audio_file = st.session_state.audio_cache[cache_key]
|
403 |
else:
|
404 |
+
cleaned_text = clean_text_for_tts(line.split(': ', 1)[1])
|
405 |
+
audio_file = await async_edge_tts_generate(cleaned_text, FUN_USERNAMES.get(username, "en-US-AriaNeural"))
|
406 |
st.session_state.audio_cache[cache_key] = audio_file
|
407 |
if audio_file:
|
408 |
play_and_download_audio(audio_file)
|
|
|
435 |
if filename:
|
436 |
markdown_response += f"\n- **Image**: "
|
437 |
st.session_state.pasted_image_data = None
|
438 |
+
try:
|
439 |
+
await save_chat_entry(st.session_state.username, markdown_response)
|
440 |
+
except edge_tts.exceptions.NoAudioReceived:
|
441 |
+
# Log failure but continue without audio
|
442 |
+
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
443 |
+
with open(HISTORY_FILE, 'a') as f:
|
444 |
+
f.write(f"[{timestamp}] {st.session_state.username}: Quote saved without audio - No audio received\n")
|
445 |
+
await asyncio.to_thread(lambda: open(CHAT_FILE, 'a').write(f"[{timestamp}] {st.session_state.username}: {markdown_response}\n"))
|
446 |
loop.run_until_complete(process_quote())
|
447 |
del st.session_state.quote_line
|
448 |
st.session_state.message_text = ''
|