When running a livekit server and a sip server loc...
# ask-ai
m
When running a livekit server and a sip server locally, my calls are not able to connect over UDP, but they can connect over TCP. However, when I use TCP, I don’t hear any audio from the agent. What could be the possible issue? Alternatively, if you can draft a minimum agent to test just inbound calls and agent speaking, that would be great.
t
Thanks for reaching out, Rahib. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
I'd love to help you get to the bottom of the UDP connectivity issue and the audio problem over TCP. To better assist you, could you share a bit more about your setup? • Have you noticed any specific error messages or logs when trying to connect over UDP? • Have you had a chance to check if the RTP media ports (usually between 10000-20000) are open and properly configured through any firewalls or NAT? • Which SIP provider or configuration are you currently using? • Are there particular codecs you're using for audio transmission? Also, if you're looking for a simple agent setup to test inbound calls and audio, could you let me know which programming language or framework you prefer? This way, I can guide you more effectively. Sources: SIP APIs | LiveKit Docs | SIP troubleshooting guide | LiveKit Docs | SIP Integration | livekit/livekit_composite | DeepWiki | test/lktest/sip.go | transport/tcp.go
m
Since this is only locally. Below is my docker file to run sip server, livekit server and redis. Below is the dispatch rule:
Copy code
{
  "dispatch_rule": {
    "roomConfig": {
      "agents": [
        {
          "agentName": "telephony-voice-assistant"
        }
      ]
    },
    "rule": {
      "dispatchRuleIndividual": {
        "roomPrefix": "telephony-voice-assistant_"
      }
    }
  }
}
Copy code
services:
    redis:
        image: redis
        command: redis-server --requirepass ""
        volumes:
            - redis_data:/data
        ports:
            - 6379:6379
    livekit:
        image: livekit/livekit-server
        command: --dev --redis-host redis:6379 --bind 0.0.0.0
        ports:
            - "7880:7880"
            - "7881:7881"
            - "7882-7900:7882-7900/udp"
        depends_on:
            redis:
                condition: service_started
    sip:
        image: livekit/sip
        ports:
            - "5060:5060/udp"
            - "5060:5060/tcp"
            - "10000-10100:10000-10100/udp"
        environment:
            SIP_CONFIG_BODY: |
                api_key: 'devkey'
                api_secret: 'secret'
                ws_url: '<ws://livekit:7880>'
                redis:
                  address: 'redis:6379'
                sip_port: 5060
                rtp_port: 10000-10100
                use_external_ip: true
                media_use_external_ip: true
                logging:
                  level: debug
        depends_on:
            livekit:
                condition: service_started
            redis:
                condition: service_started
volumes:
    redis_data:
t
Thanks for sharing your setup! It sounds like the UDP connectivity and audio over TCP issues in your local Docker environment might be tied to Docker's networking model or how the ports are configured. Let’s walk through some steps that could help: • Use Host Networking: Sometimes Docker’s default bridge networking can get in the way of UDP traffic. Try running your containers with
--network host
so they can access the host network directly. • Verify Port Configuration: Double-check that the necessary UDP ports are open and mapped correctly. For instance, RTP media usually uses ports 10000-20000, and SIP signaling generally uses port 5060. • Check Configuration: Make sure your
ws_url
and
redis.address
are set to the host’s accessible IP. On Linux, this often looks like
172.17.0.1
. • Inspect Logs: Take a look at your Docker logs for any errors about port binding or ICE candidate gathering. If you notice missing public IPv4 UDP candidates, that’s a clue something might be off in the setup. • Test Connectivity: You can use LiveKit’s Connection Test utility to help diagnose any WebRTC, TURN, or WebSocket connectivity hiccups. If you’d like, I’m happy to help you set up a minimal agent to test inbound calls and audio. Just let me know which programming language or framework you prefer, and we can take it from there! Sources: Diagnosing Connection Errors with Connection Test Utility | Deploy to a VM | LiveKit Docs | pkg/sip/server.go | Self-hosting the Ingress Service | LiveKit Docs | config-sample.yaml
m
I am building in python
t
Let's walk through setting up a minimum SIP agent in Python for handling inbound calls and audio with LiveKit together. Here’s a step-by-step guide to help you get started smoothly: 1. Prerequisites: First, make sure you have a SIP provider (like Twilio), the LiveKit CLI installed, and the necessary environment variables set up (
LIVEKIT_URL
,
LIVEKIT_API_KEY
,
LIVEKIT_API_SECRET
). 2. Create the Agent: You can use the LiveKit CLI to scaffold a voice agent like this:
Copy code
lk app create --template voice-pipeline-agent-python
Next, you’ll want to modify the
agent.py
file to assign an
agent_name
for dispatching calls:
Copy code
if __name__ == "__main__":
    cli.run_app(
        WorkerOptions(
            entrypoint_fnc=entrypoint,
            prewarm_fnc=prewarm,
            agent_name="inbound-agent",  # Required for telephony dispatch
        ),
    )
Then, start your agent in development mode with:
Copy code
python3 agent.py dev
1. Set Up Inbound SIP Trunk: You’ll want to create a trunk configuration and apply it either through the LiveKit CLI or programmatically using the LiveKit Python SDK. 2. Create Dispatch Rule: Define a dispatch rule to route incoming calls to your agent. This can also be done programmatically if you prefer. 3. Handle Inbound Calls: In your agent’s entry point, use
session.start()
and
generate_reply()
to answer calls and provide friendly voice responses like this:
Copy code
@entrypoint
async def entrypoint(ctx: JobContext):
    session = VoicePipelineAgent(ctx)
    await session.start()

    # Answer the call with a voice response
    await session.generate_reply(
        instructions="Greet the user and offer your assistance."
    )
    await session.say("How can I help you today?")
If you’re interested in more advanced audio handling, I recommend checking out the
playing_audio.py
example in the official repository—it’s a great resource. Please don’t hesitate to reach out if you need any further help or specific examples. I’m here to support you every step of the way! Sources: Agents telephony integration | LiveKit Docs | Creating SIP Inbound Trunks and Dispatch Rules with Python SDK | README.md | Accepting incoming calls | LiveKit Docs | Accepting incoming calls | LiveKit Docs
m
So now when i make the call with zoiper to my agent these are the logs i see 2025-09-17 113121,493 - DEBUG livekit.agents - input stream attached {"room": "telephony-voice-assistant__1200_TVb36y8kcubh", "participant": null, "source": "SOURCE_UNKNOWN", "accepted_sources": ["SOURCE_MICROPHONE"], "pid": 45056, "job_id": "AJ_DkdKU7Brx7fr"} 2025-09-17 113121,494 - DEBUG livekit.agents - http_session(): creating a new httpclient ctx {"room": "telephony-voice-assistant__1200_TVb36y8kcubh", "pid": 45056, "job_id": "AJ_DkdKU7Brx7fr"} error: failed to fetch server settings: http status: 404 2025-09-17 113121,636 - ERROR livekit - livekit_ffi:serverroom149livekit ffiserver:room - audio filter cannot be enabled: LiveKit Cloud is required {"room": "telephony-voice-assistant__1200_TVb36y8kcubh", "pid": 45056, "job_id": "AJ_DkdKU7Brx7fr"} 2025-09-17 113121,636 - DEBUG livekit.agents - using audio io:
RoomIO
->
AgentSession
->
TranscriptSynchronizer
->
RoomIO
{"room": "telephony-voice-assistant__1200_TVb36y8kcubh", "pid": 45056, "job_id": "AJ_DkdKU7Brx7fr"} 2025-09-17 113121,636 - DEBUG livekit.agents - using transcript io:
AgentSession
->
TranscriptSynchronizer
->
RoomIO
{"room": "telephony-voice-assistant__1200_TVb36y8kcubh", "pid": 45056, "job_id": "AJ_DkdKU7Brx7fr"} not authenticated 2025-09-17 113121,737 - DEBUG livekit.agents - start reading stream {"room": "telephony-voice-assistant__1200_TVb36y8kcubh", "participant": "sip_1200", "source": "SOURCE_MICROPHONE", "pid": 45056, "job_id": "AJ_DkdKU7Brx7fr"} 2025-09-17 113121,737 - ERROR livekit - livekit_ffi:serveraudio stream123livekit ffiserver:audio_stream - failed to initialize the audio filter. it will not be enabled for this session. {"room": "telephony-voice-assistant__1200_TVb36y8kcubh", "pid": 45056, "job_id": "AJ_DkdKU7Brx7fr"} 2025-09-17 113126,533 - INFO livekit.agents - STT metrics {"room": "telephony-voice-assistant__1200_TVb36y8kcubh", "audio_duration": 4.75, "pid": 45056, "job_id": "AJ_DkdKU7Brx7fr"} 2025-09-17 113131,583 - INFO livekit.agents - STT metrics {"room": "telephony-voice-assistant__1200_TVb36y8kcubh", "audio_duration": 5.05, "pid": 45056, "job_id": "AJ_DkdKU7Brx7fr"} 2025-09-17 113136,632 - INFO livekit.agents - STT metrics {"room": "telephony-voice-assistant__1200_TVb36y8kcubh", "audio_duration": 5.05, "pid": 45056, "job_id": "AJ_DkdKU7Brx7fr"} 2025-09-17 113141,682 - INFO livekit.agents - STT metrics {"room": "telephony-voice-assistant__1200_TVb36y8kcubh", "audio_duration": 5.05, "pid": 45056, "job_id": "AJ_DkdKU7Brx7fr"} And it looks like the agent is streaming audio but i dont hear any audio on the call.
t
Thank you for sharing the details! From what I see in the logs and your description, it looks like the agent is streaming audio, but it’s not coming through on the call. Let’s work through some steps together to get this sorted out: 1. Verify SIP Trunk Configuration: Please double-check that the SIP trunk is set up correctly with the right credentials and endpoints. Sometimes a small misconfiguration here can block the audio. 2. Check Audio Output Setup: Make sure the agent’s audio output is properly configured. It’s important that the
AudioOutput
implementation is connected and actively forwarding audio frames. 3. Inspect Call State: Using the LiveKit CLI or SDK, confirm that the SIP participant’s call state changes to "active" before expecting audio. For instance, look at the
sip.callStatus
attribute. 4. Enable Noise and Echo Cancellation: If audio seems muffled or suppressed, turning on background noise and echo cancellation can really improve clarity. 5. Debug Audio Tracks: The LiveKit Chrome Developer Extension is a handy tool to check audio tracks being published and subscribed to in real time. This can help ensure the SIP participant’s audio track is active and playing correctly. 6. Check Logs for Warnings: Keep an eye out for warnings about silent audio frames or media timeouts in the server logs—they often give clues about audio pipeline issues. 7. Validate Network Configuration: Lastly, please verify that the necessary UDP ports for RTP media (like 10000-20000) are open and reachable. If you try these steps and the problem is still there, just let me know! I’m here to help and can guide you through more detailed troubleshooting or review specific logs with you. Sources: SIP troubleshooting guide | LiveKit Docs | Development Tools | livekit/livekit_composite | DeepWiki | livekit-agents/livekit/agents/voice/agent.py | agents/src/voice/agent_activity.ts | Make outbound calls | LiveKit Docs
m
This is what my agent looks like now
Copy code
import logging

from dotenv import load_dotenv
from livekit.agents import (
    NOT_GIVEN,
    Agent,
    AgentFalseInterruptionEvent,
    AgentSession,
    JobContext,
    JobProcess,
    MetricsCollectedEvent,
    RoomInputOptions,
    RunContext,
    WorkerOptions,
    cli,
    metrics,
)
from livekit.agents.llm import function_tool
from livekit.plugins import cartesia, deepgram, noise_cancellation, openai, silero
from livekit.plugins.turn_detector.multilingual import MultilingualModel

logger = logging.getLogger("agent")

load_dotenv(".env.local")


class Assistant(Agent):
    def __init__(self) -> None:
        super().__init__(
            instructions="""You are a helpful voice AI assistant.
            You eagerly assist users with their questions by providing information from your extensive knowledge.
            Your responses are concise, to the point, and without any complex formatting or punctuation including emojis, asterisks, or other symbols.
            You are curious, friendly, and have a sense of humor.""",
        )

    # all functions annotated with @function_tool will be passed to the LLM when this
    # agent is active
    @function_tool
    async def lookup_weather(self, context: RunContext, location: str):
        """Use this tool to look up current weather information in the given location.

        If the location is not supported by the weather service, the tool will indicate this. You must tell the user the location's weather is unavailable.

        Args:
            location: The location to look up weather information for (e.g. city name)
        """

        <http://logger.info|logger.info>(f"Looking up weather for {location}")

        return "sunny with a temperature of 70 degrees."


def prewarm(proc: JobProcess):
    proc.userdata["vad"] = silero.VAD.load()


async def entrypoint(ctx: JobContext):
    # Logging setup
    # Add any other context you want in all log entries here
    ctx.log_context_fields = {
        "room": ctx.room.name,
    }

    # Set up a voice AI pipeline using OpenAI, Cartesia, Deepgram, and the LiveKit turn detector
    session = AgentSession(
        # A Large Language Model (LLM) is your agent's brain, processing user input and generating a response
        # See all providers at <https://docs.livekit.io/agents/integrations/llm/>
        llm=openai.LLM.with_ollama(
            model="qwen2.5:3b", base_url="<http://localhost:11434/v1>", temperature=0.3
        ),
        # Speech-to-text (STT) is your agent's ears, turning the user's speech into text that the LLM can understand
        # See all providers at <https://docs.livekit.io/agents/integrations/stt/>
        stt=deepgram.STT(model="nova-3", language="multi"),
        # Text-to-speech (TTS) is your agent's voice, turning the LLM's text into speech that the user can hear
        # See all providers at <https://docs.livekit.io/agents/integrations/tts/>
        tts=cartesia.TTS(voice="6f84f4b8-58a2-430c-8c79-688dad597532"),
        # VAD and turn detection are used to determine when the user is speaking and when the agent should respond
        # See more at <https://docs.livekit.io/agents/build/turns>
        turn_detection=MultilingualModel(),
        vad=ctx.proc.userdata["vad"],
        # allow the LLM to generate a response while waiting for the end of turn
        # See more at <https://docs.livekit.io/agents/build/audio/#preemptive-generation>
        preemptive_generation=True,
    )

    # To use a realtime model instead of a voice pipeline, use the following session setup instead:
    # session = AgentSession(
    #     # See all providers at <https://docs.livekit.io/agents/integrations/realtime/>
    #     llm=openai.realtime.RealtimeModel(voice="marin")
    # )

    # sometimes background noise could interrupt the agent session, these are considered false positive interruptions
    # when it's detected, you may resume the agent's speech
    @session.on("agent_false_interruption")
    def _on_agent_false_interruption(ev: AgentFalseInterruptionEvent):
        <http://logger.info|logger.info>("false positive interruption, resuming")
        session.generate_reply(instructions=ev.extra_instructions or NOT_GIVEN)

    # Metrics collection, to measure pipeline performance
    # For more information, see <https://docs.livekit.io/agents/build/metrics/>
    usage_collector = metrics.UsageCollector()

    @session.on("metrics_collected")
    def _on_metrics_collected(ev: MetricsCollectedEvent):
        metrics.log_metrics(ev.metrics)
        usage_collector.collect(ev.metrics)

    async def log_usage():
        summary = usage_collector.get_summary()
        <http://logger.info|logger.info>(f"Usage: {summary}")

    ctx.add_shutdown_callback(log_usage)

    # # Add a virtual avatar to the session, if desired
    # # For other providers, see <https://docs.livekit.io/agents/integrations/avatar/>
    # avatar = hedra.AvatarSession(
    #   avatar_id="...",  # See <https://docs.livekit.io/agents/integrations/avatar/hedra>
    # )
    # # Start the avatar and wait for it to join
    # await avatar.start(session, room=ctx.room)

    # Start the session, which initializes the voice pipeline and warms up the models
    await session.start(
        agent=Assistant(),
        room=ctx.room,
        room_input_options=RoomInputOptions(
            # LiveKit Cloud enhanced noise cancellation
            # - If self-hosting, omit this parameter
            # - For telephony applications, use `BVCTelephony` for best results
            noise_cancellation=noise_cancellation.BVC(),
        ),
    )

    # Join the room and connect to the user
    await ctx.connect()


if __name__ == "__main__":
    cli.run_app(
        WorkerOptions(
            entrypoint_fnc=entrypoint,
            prewarm_fnc=prewarm,
            agent_name="telephony-voice-assistant",
        )
    )
on console it works
t
It looks like the audio is working fine in the console but not during SIP calls. Let’s walk through some steps together to help get this sorted out: 1. Verify Audio Routing: Double-check that the agent’s audio input and output are correctly routed to the LiveKit room during SIP calls. It’s important to avoid hardcoding console-specific audio sources when in SIP mode. 2. Check Audio Track Publishing: Make sure the SIP participant’s audio track is being published to the room using
NewParticipantTrack
and
WriteAudioTo()
. This helps ensure the audio is properly shared. 3. Enable Echo and Noise Cancellation: Try applying echo cancellation and noise suppression settings for SIP audio, similar to what’s used in console mode. This can really improve the call quality. 4. Increase Audio Queue Size: If you notice audio frames are dropping, increasing the
queue_size_ms
in
rtc.AudioSource
to somewhere between 1000–2000ms might help smooth things out. 5. Verify Codec Compatibility: Check that your SIP trunk supports wideband codecs like G.722 for HD voice. If needed, enabling G.711u can help with compatibility. 6. Debug Audio Tracks: Using LiveKit’s Chrome Developer Extension to inspect audio tracks can be really useful. It lets you see if the tracks are active and properly rendered during calls. 7. Match Agent and Dispatch Rule Names: Lastly, ensure the
agent_name
matches exactly in both the agent’s configuration and the dispatch rule to avoid any mismatches. If you’d like, I’m here to help you with any of these steps or answer any questions you have. Just let me know! Sources: Getting Help | livekit/livekit_composite | DeepWiki | HD voice for SIP | LiveKit Docs | livekit-agents/livekit/agents/voice/chat_cli.py | test/lktest/livekit.go | SIP troubleshooting guide | LiveKit Docs
m
Could you finalize my docker file i am on macOS and running this in container and making inbound calls via zoiper
Copy code
services:
    redis:
        image: redis
        command: redis-server --requirepass ""
        volumes:
            - redis_data:/data
        ports:
            - 6379:6379
    livekit:
        image: livekit/livekit-server
        command: --dev --redis-host redis:6379 --bind 0.0.0.0
        ports:
            - "7880:7880"
            - "7881:7881"
            - "50000-60000:50000-60000/udp" # Correct LiveKit ICE/UDP range
        depends_on:
            redis:
                condition: service_started
    sip:
        image: livekit/sip
        ports:
            - "5060:5060/udp"
            - "5060:5060/tcp"
            - "10000-20000:10000-20000/udp" # Correct SIP RTP range per docs
        environment:
            SIP_CONFIG_BODY: |
                api_key: 'devkey'
                api_secret: 'secret'
                ws_url: '<ws://livekit:7880>'
                redis:
                  address: 'redis:6379'
                sip_port: 5060
                rtp_port: 10000-20000  # Match LiveKit docs for SIP RTP
                use_external_ip: true
                media_use_external_ip: true
                logging:
                  level: debug
        depends_on:
            livekit:
                condition: service_started
            redis:
                condition: service_started
volumes:
    redis_data:
t
I'm happy to share the finalized Docker configuration for running LiveKit, SIP, and Redis on macOS with inbound SIP calls. This setup should help you get everything up and running smoothly:
Copy code
services:
  redis:
    image: redis
    volumes:
      - redis_data:/data
    ports:
      - 6379:6379

  livekit:
    image: livekit/livekit-server
    command: --dev --redis-host redis:6379 --bind 0.0.0.0
    ports:
      - "7880:7880"
      - "7881:7881"
      - "50000-60000:50000-60000/udp" # ICE/UDP range for LiveKit
    depends_on:
      redis:
        condition: service_started

  sip:
    image: livekit/sip
    ports:
      - "5060:5060/udp"
      - "5060:5060/tcp"
      - "10000-20000:10000-20000/udp" # RTP range for SIP
    environment:
      SIP_CONFIG_BODY: |
        api_key: 'devkey'
        api_secret: 'secret'
        ws_url: '<ws://livekit:7880>'
        redis:
          address: 'redis:6379'
        sip_port: 5060
        rtp_port: 10000-20000
        use_external_ip: true
        media_use_external_ip: true
        logging:
          level: debug
    depends_on:
      livekit:
        condition: service_started
      redis:
        condition: service_started

volumes:
  redis_data:
Here are a few key points to keep in mind:Redis: This stores your session data and is accessible on port 6379. • LiveKit: It’s set up with ICE/UDP ports (50000-60000) to handle WebRTC media smoothly. • SIP: Handles SIP signaling on port 5060 and RTP media on ports 10000-20000. • Environment Variables: Make sure the
ws_url
correctly points to your LiveKit server, and that Redis is properly linked. When you’re ready, simply start the services by running:
Copy code
docker compose up
If you have any questions or need a hand setting up SIP trunks or dispatch rules, please don’t hesitate to reach out. I’m here to help! Sources: Self-hosted SIP server | LiveKit Docs | Accepting inbound calls | LiveKit Docs | test/integration/sip_test.go