Update app.py
Browse files
app.py
CHANGED
@@ -89,7 +89,7 @@ UNICODE_FONTS = [
|
|
89 |
("Sans Serif Bold Italic", lambda x: "".join(chr(ord(c) + 0x1D63C - 0x41) if 'A' <= c <= 'Z' else chr(ord(c) + 0x1D656 - 0x61) if 'a' <= c <= 'z' else c for c in x)),
|
90 |
("Monospace", lambda x: "".join(chr(ord(c) + 0x1D670 - 0x41) if 'A' <= c <= 'Z' else chr(ord(c) + 0x1D68A - 0x61) if 'a' <= c <= 'z' else c for c in x)),
|
91 |
("Circled", lambda x: "".join(chr(ord(c) - 0x41 + 0x24B6) if 'A' <= c <= 'Z' else chr(ord(c) - 0x61 + 0x24D0) if 'a' <= c <= 'z' else c for c in x)),
|
92 |
-
("Squared", lambda x: "".join(chr(ord(c) -
|
93 |
("Negative Circled", lambda x: "".join(chr(ord(c) - 0x41 + 0x1F150) if 'A' <= c <= 'Z' else c for c in x)),
|
94 |
("Negative Squared", lambda x: "".join(chr(ord(c) - 0x41 + 0x1F170) if 'A' <= c <= 'Z' else c for c in x)),
|
95 |
("Regional Indicator", lambda x: "".join(chr(ord(c) - 0x41 + 0x1F1E6) if 'A' <= c <= 'Z' else c for c in x)),
|
@@ -173,9 +173,9 @@ def log_action(username, action):
|
|
173 |
def clean_text_for_tts(text):
|
174 |
cleaned = re.sub(r'[#*!\[\]]+', '', text)
|
175 |
cleaned = ' '.join(cleaned.split())
|
176 |
-
return cleaned
|
177 |
|
178 |
-
# Audio Processor Class from your code
|
179 |
class AudioProcessor:
|
180 |
def __init__(self):
|
181 |
self.cache_dir = "audio_cache"
|
@@ -196,7 +196,7 @@ class AudioProcessor:
|
|
196 |
cache_path = filename or os.path.join(self.cache_dir, f"{cache_key}.mp3")
|
197 |
|
198 |
if cache_key in self.metadata and os.path.exists(cache_path):
|
199 |
-
return
|
200 |
|
201 |
# Clean text for speech
|
202 |
text = text.replace("\n", " ").replace("</s>", " ").strip()
|
@@ -204,8 +204,14 @@ class AudioProcessor:
|
|
204 |
return None
|
205 |
|
206 |
# Generate audio with edge_tts
|
207 |
-
|
208 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
209 |
|
210 |
# Update metadata
|
211 |
self.metadata[cache_key] = {
|
@@ -215,7 +221,7 @@ class AudioProcessor:
|
|
215 |
}
|
216 |
self._save_metadata()
|
217 |
|
218 |
-
return
|
219 |
|
220 |
# Chat saver - words locked tight! π¬π
|
221 |
async def save_chat_entry(username, message, is_markdown=False, quote_line=None):
|
@@ -245,8 +251,9 @@ async def save_chat_entry(username, message, is_markdown=False, quote_line=None)
|
|
245 |
cleaned_message = clean_text_for_tts(message)
|
246 |
audio_processor = AudioProcessor()
|
247 |
audio_filename = f"{format_timestamp_prefix(username)}-{hashlib.md5(cleaned_message.encode()).hexdigest()[:8]}.mp3"
|
248 |
-
|
249 |
-
|
|
|
250 |
with open(HISTORY_FILE, 'a') as f:
|
251 |
f.write(f"[{timestamp}] {username} ({voice}): Audio generated - {audio_filename}\n")
|
252 |
with open(user_history_file, 'a') as f:
|
@@ -259,6 +266,8 @@ async def save_chat_entry(username, message, is_markdown=False, quote_line=None)
|
|
259 |
file_path = message.split(": ")[1]
|
260 |
if os.path.exists(file_path) and file_path.endswith(('.png', '.jpg', '.mp4', '.pdf')):
|
261 |
f.write(f"{indent}[{timestamp}] Media: \n")
|
|
|
|
|
262 |
|
263 |
await broadcast_message(f"{username}|{message}", "chat")
|
264 |
st.session_state.last_chat_update = time.time()
|
@@ -488,16 +497,6 @@ async def run_websocket_server():
|
|
488 |
st.session_state.server_running = True
|
489 |
await server.wait_closed()
|
490 |
|
491 |
-
# Dummy AI lookup function (replace with actual implementation)
|
492 |
-
async def perform_ai_lookup(query, vocal_summary=True, extended_refs=False, titles_summary=True, full_audio=False, useArxiv=True, useArxivAudio=False):
|
493 |
-
username = st.session_state.get('username', 'System π')
|
494 |
-
result = f"AI Lookup Result for '{query}' (Arxiv: {useArxiv}, Audio: {useArxivAudio})"
|
495 |
-
await save_chat_entry(username, result)
|
496 |
-
if useArxivAudio:
|
497 |
-
audio_file = await async_edge_tts_generate(result, st.session_state.voice)
|
498 |
-
if audio_file:
|
499 |
-
st.audio(audio_file)
|
500 |
-
|
501 |
# Delete all user files function
|
502 |
def delete_user_files():
|
503 |
protected_files = {'app.py', 'requirements.txt', 'README.md', CHAT_FILE, QUOTE_VOTES_FILE, MEDIA_VOTES_FILE, HISTORY_FILE, STATE_FILE}
|
@@ -597,11 +596,6 @@ def main():
|
|
597 |
audio_ref = line.split("Audio: ")[-1].strip()
|
598 |
if os.path.exists(audio_ref):
|
599 |
st.session_state.audio_cache[cache_key] = audio_ref
|
600 |
-
else:
|
601 |
-
cleaned_text = clean_text_for_tts(line.split(': ', 1)[1].split("Audio:")[0])
|
602 |
-
voice = st.session_state.voice if username == st.session_state.username else FUN_USERNAMES.get(username, "en-US-AriaNeural")
|
603 |
-
audio_file = await async_edge_tts_generate(cleaned_text, voice)
|
604 |
-
st.session_state.audio_cache[cache_key] = audio_file
|
605 |
audio_file = st.session_state.audio_cache.get(cache_key)
|
606 |
if audio_file:
|
607 |
play_and_download_audio(audio_file)
|
@@ -689,8 +683,9 @@ def main():
|
|
689 |
pdf_filename, texts, audio_files = await save_pdf_and_generate_audio(uploaded_file, username)
|
690 |
await save_chat_entry(username, f"Uploaded PDF: {pdf_filename}")
|
691 |
for i, (text, audio_file) in enumerate(zip(texts, audio_files)):
|
692 |
-
|
693 |
-
|
|
|
694 |
else:
|
695 |
await save_chat_entry(username, f"Uploaded media: {file_path}")
|
696 |
await save_chat_history_with_image(username, file_path)
|
|
|
89 |
("Sans Serif Bold Italic", lambda x: "".join(chr(ord(c) + 0x1D63C - 0x41) if 'A' <= c <= 'Z' else chr(ord(c) + 0x1D656 - 0x61) if 'a' <= c <= 'z' else c for c in x)),
|
90 |
("Monospace", lambda x: "".join(chr(ord(c) + 0x1D670 - 0x41) if 'A' <= c <= 'Z' else chr(ord(c) + 0x1D68A - 0x61) if 'a' <= c <= 'z' else c for c in x)),
|
91 |
("Circled", lambda x: "".join(chr(ord(c) - 0x41 + 0x24B6) if 'A' <= c <= 'Z' else chr(ord(c) - 0x61 + 0x24D0) if 'a' <= c <= 'z' else c for c in x)),
|
92 |
+
("Squared", lambda x: "".join(chr(ord(c) - 0x41 + 0x1F130) if 'A' <= c <= 'Z' else c for c in x)),
|
93 |
("Negative Circled", lambda x: "".join(chr(ord(c) - 0x41 + 0x1F150) if 'A' <= c <= 'Z' else c for c in x)),
|
94 |
("Negative Squared", lambda x: "".join(chr(ord(c) - 0x41 + 0x1F170) if 'A' <= c <= 'Z' else c for c in x)),
|
95 |
("Regional Indicator", lambda x: "".join(chr(ord(c) - 0x41 + 0x1F1E6) if 'A' <= c <= 'Z' else c for c in x)),
|
|
|
173 |
def clean_text_for_tts(text):
|
174 |
cleaned = re.sub(r'[#*!\[\]]+', '', text)
|
175 |
cleaned = ' '.join(cleaned.split())
|
176 |
+
return cleaned if cleaned else "No text to speak" # Default if empty
|
177 |
|
178 |
+
# Audio Processor Class from your code, adapted
|
179 |
class AudioProcessor:
|
180 |
def __init__(self):
|
181 |
self.cache_dir = "audio_cache"
|
|
|
196 |
cache_path = filename or os.path.join(self.cache_dir, f"{cache_key}.mp3")
|
197 |
|
198 |
if cache_key in self.metadata and os.path.exists(cache_path):
|
199 |
+
return cache_path
|
200 |
|
201 |
# Clean text for speech
|
202 |
text = text.replace("\n", " ").replace("</s>", " ").strip()
|
|
|
204 |
return None
|
205 |
|
206 |
# Generate audio with edge_tts
|
207 |
+
try:
|
208 |
+
communicate = edge_tts.Communicate(text, voice)
|
209 |
+
await communicate.save(cache_path)
|
210 |
+
if not os.path.exists(cache_path):
|
211 |
+
raise edge_tts.exceptions.NoAudioReceived("No audio file created")
|
212 |
+
except edge_tts.exceptions.NoAudioReceived as e:
|
213 |
+
log_action("System π", f"TTS failed for text '{text}' with voice '{voice}': {str(e)}")
|
214 |
+
return None
|
215 |
|
216 |
# Update metadata
|
217 |
self.metadata[cache_key] = {
|
|
|
221 |
}
|
222 |
self._save_metadata()
|
223 |
|
224 |
+
return cache_path
|
225 |
|
226 |
# Chat saver - words locked tight! π¬π
|
227 |
async def save_chat_entry(username, message, is_markdown=False, quote_line=None):
|
|
|
251 |
cleaned_message = clean_text_for_tts(message)
|
252 |
audio_processor = AudioProcessor()
|
253 |
audio_filename = f"{format_timestamp_prefix(username)}-{hashlib.md5(cleaned_message.encode()).hexdigest()[:8]}.mp3"
|
254 |
+
log_action(username, f"Attempting TTS with text: '{cleaned_message}' and voice: '{voice}'")
|
255 |
+
audio_file = await audio_processor.create_audio(cleaned_message, voice, audio_filename)
|
256 |
+
if audio_file:
|
257 |
with open(HISTORY_FILE, 'a') as f:
|
258 |
f.write(f"[{timestamp}] {username} ({voice}): Audio generated - {audio_filename}\n")
|
259 |
with open(user_history_file, 'a') as f:
|
|
|
266 |
file_path = message.split(": ")[1]
|
267 |
if os.path.exists(file_path) and file_path.endswith(('.png', '.jpg', '.mp4', '.pdf')):
|
268 |
f.write(f"{indent}[{timestamp}] Media: \n")
|
269 |
+
else:
|
270 |
+
log_action(username, f"Failed to generate audio for message: '{message}'")
|
271 |
|
272 |
await broadcast_message(f"{username}|{message}", "chat")
|
273 |
st.session_state.last_chat_update = time.time()
|
|
|
497 |
st.session_state.server_running = True
|
498 |
await server.wait_closed()
|
499 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
500 |
# Delete all user files function
|
501 |
def delete_user_files():
|
502 |
protected_files = {'app.py', 'requirements.txt', 'README.md', CHAT_FILE, QUOTE_VOTES_FILE, MEDIA_VOTES_FILE, HISTORY_FILE, STATE_FILE}
|
|
|
596 |
audio_ref = line.split("Audio: ")[-1].strip()
|
597 |
if os.path.exists(audio_ref):
|
598 |
st.session_state.audio_cache[cache_key] = audio_ref
|
|
|
|
|
|
|
|
|
|
|
599 |
audio_file = st.session_state.audio_cache.get(cache_key)
|
600 |
if audio_file:
|
601 |
play_and_download_audio(audio_file)
|
|
|
683 |
pdf_filename, texts, audio_files = await save_pdf_and_generate_audio(uploaded_file, username)
|
684 |
await save_chat_entry(username, f"Uploaded PDF: {pdf_filename}")
|
685 |
for i, (text, audio_file) in enumerate(zip(texts, audio_files)):
|
686 |
+
if audio_file:
|
687 |
+
with open(CHAT_FILE, 'a') as f:
|
688 |
+
f.write(f" [{timestamp}] Page {i+1} Audio: {audio_file}\n")
|
689 |
else:
|
690 |
await save_chat_entry(username, f"Uploaded media: {file_path}")
|
691 |
await save_chat_history_with_image(username, file_path)
|