This is a submission for the AssemblyAI Voice Agents Challenge
What I Built
Real-time Youtube Transcription App addressing 2nd prompt of Assembly AI Challenge (Real-Time Voice Performance)
Demo
App is currently on production stage:
GitHub Repository
https://github.com/bahamondeX/aai-challenge-2
Technical Implementation & AssemblyAI Integration
I used universal streaming AssemblyAI API to leverage it's top notch performance for real-time use cases and expressive API to handle multiple speakers with turns formatting:
def handler(url: str, is_live: bool = False) -> tp.Generator[bytes, None, None]:
return get_live_audio_optimized(url) if is_live else get_audio_stream_pcm_s16le_optimized(url)
def on_begin(self: StreamingClient, event: BeginEvent):
logger.info(f"Begin event: {event}")
def on_turn(self: StreamingClient, event: TurnEvent):
self.queue.put_nowait(event) # type: ignore
def on_termination(self: StreamingClient, event: TerminationEvent):
logger.info(f"Termination event: {event}")
def on_error(self: StreamingClient, event: StreamingError):
logger.error(f"Error event: {event}")
async def transcriber(url: str, is_live: bool = False):
client = StreamingClient(StreamingClientOptions(api_key=AAI_API_KEY))
client.queue = asyncio.Queue[TurnEvent]() # type: ignore
client.on(StreamingEvents.Begin, on_begin) # type: ignore
client.on(StreamingEvents.Turn, on_turn) # type: ignore
client.on(StreamingEvents.Termination, on_termination) # type: ignore
client.on(StreamingEvents.Error, on_error) # type: ignore
client.connect(StreamingParameters(sample_rate=16000))
async def stream_audio():
try:
await asyncio.get_event_loop().run_in_executor(
None, lambda: client.stream(handler(url, is_live))
)
except Exception as e:
logger.error(f"Streaming error: {e}")
asyncio.create_task(stream_audio())
while True:
try:
data = await client.queue.get() # type: ignore
content = data.model_dump_json()
yield content
except asyncio.TimeoutError:
logger.warning("Transcription timeout")
break
except Exception as e:
logger.error(f"Transcription error: {e}")
break
Top comments (0)