give me correct import for ServerVad
# ask-ai
r
give me correct import for ServerVad
t
Thanks for reaching out, Gaurav. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Which language or SDK are you using (Go, JavaScript/TypeScript, Python, or something else)? The import path for
ServerVad
depends on the language — tell me which one and I’ll give the exact import statement.
r
python 3.12.
Copy code
dependencies = [
    "livekit-agents[google]~=1.2",
    "python-dotenv",
]
t
You're using Python and the
livekit-agents
package —
ServerVad
is not a separate import. Configure server-side VAD via the
TurnDetection
class when creating a realtime model. For OpenAI realtime:
Copy code
from livekit.plugins.openai import realtime
from openai.types.beta.realtime.session import TurnDetection

llm = realtime.RealtimeModel(
    turn_detection=TurnDetection(
        type="server_vad",
        threshold=0.5,
        prefix_padding_ms=300,
        silence_duration_ms=500,
    )
)
For Azure OpenAI realtime:
Copy code
from livekit.plugins.openai import realtime
from openai.types.beta.realtime.session import TurnDetection

llm = realtime.RealtimeModel.with_azure(
    azure_deployment="your-deployment",
    azure_endpoint="your-endpoint",
    api_version="2024-10-01-preview",
    api_key="your-key",
    turn_detection=TurnDetection(
        type="server_vad",
        threshold=0.5,
        prefix_padding_ms=300,
        silence_duration_ms=500,
    )
)
Would you like sample values for the thresholds or help integrating this into your existing code? Sources: Azure OpenAI Realtime API and LiveKit | LiveKit docs | OpenAI Realtime API plugin guide | LiveKit docs
r
actually using
Copy code
llm=google.realtime.RealtimeModel(
    model="gemini-2.5-flash-native-audio-preview-12-2025",
    voice="Aoede",
    temperature=0.8,
t
You're using
google.realtime.RealtimeModel
—
ServerVad
is not a separate import for the Google realtime integration. Gemini Live handles server-side VAD automatically, so you don't import or configure
ServerVad
. If you want to disable Google’s automatic VAD and use client-side turn detection instead, add
realtime_input_config
to disable automatic activity detection and provide a
turn_detection
model plus an
stt
plugin. Example:
Copy code
from google.genai import types
from livekit.plugins.turn_detector.multilingual import MultilingualModel
from livekit.plugins.google import realtime as google_realtime
from livekit.session import AgentSession

session = AgentSession(
    turn_detection=MultilingualModel(),
    llm=google_realtime.RealtimeModel(
        model="gemini-2.5-flash-native-audio-preview-12-2025",
        voice="Aoede",
        temperature=0.8,
        realtime_input_config=types.RealtimeInputConfig(
            automatic_activity_detection=types.AutomaticActivityDetection(
                disabled=True,
            ),
        ),
        input_audio_transcription=None,
        stt="assemblyai/universal-streaming"
    )
)
Would you like help choosing `threshold`/settings for the turn detector or sample STT providers? Sources: Gemini Live API plugin | LiveKit docs
r
but this still doesnt incorporate prefix_padding_ms=300, silence_duration_ms=500
t
You're right to check —
prefix_padding_ms
and
silence_duration_ms
cannot be set on
google.realtime.RealtimeModel
. Gemini Live handles VAD internally and does not expose those low-level VAD options. You have two practical alternatives: • Switch to OpenAI/Azure Realtime models, which support
TurnDetection
with
prefix_padding_ms
and
silence_duration_ms
. • Keep using Gemini but disable its automatic activity detection and run client-side turn detection + STT (e.g., LiveKit turn detector + AssemblyAI/Deepgram). This gives you endpointing control, but requires adding/configuring the turn detector and STT pipeline. Which option would you prefer? I can provide the exact code for OpenAI/Azure
TurnDetection
settings or a sample showing how to wire the client-side turn detector + STT with Gemini. Sources: Azure OpenAI Realtime API and LiveKit | LiveKit docs | Gemini Live API plugin | LiveKit docs | OpenAI Realtime API plugin guide | LiveKit docs
r
a sample showing how to wire the client-side turn detector + STT with Gemini.
t
You're asking for a sample showing how to wire client-side turn detection + STT with the Google Gemini realtime model. Below is a concise, runnable-style Python example using LiveKit Agents plugins (AssemblyAI STT, Silero VAD, multilingual turn detector) that disables Gemini's automatic activity detection so the client-side turn detector controls endpointing.
Copy code
# Example: client-side turn detection + STT with Google Gemini (livekit-agents)
# Adjust imports/names to match your installed package versions.

from google.genai import types as genai_types
from livekit.plugins.google import realtime as google_realtime
from livekit.plugins.turn_detector.multilingual import MultilingualModel
from livekit.plugins import silero, assemblyai, turn_detector
from livekit.agents import AgentSession, SessionConfig, JobContext  # adjust paths if needed
import asyncio

async def entrypoint(ctx: JobContext):
    # 1) STT plugin (AssemblyAI) — handles transcription + semantic endpointing
    stt_plugin = assemblyai.STT(
        api_key="YOUR_ASSEMBLYAI_KEY",
        end_of_turn_confidence_threshold=0.4,
        min_end_of_turn_silence_when_confident=400,  # ms
        max_turn_silence=1280,  # ms
    )

    # 2) Optional VAD plugin (Silero) for low-latency interruption detection
    vad_plugin = silero.VAD.load()

    # 3) Client-side turn detector model (MultilingualModel)
    turn_detector_model = MultilingualModel()

    # 4) Google Gemini realtime LLM configured to disable server-side automatic activity detection
    llm_plugin = google_realtime.RealtimeModel(
        model="gemini-2.5-flash-native-audio-preview-12-2025",
        voice="Aoede",
        temperature=0.8,
        instructions="You are a helpful assistant.",
        realtime_input_config=genai_types.RealtimeInputConfig(
            automatic_activity_detection=genai_types.AutomaticActivityDetection(disabled=True)
        ),
        input_audio_transcription=None,  # rely on STT plugin for transcription
    )

    # 5) Assemble the AgentSession using the client-side turn detection pipeline
    session = AgentSession(
        ctx.room,
        session_config=SessionConfig(
            turn_detection=turn_detector_model,
            stt=stt_plugin,
            vad=vad_plugin,
            llm=llm_plugin,
            tts=None,  # Optional: add TTS if you need synthesized output
        )
    )

    await session.start()
    # session will manage audio I/O, STT, VAD, and turn detection
    # await session.stop() when finished (not shown)

# If running standalone for testing:
# asyncio.run(entrypoint(your_job_context))
Notes and tuning tips: • Use
realtime_input_config.automatic_activity_detection.disabled=True
to stop Gemini’s server-side VAD so the client-side pipeline controls turn boundaries. • Tune AssemblyAI endpointing params (
end_of_turn_confidence_threshold
,
min_end_of_turn_silence_when_confident
,
max_turn_silence
) to approximate
prefix_padding_ms
/
silence_duration_ms
behavior. • Keep Silero VAD for fast interruption detection; the multilingual turn detector uses the STT stream + context to decide final turns. • Replace keys, room/context objects, and model names with your real values. Would you like this adapted to a minimal runnable script with mocked room/context or to use a different STT provider (Deepgram, Whisper, etc.)? Sources: Gemini Live API plugin | LiveKit docs | AssemblyAI plugin guide | LiveKit Docs | Turn detection and interruptions | LiveKit Docs | LiveKit turn detector plugin | LiveKit docs
r
use a free stt
t
Great — I'll give a concise example using a free STT option. Two common free choices are: • Groq’s free Whisper endpoint (cloud, free tier) — simple and low-latency. • Local open-source Whisper (faster-whisper or whisper.cpp) — fully offline. Which do you prefer: Groq cloud (easy keys) or local Whisper (no external API)?
r
local Whisper (no external API)
t
Acknowledged — I'll provide a concise, runnable sample that wires local Whisper (offline) as the STT, Silero VAD for client-side voice activity detection, and Google Gemini RealtimeModel with its automatic activity detection disabled. Before you run it: • Run a local Whisper server (e.g., whisper-api-server, whisper.cpp http wrapper, or faster-whisper-based server) that exposes an OpenAI-compatible transcription endpoint at http://localhost:8000/v1. • Install required packages: livekit-agents[google], faster-whisper (or your chosen whisper server tool), and silero plugin. Sample (adjust imports/paths to match your environment):
Copy code
import asyncio
from google.genai import types as genai_types
from livekit.plugins.google import realtime as google_realtime
from livekit.plugins import silero
from livekit.plugins.openai import STT as OpenAI_STT  # uses base_url to point to local Whisper
from livekit.agents import AgentSession, SessionConfig, JobContext  # adjust if package paths differ
from livekit.plugins.turn_detector.multilingual import MultilingualModel

async def entrypoint(ctx: JobContext):
    # 1) Load Silero VAD (client-side quick interruption detection)
    vad = silero.VAD.load()

    # 2) Configure local Whisper STT by pointing OpenAI-compatible STT plugin to localhost
    stt = OpenAI_STT(
        model="whisper-1",
        base_url="<http://localhost:8000/v1>",  # your local Whisper server endpoint
        api_key=None,                         # typically not needed for local server
    )

    # 3) Use multilingual turn detector (optional) or rely on VAD-based turn detection
    turn_detector = MultilingualModel()

    # 4) Configure Gemini realtime LLM and disable its automatic activity detection
    llm = google_realtime.RealtimeModel(
        model="gemini-2.5-flash-native-audio-preview-12-2025",
        voice="Aoede",
        temperature=0.8,
        instructions="You are a helpful assistant.",
        realtime_input_config=genai_types.RealtimeInputConfig(
            automatic_activity_detection=genai_types.AutomaticActivityDetection(disabled=True)
        ),
        input_audio_transcription=None,  # rely on local STT for transcripts
    )

    # 5) Assemble the AgentSession using client-side STT + VAD + turn detector
    session = AgentSession(
        ctx.room,
        session_config=SessionConfig(
            llm=llm,
            stt=stt,
            vad=vad,
            turn_detection=turn_detector,  # or use "vad" mode if you prefer only VAD
            tts=None,  # optional: let Gemini provide audio output or add separate TTS
        )
    )

    await session.start()
    # Session runs until stopped; stop when appropriate in your app:
    # await session.stop()

# If you need a minimal runner (adjust to your app framework)
# asyncio.run(entrypoint(your_job_context))
Tuning notes: • Use
turn_detection=turn_detector
to let the multilingual model combine STT context + VAD for semantic endpointing. • If your local Whisper server can emit END_OF_SPEECH/endpointing events, you may prefer
turn_detection="stt"
. • If you only have final transcripts (no streaming endpoint events), use
turn_detection=MultilingualModel()
or
turn_detection="vad"
. • To approximate
prefix_padding_ms
and
silence_duration_ms
, tune: ◦ Silero VAD parameters (e.g.,
min_silence_duration
) and/or ◦ Your turn detector or STT endpointing thresholds on the local server. Would you like a Dockerfile or a whisper.cpp / whisper-api-server example to run the local Whisper server? Sources: Gemini Live API plugin | LiveKit docs | examples/voice_agents | livekit/livekit_composite | DeepWiki | Silero VAD plugin | LiveKit docs | How does end-of-utterance detection work in conversations?
r
is whisper better than gemini stt
t
Good question — here’s a short comparison to help decide which fits your use case. Accuracy • Whisper (local): Very good on many accents and noisy audio when you run a large model (e.g., large-v3). Can outperform generic cloud models for some languages and noisy conditions if you use the right model and hardware. • Gemini STT: High quality for Google’s supported languages and generally strong on natural speech; may be better tuned for low-latency streaming in production. Latency • Whisper (local): Depends on your hardware and model size. On CPU it can be slow; on a GPU it’s low-latency but still generally slower than a purpose-built streaming cloud STT. • Gemini STT: Built for realtime streaming with low latency out of the box. Cost • Whisper (local): No per-request cloud cost (aside from your infra/GPU cost). Good for development and privacy-focused deployments. • Gemini STT: Paid API usage; simpler operational overhead but recurring cost. Privacy & Control • Whisper (local): Full data control — audio never leaves your environment. • Gemini STT: Data goes to Google’s service; less control unless you use enterprise agreements. Configurability & Endpointing • Whisper (local): You control endpointing behavior and can integrate it with client-side turn detection; you can tune silence/padding indirectly by how you stream and buffer audio. • Gemini STT: Built-in streaming/endpointing optimized by Google; you cannot configure low-level VAD parameters like
prefix_padding_ms
or
silence_duration_ms
. Reliability & Maintenance • Whisper (local): You must manage model hosting, scaling, updates, and resource usage. • Gemini STT: Managed service — Google handles scaling and reliability. When to pick which • Choose local Whisper if you need privacy, want no per-call cloud cost, or need tight control over endpointing and can host GPU resources. • Choose Gemini STT if you need lowest-latency streaming out of the box, simpler operations, and strong production-grade transcription across supported languages. Practical hybrid option • Use Gemini for LLM/TT S but run local Whisper for STT + client-side turn detection (what we sketched earlier) to get privacy/control while keeping Gemini for audio generation. If you tell me your priorities (latency, cost, privacy, infra available), I’ll recommend which to use and suggest exact tuning values. Would you like that?