Spaces:
Sleeping
Sleeping
import streamlit as st | |
import asyncio | |
from quickstart import WebSocketHandler, AsyncHumeClient, ChatConnectOptions, MicrophoneInterface, SubscribeEvent | |
import os | |
from dotenv import load_dotenv | |
import chainlit as cl | |
# Page config | |
st.set_page_config( | |
page_title="Hume.ai Voice Chat", | |
page_icon="🎤", | |
layout="centered" | |
) | |
st.title("Hume.ai Voice Chat Demo") | |
# Load environment variables | |
load_dotenv() | |
async def run_chat(): | |
# Initialize client and handlers | |
client = AsyncHumeClient(api_key=os.getenv("HUME_API_KEY")) | |
options = ChatConnectOptions( | |
config_id=os.getenv("HUME_CONFIG_ID"), | |
secret_key=os.getenv("HUME_SECRET_KEY") | |
) | |
# Create a custom WebSocketHandler that updates Chainlit | |
class ChainlitWebSocketHandler(WebSocketHandler): | |
async def on_message(self, message: SubscribeEvent): | |
await super().on_message(message) | |
if message.type in ["user_message", "assistant_message"]: | |
role = message.message.role | |
message_text = message.message.content | |
# Create emotion text if available | |
emotion_text = "" | |
if message.from_text is False and hasattr(message, 'models') and hasattr(message.models, 'prosody'): | |
scores = dict(message.models.prosody.scores) | |
top_3_emotions = self._extract_top_n_emotions(scores, 3) | |
emotion_text = " | ".join([f"{emotion} ({score:.2f})" for emotion, score in top_3_emotions.items()]) | |
# Send message to Chainlit | |
content = f"{message_text}\n\n*Emotions: {emotion_text}*" if emotion_text else message_text | |
await cl.Message( | |
content=content, | |
author=role.capitalize() | |
).send() | |
websocket_handler = ChainlitWebSocketHandler() | |
async with client.empathic_voice.chat.connect_with_callbacks( | |
options=options, | |
on_open=websocket_handler.on_open, | |
on_message=websocket_handler.on_message, | |
on_close=websocket_handler.on_close, | |
on_error=websocket_handler.on_error | |
) as socket: | |
websocket_handler.set_socket(socket) | |
# Create microphone interface task | |
microphone_task = asyncio.create_task( | |
MicrophoneInterface.start( | |
socket, | |
allow_user_interrupt=False, | |
byte_stream=websocket_handler.byte_strs | |
) | |
) | |
await microphone_task | |
async def start(): | |
await cl.Message(content="Welcome to the Hume.ai Voice Chat Demo! Click p to chat.").send() | |
async def on_audio(): | |
await run_chat() | |
async def on_end(): | |
connection = cl.user_session.get("hume_connection") | |
if connection: | |
await connection.__aexit__(None, None, None) | |
cl.user_session.set("hume_socket", None) | |
cl.user_session.set("hume_connection", None) | |