Spaces:
Running
Running
Upload app.py
Browse files
app.py
CHANGED
@@ -22,7 +22,7 @@ client = ElevenLabs(api_key=ELEVENLABS_API_KEY)
|
|
22 |
st.set_page_config(page_title="Voice Agent Pro", page_icon="π§")
|
23 |
logger.info("π¬ Streamlit app started")
|
24 |
|
25 |
-
# Inject large fonts + tips
|
26 |
st.markdown("""
|
27 |
<style>
|
28 |
.big-title {
|
@@ -46,11 +46,46 @@ st.markdown("""
|
|
46 |
border-radius: 0.5em;
|
47 |
margin-bottom: 1em;
|
48 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
</style>
|
50 |
""", unsafe_allow_html=True)
|
51 |
|
52 |
st.markdown('<div class="big-title">π§ Voice Agent Pro</div>', unsafe_allow_html=True)
|
53 |
-
st.markdown('<div class="instructions">Ask a question <b>OR</b> paste a URL <b>OR</b> upload a file β and I
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
|
55 |
# Voice selection
|
56 |
st.sidebar.header("ποΈ Voice Settings")
|
@@ -62,21 +97,21 @@ font_class = "big-answer" if font_size == "Large" else ""
|
|
62 |
|
63 |
# One-liners per voice
|
64 |
preview_lines = {
|
65 |
-
"grandma GG": "Back in my day, we didn
|
66 |
"tech wizard": "System online. You may now enter your query, human.",
|
67 |
-
"perky sidekick": "You got this! Let
|
68 |
-
"bill the newscaster": "Breaking news β you
|
69 |
-
"spunky charlie": "Whoa! Is it story time already? Let
|
70 |
"sassy teen": "Seriously? You better ask something cool."
|
71 |
}
|
72 |
|
73 |
preview_line = preview_lines.get(voice_label, "Testing voice.")
|
74 |
st.markdown(f"π§ <b>{voice_label}</b> says:", unsafe_allow_html=True)
|
75 |
-
st.markdown(f"_
|
76 |
|
77 |
# Stream preview audio (no autoplay)
|
78 |
try:
|
79 |
-
stream = client.text_to_speech.
|
80 |
text=preview_line,
|
81 |
voice_id=voice_id,
|
82 |
model_id="eleven_multilingual_v2"
|
@@ -201,14 +236,14 @@ if st.button("π Summarize"):
|
|
201 |
logger.exception("π₯ GPT/audio failed")
|
202 |
|
203 |
# Output
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
|
|
22 |
st.set_page_config(page_title="Voice Agent Pro", page_icon="π§")
|
23 |
logger.info("π¬ Streamlit app started")
|
24 |
|
25 |
+
# Inject large fonts + tips + bolt badge
|
26 |
st.markdown("""
|
27 |
<style>
|
28 |
.big-title {
|
|
|
46 |
border-radius: 0.5em;
|
47 |
margin-bottom: 1em;
|
48 |
}
|
49 |
+
.bolt-badge {
|
50 |
+
position: fixed;
|
51 |
+
bottom: 20px;
|
52 |
+
right: 20px;
|
53 |
+
z-index: 1000;
|
54 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
55 |
+
color: white;
|
56 |
+
padding: 8px 16px;
|
57 |
+
border-radius: 25px;
|
58 |
+
font-size: 0.85em;
|
59 |
+
font-weight: 600;
|
60 |
+
text-decoration: none;
|
61 |
+
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
|
62 |
+
transition: all 0.3s ease;
|
63 |
+
display: flex;
|
64 |
+
align-items: center;
|
65 |
+
gap: 6px;
|
66 |
+
}
|
67 |
+
.bolt-badge:hover {
|
68 |
+
transform: translateY(-2px);
|
69 |
+
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
|
70 |
+
text-decoration: none;
|
71 |
+
color: white;
|
72 |
+
}
|
73 |
+
.bolt-icon {
|
74 |
+
font-size: 1.1em;
|
75 |
+
}
|
76 |
</style>
|
77 |
""", unsafe_allow_html=True)
|
78 |
|
79 |
st.markdown('<div class="big-title">π§ Voice Agent Pro</div>', unsafe_allow_html=True)
|
80 |
+
st.markdown('<div class="instructions">Ask a question <b>OR</b> paste a URL <b>OR</b> upload a file β and I'll summarize it in bullet points with expressive AI narration!</div>', unsafe_allow_html=True)
|
81 |
+
|
82 |
+
# Add Bolt badge
|
83 |
+
st.markdown("""
|
84 |
+
<a href="https://bolt.new" target="_blank" class="bolt-badge">
|
85 |
+
<span class="bolt-icon">β‘</span>
|
86 |
+
Built with Bolt
|
87 |
+
</a>
|
88 |
+
""", unsafe_allow_html=True)
|
89 |
|
90 |
# Voice selection
|
91 |
st.sidebar.header("ποΈ Voice Settings")
|
|
|
97 |
|
98 |
# One-liners per voice
|
99 |
preview_lines = {
|
100 |
+
"grandma GG": "Back in my day, we didn't need AI to sound this fabulous.",
|
101 |
"tech wizard": "System online. You may now enter your query, human.",
|
102 |
+
"perky sidekick": "You got this! Let's answer that question together!",
|
103 |
+
"bill the newscaster": "Breaking news β you've just selected the perfect voice.",
|
104 |
+
"spunky charlie": "Whoa! Is it story time already? Let's go!",
|
105 |
"sassy teen": "Seriously? You better ask something cool."
|
106 |
}
|
107 |
|
108 |
preview_line = preview_lines.get(voice_label, "Testing voice.")
|
109 |
st.markdown(f"π§ <b>{voice_label}</b> says:", unsafe_allow_html=True)
|
110 |
+
st.markdown(f"_"{preview_line}"_", unsafe_allow_html=True)
|
111 |
|
112 |
# Stream preview audio (no autoplay)
|
113 |
try:
|
114 |
+
stream = client.text_to_speech.convert_as_stream(
|
115 |
text=preview_line,
|
116 |
voice_id=voice_id,
|
117 |
model_id="eleven_multilingual_v2"
|
|
|
236 |
logger.exception("π₯ GPT/audio failed")
|
237 |
|
238 |
# Output
|
239 |
+
if st.session_state.answer:
|
240 |
+
st.subheader("π Answer")
|
241 |
+
st.success(st.session_state.answer)
|
242 |
+
|
243 |
+
if st.session_state.audio_key:
|
244 |
+
audio_path = os.path.join(AUDIO_DIR, f"{st.session_state.audio_key}.mp3")
|
245 |
+
if os.path.exists(audio_path):
|
246 |
+
st.audio(audio_path)
|
247 |
+
else:
|
248 |
+
st.error("β Audio file missing.")
|
249 |
+
logger.warning(f"β Missing audio file: {audio_path}")
|