Skip to content

Commit 747291c

Browse files
Some fixes to audio playing. Minor UI fixes.
2 parents c07208d + e4f9e64 commit 747291c

8 files changed

+37
-32
lines changed

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
license = "MIT"
88
name = "pyrobbot"
99
readme = "README.md"
10-
version = "0.7.5"
10+
version = "0.7.6"
1111

1212
[build-system]
1313
build-backend = "poetry.core.masonry.api"

pyrobbot/app/app_page_templates.py

+14-11
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ def render_custom_audio_player(
160160
b64 = base64.b64encode(data).decode()
161161
md = f"""
162162
<audio controls {autoplay} {hidden} preload="metadata">
163-
<source src="data:audio/mp3;base64,{b64}#" type="audio/mp3">
163+
<source src="data:audio/mp3;base64,{b64}#" type="audio/mpeg">
164164
</audio>
165165
"""
166166
parent_element = parent_element or st
@@ -259,7 +259,10 @@ def render_chat_history(self):
259259
continue
260260
with st.chat_message(role, avatar=self.avatars.get(role)):
261261
with contextlib.suppress(KeyError):
262-
st.caption(f"{message['chat_model']}, {message['timestamp']}")
262+
if role == "assistant":
263+
st.caption(message["chat_model"])
264+
else:
265+
st.caption(message["timestamp"])
263266
st.markdown(message["content"])
264267
with contextlib.suppress(KeyError):
265268
if audio := message.get("reply_audio_file_path"):
@@ -285,7 +288,7 @@ def voice_output(self) -> bool:
285288
"""Return the state of the voice output toggle."""
286289
return st.session_state.get("toggle_voice_output", False)
287290

288-
def play_chime(self, chime_type: str = "correct-answer-tone", parent_element=None):
291+
def play_chime(self, chime_type: str = "success", parent_element=None):
289292
"""Sound a chime to send notificatons to the user."""
290293
chime = load_chime(chime_type)
291294
self.render_custom_audio_player(
@@ -294,13 +297,12 @@ def play_chime(self, chime_type: str = "correct-answer-tone", parent_element=Non
294297

295298
def render_title(self):
296299
"""Render the title of the chatbot page."""
297-
with st.container(height=70, border=False):
300+
with st.container(height=145, border=False):
298301
self.title_container = st.empty()
299-
with st.container(height=50, border=False):
302+
self.title_container.subheader(self.title, divider="rainbow")
300303
left, _ = st.columns([0.7, 0.3])
301304
with left:
302305
self.status_msg_container = st.empty()
303-
self.title_container.subheader(self.title, divider="rainbow")
304306

305307
@property
306308
def direct_text_prompt(self):
@@ -310,13 +312,14 @@ def direct_text_prompt(self):
310312
)
311313
text_from_manual_audio_recorder = ""
312314
with st.container():
313-
left, right = st.columns([0.95, 0.05])
315+
left, right = st.columns([0.9, 0.1])
314316
with left:
315317
text_from_chat_input_widget = st.chat_input(placeholder=placeholder)
316318
with right:
317319
if not st.session_state.get("toggle_continuous_voice_input"):
318320
audio = self.manual_switch_mic_recorder()
319321
text_from_manual_audio_recorder = self.chat_obj.stt(audio).text
322+
320323
return text_from_chat_input_widget or text_from_manual_audio_recorder
321324

322325
@property
@@ -334,7 +337,7 @@ def continuous_text_prompt(self):
334337

335338
logger.debug("Running on continuous audio prompt. Waiting user input...")
336339
with self.status_msg_container:
337-
self.play_chime()
340+
self.play_chime(chime_type="warning")
338341
with st.spinner(f"{self.chat_obj.assistant_name} is listening..."):
339342
while True:
340343
with self.parent.text_prompt_queue.mutex:
@@ -361,7 +364,7 @@ def _render_chatbot_page(self): # noqa: PLR0915
361364
self.chat_obj.reply_only_as_text = not self.voice_output
362365

363366
self.render_title()
364-
chat_msgs_container = st.container(height=600, border=False)
367+
chat_msgs_container = st.container(height=550, border=False)
365368
with chat_msgs_container:
366369
self.render_chat_history()
367370

@@ -377,7 +380,7 @@ def _render_chatbot_page(self): # noqa: PLR0915
377380
self.parent.reply_ongoing.set()
378381

379382
if continuous_stt_prompt:
380-
self.play_chime("option-select")
383+
self.play_chime("success")
381384
self.status_msg_container.success("Got your message!")
382385
time.sleep(0.5)
383386
elif continuous_stt_prompt:
@@ -403,7 +406,6 @@ def _render_chatbot_page(self): # noqa: PLR0915
403406
"name": self.chat_obj.username,
404407
"content": prompt,
405408
"timestamp": time_now,
406-
"chat_model": self.chat_obj.model,
407409
}
408410
)
409411

@@ -418,6 +420,7 @@ def _render_chatbot_page(self): # noqa: PLR0915
418420
"name": self.chat_obj.assistant_name,
419421
"content": reply["text"],
420422
"reply_audio_file_path": reply["audio"],
423+
"chat_model": self.chat_obj.model,
421424
}
422425
)
423426

pyrobbot/app/app_utils.py

+1-7
Original file line numberDiff line numberDiff line change
@@ -215,12 +215,6 @@ def get_avatar_images():
215215
@st.cache_data
216216
def load_chime(chime_type: str) -> AudioSegment:
217217
"""Load a chime sound from the data directory."""
218-
type2filename = {
219-
"correct-answer-tone": "mixkit-correct-answer-tone-2870.wav",
220-
"option-select": "mixkit-interface-option-select-2573.wav",
221-
}
222-
223218
return AudioSegment.from_file(
224-
GeneralDefinitions.APP_DIR / "data" / type2filename[chime_type],
225-
format="wav",
219+
GeneralDefinitions.APP_DIR / "data" / f"{chime_type}.wav", format="wav"
226220
)
Binary file not shown.
Binary file not shown.

pyrobbot/app/data/success.wav

309 KB
Binary file not shown.

pyrobbot/app/data/warning.wav

142 KB
Binary file not shown.

pyrobbot/voice_chat.py

+21-13
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,6 @@ def __init__(self, configs: VoiceChatConfigs = default_configs, **kwargs):
5757

5858
self.block_size = int((self.sample_rate * self.frame_duration) / 1000)
5959

60-
self.mixer = pygame.mixer
61-
try:
62-
self.mixer.init(
63-
frequency=self.sample_rate, channels=1, buffer=self.block_size
64-
)
65-
except pygame.error as error:
66-
logger.exception(error)
67-
logger.error(
68-
"Can't initialize the mixer. Please check your system's audio settings."
69-
)
70-
logger.warning("Voice chat may not be available or may not work as expected.")
71-
7260
self.vad = webrtcvad.Vad(2)
7361

7462
self.default_chime_theme = "big-sur"
@@ -113,6 +101,26 @@ def __init__(self, configs: VoiceChatConfigs = default_configs, **kwargs):
113101
daemon=True,
114102
)
115103

104+
@property
105+
def mixer(self):
106+
"""Return the mixer object."""
107+
mixer = getattr(self, "_mixer", None)
108+
if mixer is not None:
109+
return mixer
110+
111+
self._mixer = pygame.mixer
112+
try:
113+
self.mixer.init(
114+
frequency=self.sample_rate, channels=1, buffer=self.block_size
115+
)
116+
except pygame.error as error:
117+
logger.exception(error)
118+
logger.error(
119+
"Can't initialize the mixer. Please check your system's audio settings."
120+
)
121+
logger.warning("Voice chat may not be available or may not work as expected.")
122+
return self._mixer
123+
116124
def start(self):
117125
"""Start the chat."""
118126
# ruff: noqa: T201
@@ -524,7 +532,7 @@ def _assistant_still_replying(self):
524532
def _check_needed_imports():
525533
"""Check if the needed modules are available."""
526534
if not _sounddevice_imported:
527-
logger.error(
535+
logger.warning(
528536
"Module `sounddevice`, needed for local audio recording, is not available."
529537
)
530538

0 commit comments

Comments
 (0)