LiveKit SIP

repository·main·Indexed 19 days ago

https://github.com/livekit/sip

A bridge service that connects telephony networks via SIP to LiveKit WebRTC sessions. It enables integrating traditional phone calls into LiveKit rooms, supporting features such as dialing in and out, SIP Trunking, SIP Dispatch Rules, digest authentication, and DTMF. The service is written in Go and uses Redis for session state and communication with the LiveKit server.

Tokens
5.2K
Snippets
24
Records
30
Agent score
66%

What's inside livekit-sip

  1. How the LiveKit SIP Service works

    main

    The LiveKit SIP service acts as a bridge between WebRTC sessions and telephony networks using SIP Trunking. It allows you to bring SIP traffic into a LiveKit room, enabling features like dialing out (sending INVITEs), dialing in (accepting INVITEs), digest authentication, and DTMF (touch tone) support.

    Inbound Call Workflow

    To accept inbound calls, you must follow these steps:

    1. Create an SIP Trunk using the CreateSIPTrunk API (via LiveKit server).
    2. Create an SIP Dispatch Rule using the CreateSIPDispatchRule API (via LiveKit server).
    3. When a call is received, the SIP service connects to the specified LiveKit room, and the SIP caller joins as a participant.

    Service Architecture

    The SIP service communicates with the LiveKit server via Redis, which is also used to store SIP session state. Note that the SIP service must expose a public IP address to allow remote SIP peers to connect.

  2. Run SIP Service with Docker

    main

    To run the SIP service in Docker, you must use the --network host flag because the service requires a large range of UDP ports (10000-20000) which are difficult for Docker to manage via standard bridge networking.

    When running locally, use host.docker.internal to connect to the host's LiveKit and Redis instances (use 172.17.0.1 on Linux).

    Example Command

    docker run --rm \
        -e SIP_CONFIG_BODY="$(cat config.yaml)" \
        --network host \
        livekit/sip
    docker run --rm \
        -e SIP_CONFIG_BODY="`cat config.yaml`" \
        --network host \
        livekit/sip
  3. Install and Run SIP Service natively

    main

    The SIP service is written in Go and requires libopus to be installed on the host system.

    Prerequisites

    Go >= 1.18

    Dependencies:

    • Debian: sudo apt-get install pkg-config libopus-dev libopusfile-dev libsoxr-dev
    • macOS: brew install pkg-config opus opusfile libsoxr

    Build and Run

    1. Build using mage:
      mage build
    2. Run the service (ensure a local Redis and LiveKit server are running):
      sip --config=config.yaml
    mage build
    sip --config=config.yaml
  4. Understand CallDispatch results

    main

    When implementing DispatchCall, the DispatchResult returned determines the fate of the incoming SIP call:

    • DispatchAccept: The call is accepted and routed to the configured room.
    • DispatchRequestPin: The call requires a PIN before being connected.
    • DispatchNoRuleReject: The call is rejected with an error.
    • DispatchNoRuleDrop: The call is silently dropped.
    • DispatchServiceUnavailable: The dispatch rule evaluation failed at the transport level.
  5. Understand AuthResult outcomes

    main

    The AuthResult returned by GetAuthCredentials dictates how the server handles SIP authentication:

    • AuthNotFound: Authentication credentials not found.
    • AuthDrop: Drop the call due to authentication failure.
    • AuthPassword: Use the provided password for authentication.
    • AuthAccept: Accept the call based on the provided credentials.
    • AuthQuotaExceeded: Reject the call because the user has exceeded their quota.
    • AuthNoTrunkFound: No matching trunk was found for the request.
  6. Configure the LiveKit SIP Service

    main

    The SIP service is configured using a YAML file. You can provide the configuration via the SIP_CONFIG_FILE environment variable (pointing to a file path) or the SIP_CONFIG_BODY environment variable (containing the raw YAML string).

    Required Fields

    • api_key: LiveKit server API key (or LIVEKIT_API_KEY env).
    • api_secret: LiveKit server API secret (or LIVEKIT_API_SECRET env).
    • ws_url: LiveKit server websocket URL (or LIVEKIT_WS_URL env).
    • redis:
      • address: Redis address used by the LiveKit server.
      • username: Redis username.
      • password: Redis password.
      • db: Redis database index.

    Optional Fields

    • health_port: HTTP port for health checks.
    • prometheus_port: Port for Prometheus metrics collection.
    • log_level: debug, info, warn, or error (default: info).
    • sip_port: Port for SIP traffic (default: 5060).
    • rtp_port: Port range for RTP traffic (default: 10000-20000).
    # required fields
    api_key: livekit server api key. LIVEKIT_API_KEY env can be used instead
    api_secret: livekit server api secret. LIVEKIT_API_SECRET env can be used instead
    ws_url: livekit server websocket url. LIVEKIT_WS_URL env can be used instead
    redis:
      address: must be the same redis address used by your livekit server
      username: redis username
      password: redis password
      db: redis db
    
    # optional fields
    health_port: if used, will open an http port for health checks
    prometheus_port: port used to collect prometheus metrics. Used for autoscaling
    log_level: debug, info, warn, or error (default info)
    sip_port: port to listen and send SIP traffic (default 5060)
    rtp_port: port to listen and send RTP traffic (default 10000-20000)
  7. Run the LiveKit SIP service

    main

    The livekit-sip binary is the entrypoint for the LiveKit SIP service. It requires a YAML configuration to initialize components like Redis, monitoring, and the SIP server. You can provide the configuration via a file path or a raw YAML string.

    # Using a configuration file
    ./livekit-sip --config /path/to/config.yaml
    
    # Using a configuration body via environment variable
    export SIP_CONFIG_BODY="yaml_content_here"
    ./livekit-sip
  8. Run LiveKit SIP locally with Docker Compose

    main

    To run the LiveKit SIP service for testing and development, you can use the provided docker-compose.yaml. This setup includes a Redis instance, the LiveKit server, and the SIP service.

    Note that the configuration uses network_mode: host to facilitate local networking. If you are running on MacOS, you may need to adjust the networking or ensure the services can communicate via localhost as configured in the environment variables.

    services:
      redis:
        image: redis
        volumes:
          - redis_data:/data
        ports:
          - 6379:6379
      livekit:
        image: livekit/livekit-server
        command: --dev --redis-host localhost:6379
        network_mode: host
        depends_on:
            redis:
                condition: service_started
      sip:
        image: livekit/sip
        network_mode: host
        environment:
          SIP_CONFIG_BODY: |
            api_key: 'devkey'
            api_secret: 'secret'
            ws_url: 'ws://localhost:7880'
            redis:
              address: 'localhost:6379'
            sip_port: 5060
            rtp_port: 10000-20000
            use_external_ip: true
            logging:
              level: debug
    volumes:
      redis_data:
  9. Encode audio to PCM16LE

    main

    To encode an audio file (e.g., .ogg) to the PCM16LE format required for SIP media resources, use ffmpeg with an 8000Hz sample rate and the s16le format.

    ffmpeg -i file.ogg -ar 8000 -f s16le file.s16le