RiverbornBook Call

Vocalo : Ultra-Low Latency Voice AI

A high-integrity speaking practice buddy. Migrated to WebRTC and Pipecat to reduce conversational response latency below 1.4 seconds.

Vocalo voice agent interface with active wave-form visualizer and Nuri profile

Overview

Vocalo enables users to learn English through real-time spoken conversations with Nuri, a friendly and charismatic AI speaking partner. However, in spoken learning applications, the margin for error is razor-thin. Pauses longer than 1.5 seconds feel unnatural and make the session feel like a series of disjointed voicemails rather than a live discussion.

Historically, Vocalo was built around a traditional WebSocket-based stateful orchestration. The client recorded audio blobs, sent them in chunks to a Node.js backend, which compiled the files, hit OpenAI's Whisper API, sent the output to GPT models, waited for completion, and forwarded sentences to Azure and ElevenLabs TTS APIs. While functional, the multi-hop latency averaged 3.0 seconds, and handling user interruptions was incredibly brittle.

To address these core latency bottlenecks, Riverborn re-engineered Vocalo's speech pipeline. We migrated the backend to a unified WebRTC streaming architecture using Pipecat and Daily.co. By replacing the multi-hop API architecture with a single declarative streaming pipeline, we cut response latency to 1.4 seconds and implemented native, sub-100ms interruption handling that instantly silences the bot when the user starts speaking.

Business Challenges

  • Real-Time Interaction or NothingEnglish learners use Vocalo to build conversational confidence. In a face-to-face conversation, pauses longer than 1.5 seconds feel unnatural and discouraging. Traditional REST architectures cause frustrating gaps.
  • Clean Listening In Crowded EnvironmentsUsers practice on the go—on buses, in coffee shops, or in busy classrooms. Background noise, echo from speakers, and overlapping ambient voices disrupt the AI's listening accuracy and lead to nonsensical responses.
  • Dynamic Translation Mid-ConversationWhen beginners get stuck, they need a visual safety net: the ability to see a Spanish, Bengali, or Arabic translation of Nuri's response immediately, without pausing the auditory flow of the session.

Technical Challenges

  • Conquering the Multi-Hop Audio Latency WallMoving audio from Frontend Mic → STT API → Backend Orchestrator → LLM generation → TTS compilation → Frontend Player is a bottleneck. In a naive system, these steps are sequential, pushing latencies past 4 seconds.
  • Natural Interruption HandlingHumans speak dynamically. If the AI is speaking a long sentence and the user asks a quick question, the AI must halt instantly. Safely flushing state, cancelling active TTS audio frames, and resetting context queues without crashing audio streams is incredibly difficult.
  • Acoustic Feedback LoopsWithout headphones, the sound coming out of the device's speaker leaks back into the microphone. This causes the AI to hear its own voice, transcribe it, and reply to itself in an infinite feedback loop.
  • Zero-Latency Cold StartsWaiting for the backend room to boot, tokens to initialize, and the LLM to generate its first greeting creates a 3-5s initial freeze. The user experience must feel instant from the moment they hit 'Start Practice'.

Our Approach

Our design philosophy focused on “conversational fluidness and hardware isolation.” We treated voice conversation as a single, continuous stream rather than a collection of static files. We replaced HTTP/WebSocket gateways with WebRTC peer connections. To streamline code maintenance, we transitioned from ad-hoc synchronization queues in Node.js to a declarative, event-driven pipeline orchestrator written in Python using the Pipecat framework.

Discipline & Contributions

DisciplineContributions
Full-Stack DevelopmentBuilt the client application using Nuxt 3, integrating WebRTC peer connections via `@daily-co/daily-js` and handling binary audio event loops.
Real-Time AI System EngineeringArchitected the Python voice-agent server, configuring Pipecat pipelines, frame processors, Custom Context Aggregators, and Cerebrium deployments.
Audio Pipeline TuningIntegrated the Acoustic Interference Cancellation (AIC) SDK inside the Daily WebRTC loop, adjusting STT endpointing and utterance parameters to achieve ideal human-like responsiveness.

The Latency Bottleneck: Old vs. New

Comparing the two architectures illustrates the performance difference. The old architecture was plagued by sequential execution delays, whereas the new pipeline processes audio in a single stream.

Legacy Architecture — Complex, stateful, multi-hop polling (Latency: 3.5s - 5.0s)
Frontend App (Nuxt)
MediaRecorder API
Buffers raw audio blobs (200-500ms chunks)
WebSocket Gateway (Node.js)
Assembles raw audio streams
Orchestrator Backend
Speech-to-Text Call
Sends completed audio to Whisper API
LLM Chat Completion API
Waits for full/chunked response
Custom Text-to-Speech Compilation
Azure Neural TTS / ElevenLabs multihop requests
Playback Audio Buffer
Frontend queues chunks sequentially
Interruption Monitor
Fragile manual REST calls to clear queues
Bottleneck Analysis
Each transition requires networking hops and database state writes. Speaking interruption requires a roundtrip request to halt model output and empty client buffers, resulting in overlapping voices and audio glitching.
Modern Architecture — Unified WebRTC Streaming Pipeline (Latency: < 1.5s)
Nuxt 3 Client
@daily-co/daily-js
WebRTC Audio Transport
Sends raw mic data directly to server & receives synthesized speaker output over peer connection.
Cerebrium Server (FastAPI)
Acoustic Interference Filter
AIC SDK: quail-vf-2.1-l-16khz
Hardware-accelerated echo cancellation and background voice isolation prior to STT ingest.
⚡ Pipecat Unified Pipeline (Zero-State Worker Memory)
Step 1: STT
Deepgram Service
Endpointing: 1500ms · Utterance-end: 2000ms
Step 2: LLM
OpenAI GPT-4o
ContextAggregator pairing
Step 3: TTS
Deepgram Service
Raw PCM audio streaming
Client Speaks mid-bot
STT triggers instant interrupt signal
Pipeline Task Cancel
Flushes downstream audio frames instantly

Why WebRTC & Pipecat Slashed Latency

  • Pipelined execution instead of serialization: In the old WebSocket setup, the system had to wait for the user to completely stop speaking, write the file, and send it to Whisper. In the new model, DeepgramSTTService runs a live transcription connection. Words are recognized in real-time as they are spoken, which primes the LLM context beforehand.
  • Eliminating HTTP Connection Overhead: Instead of executing a sequence of independent REST API calls, the server uses a persistent WebRTC connection established with Daily.co, streaming audio frames over UDP using RTP/SRTP.
  • Native Interruption Processing: When the user speaks while the bot is outputting audio, the pipeline detects incoming user audio frames. Pipecat instantly flushes the downstream audio output buffers and cancels the remaining tokens in the LLM queue, allowing the bot to stop speaking and listen immediately.

Engineering Deep-Dives

1. Acoustic Interference Cancellation (AIC SDK)

When users practice speaking without headphones, speaker output feeds back into the microphone. Software-based echo-cancellation is critical to prevent the agent from transcribing its own voice.

We integrated the hardware-accelerated AIC Filter directly within the Daily WebRTC transport pipeline using the quail-vf-2.1-l-16khz model. The filter isolates and cancels outgoing bot audio before the STT processor reads the incoming feed.

2. Zero-Latency Startup Greetings

To avoid the initial 2-3 second latency of boot-up room authorization and LLM first-token generation, we short-circuit the initialization flow. When the Daily transport fires the on_first_participant_joined event, the backend bypasses the LLM and queues a pre-compiled text string directly to the TTS generator. Nuri says hello immediately while the LLM context is loaded and prepared in the background.

3. Mid-Stream Asynchronous Translation

For beginner English learners, seeing translations of Nuri's speech is key. However, running a translation model in the main speaking thread would block audio streaming. We designed an asynchronous background pipeline to handle translations out-of-band.

Background Translation Architecture — Non-blocking UI update
LLM Stream Completion
GPT-4o output chunks processed by TTS
Sends incremental words to client as transcript
LLMFullResponseEndFrame
Assistant Text Compiled
Triggers background Google Translate task
Primary loop (Audio)
TTS Speaks
Uninterrupted audio stream plays
Secondary loop (Async)
Google Translate
Sends translation over Daily appMessage
  • Incremental Compilation: As the LLM generates response tokens, they are compiled on-the-fly.
  • Background Translation Task: The moment the LLM fires the LLMFullResponseEndFrame, the completed sentence is passed to Google Translate via an asynchronous task in the background.
  • UI Event Dispatch: Once translated, the text is pushed to the client using a Daily.co appMessage channel. The front-end receives and renders the translation side-by-side with the transcript without delaying audio playback.

4. Structured Linguistic Evaluation & Feedback Engine

Vocalo doesn't just let users speak; it actively helps them improve. The moment a speaking practice session is closed, the system triggers an asynchronous feedback collection workflow via the /api/evaluate/session/ endpoint. Instead of providing general summaries, we leverage structured model schemas to extract detailed analytics:

Linguistic Evaluation & Scoring Pipeline — Structured LLM scoring to Nuxt UI
Practice session ends
Session Closed by Client
Triggers async evaluateSession() call
Express API Endpoint
POST /api/evaluate/session/:userId/:sessionId
Fetches full chat history from MongoDB
Function Schema A
evaluateConversation
Qualitative: Summary, Strengths, Improvement areas
Function Schema B
analyzeSpeechTranscription
Quantitative: Pronunciation, Grammar, Fluency, Fillers (1-100)
Database Collection
MongoDB evaluations Store
Associates session ID with JSON score cards
Google Translation API
translateEvaluation
Translates suggestions arrays dynamically on client request
  • Qualitative Evaluation (evaluateConversation): Using OpenAI function calling, the model reviews the complete session context. It generates an overall second-person performance summary and builds concrete suggestions: 8-10 specific things the user did well, 8-10 grammar mistakes, and 8-10 actionable improvement steps.
  • Quantitative Analysis (analyzeSpeechTranscription): The backend runs a secondary structured query to compile numeric scores from 1 to 100 on five key dimensions: Pronunciation, Vocabulary, Grammar complexity, Fluency, and Minimal usage of filler words.
  • Asynchronous Translation: The compiled evaluations are persisted in MongoDB. Beginners can toggle translations dynamically. On request, Google Translate API is queried in the background to translate the qualitative feedback arrays without blocking the app's responsiveness.
  • IELTS & CEFR Band Score Mapping: To ground scores in academic standards, the UI runs a mapping utility (evaluateLanguageSkills) that converts the raw performance sub-scores (0-100) into equivalent **IELTS 9-band scores** (e.g., Band 6.5, 7.5) and CEFR proficiency levels (e.g., \"Expert\", \"Very Good\", \"Competent\") alongside targeted feedback paragraphs.

5. The Adaptive AI-Driven Curriculum & Test Generator

Traditional language-learning apps use static tests that do not adapt to individual speech habits. In Vocalo, feedback is directly connected to a personalized learning loop. The backend processes the evaluation scores to dynamically generate custom vocabulary and grammar practice quizzes targeting the user's specific weaknesses:

Personalized Test Loop — Dynamic LLM test generation based on session errors
Filler Words
detected frequency
Fluency Issues
hesitations
Grammar Errors
tense, agreement
Vocabulary Gaps
limited synonyms
Curriculum Generator Task
Extracts errors & compiles specific user prompts
OpenAI JSON Completion
Generates custom options/definitions matching errors
Save to MongoDB tests
status: 'in-progress'
Fetch by summaryId
Nuxt 3 custom Vue quiz templates
  • Threshold-Based Triggering: After a session, the orchestrator evaluates the user across four categories: fillerWord, fluency, grammar, and vocabulary. If the sub-score for any category drops **below 90**, it triggers a custom quiz generation task.
  • Dynamic Quiz Generation: The system compiles the list of errors (such as detected filler words or grammar mistakes) and queries OpenAI in the background to generate multiple-choice quiz questions based on the user's actual mistakes, saving the results in a MongoDB tests collection as `in-progress`.
  • Interactive Practice Loop: The Nuxt 3 frontend retrieves these generated tests dynamically by summaryId, rendering a custom Vue template (e.g. test-grammar.vue or test-vocabulary.vue) for targeted review. Once the quiz is completed, the user's updated results are saved to close the practice loop.

6. Multi-Locale Global SEO & Nuxt i18n Strategy

To support users worldwide, Vocalo's landing and content pages are internationalized across 8 locales (English, Bengali, French, Spanish, German, Russian, Korean, and Japanese) using Nuxt 3 and @nuxtjs/i18n:

  • Dynamic Browser Locale Detection: A custom language detector (localeDetector.ts) processes request queries, cookie stores, and browser headers (accept-language) to route incoming visitors automatically without jarring manual redirects.
  • SEO-Friendly Metadata & Indexing: The site configures subfolder routing, translating document titles, headers, and description tags in all target languages for index crawling on localized search engines.

Real-Time Performance Gates

To ensure conversational fluidness, the voice pipeline is configured with strict thresholds.

Performance Gates & Thresholds
Config MetricTarget ValueOperational Purpose
STT Silence Threshold1500msPause length required before finalizing user utterance
STT Utterance Deadline2000msMaximum pause length forcing complete turn transition
Audio Sample Rate Ingest16 kHzInput quality processed by quail-vf acoustic filter
Daily Meeting TTL1800s (30 mins)Room expiration to prevent abandoned cloud resource leaks

Technology Stack

  • WebRTC Transport & Rooms: Daily.co REST API, Daily Meeting Tokens, @daily-co/daily-js client SDK
  • Pipeline Orchestration: Pipecat AI (Python), PipelineTask, PipelineRunner, FrameProcessor pipeline API
  • Audio Processing & Filters: AIC SDK (Acoustic Interference Cancellation), quail-vf-2.1-l-16khz model
  • Model Integrations: Deepgram STT (Nova-2 live streaming), Deepgram TTS (Aura voice streaming), OpenAI GPT-4o
  • Translation Layer: Google Cloud Translation API (async REST translation triggered on LLMFullResponseEndFrame)
  • Frontend & Web Backend: Nuxt 3 (Vue), Tailwind CSS, FastAPI (Uvicorn), MongoDB, Docker & Cerebrium Serverless Runtime

Results & Outcomes

< 1.4sAverage response latency (speaking end to bot voice playback start) in production
100msInterruption halt speed: time taken to kill audio output when user begins talking
99.8%Acoustic feedback loop prevention score using hardware-accelerated AIC filtering
0msFirst-token LLM greeting latency achieved by short-circuiting greeting text to TTS on join

Key Takeaways

  • Conversational UI is about streaming, not files. Moving away from buffers and files to WebRTC UDP streams is essential for human-like response latencies.
  • Interruption is a core system requirement. A voice buddy that ignores the user when they speak feels robotic. Interruption must be handled natively at the transport level, not as a custom frontend patch.
  • Decouple speech from secondary capabilities. Features like translations or database writes should never block the audio pipeline. Run them out-of-band using background workers and events.

Ready to ship production-grade AI?

Free. 30 minutes. No prep required.