> ## Documentation Index
> Fetch the complete documentation index at: https://docs.camb.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# LiveKit

> Build real-time voice AI agents with Camb.ai TTS and LiveKit Agents

<Note>Integration with LiveKit is currently being reviewed</Note>

## Overview

The **livekit-plugins-camb** package enables you to integrate Camb.ai's MARS text-to-speech models into your LiveKit voice agents. This integration provides high-quality, low-latency voice synthesis for real-time conversational AI applications.

### Key Features

* **MARS Models**: Access to Camb.ai's latest generation TTS models (mars-flash, mars-pro)
* **Multilingual**: Up to 158 languages depending on the MARS model — see [Language Support](/language-support)
* **Real-time Streaming**: HTTP chunked streaming for low-latency audio
* **Voice Customization**: Voice selection and enhanced pronunciation for names/places
* **Model-specific Sample Rates**: 22.05kHz (mars-flash) or 48kHz (mars-pro)

***

## Installation

### Prerequisites

* Python 3.9 or higher
* A Camb.ai API key ([get one here](https://studio.camb.ai))
* LiveKit Cloud account or self-hosted LiveKit server

### Install the Plugin

```bash theme={null}
pip install livekit-plugins-camb
```

For a complete voice agent setup with VAD (Voice Activity Detection):

```bash theme={null}
pip install livekit-plugins-camb 'livekit-agents[silero]' python-dotenv
```

***

## Quick Start

### 1. Set Up Environment Variables

Create a `.env` file in your project directory:

```bash theme={null}
# Camb.ai API key
CAMB_API_KEY=your_camb_api_key

# LiveKit credentials
LIVEKIT_URL=wss://your-project.livekit.cloud
LIVEKIT_API_KEY=your_livekit_api_key
LIVEKIT_API_SECRET=your_livekit_api_secret

# LLM provider (e.g., OpenAI)
OPENAI_API_KEY=your_openai_api_key

# STT provider (e.g., Deepgram)
DEEPGRAM_API_KEY=your_deepgram_api_key
```

### 2. Create Your Voice Agent

```python theme={null}
import logging

from dotenv import load_dotenv
from livekit.agents import (
    Agent,
    AgentServer,
    AgentSession,
    JobContext,
    JobProcess,
    cli,
    room_io,
)
from livekit.plugins import camb, silero

load_dotenv()

logger = logging.getLogger("voice-agent")


class MyAgent(Agent):
    def __init__(self) -> None:
        super().__init__(
            instructions=(
                "You are a helpful voice assistant. "
                "Keep your responses concise and conversational. "
                "Do not use emojis or special formatting."
            ),
        )

    async def on_enter(self):
        # Generate initial greeting
        self.session.generate_reply(allow_interruptions=False)


server = AgentServer()


def prewarm(proc: JobProcess):
    # Pre-load VAD model for faster startup
    proc.userdata["vad"] = silero.VAD.load()


server.setup_fnc = prewarm


@server.rtc_session()
async def entrypoint(ctx: JobContext):
    session = AgentSession(
        # Speech-to-text
        stt="deepgram/nova-3",
        # Language model
        llm="openai/gpt-4.1-mini",
        # Camb.ai TTS
        tts=camb.TTS(),
        # Voice activity detection
        vad=ctx.proc.userdata["vad"],
    )

    await session.start(
        agent=MyAgent(),
        room=ctx.room,
    )


if __name__ == "__main__":
    cli.run_app(server)
```

### 3. Run Your Agent

**Development mode** (with LiveKit Agents Playground):

```bash theme={null}
python your_agent.py dev
```

**Production mode**:

```bash theme={null}
python your_agent.py start
```

***

## Configuration

### TTS Options

The `camb.TTS` class accepts the following parameters:

| Parameter                | Type   | Default                | Description                                                   |
| ------------------------ | ------ | ---------------------- | ------------------------------------------------------------- |
| `api_key`                | `str`  | `CAMB_API_KEY` env var | Your Camb.ai API key                                          |
| `voice_id`               | `int`  | `147320`               | Voice ID (use `list_voices()` to discover)                    |
| `language`               | `str`  | `"en-us"`              | BCP-47 language code                                          |
| `model`                  | `str`  | `"mars-flash"`         | MARS model to use (`mars-flash` or `mars-pro`)                |
| `output_format`          | `str`  | `"pcm_s16le"`          | Audio format                                                  |
| `enhance_named_entities` | `bool` | `False`                | Enhanced pronunciation for names and places                   |
| `sample_rate`            | `int`  | Auto-detected          | Audio sample rate (auto-detected from model if not specified) |

### Available Models

<Tabs>
  <Tab title="Fast (Recommended)">
    ```python theme={null}
    tts=camb.TTS(model="mars-flash")
    ```

    Best for real-time voice agents. Lowest latency (22.05kHz) with high quality.
  </Tab>

  <Tab title="High Quality">
    ```python theme={null}
    tts=camb.TTS(model="mars-pro")
    ```

    Higher quality synthesis at 48kHz sample rate.
  </Tab>
</Tabs>

### Language Support

Camb.ai supports up to 158 languages depending on the MARS model — see [Language Support](/language-support) for the full per-model locale list. Specify the language using BCP-47 codes:

```python theme={null}
# English (US)
tts=camb.TTS(language="en-us")

# French
tts=camb.TTS(language="fr-fr")

# Spanish
tts=camb.TTS(language="es-es")

# German
tts=camb.TTS(language="de-de")

# Japanese
tts=camb.TTS(language="ja-jp")
```

***

## Advanced Usage

### Dynamic Option Updates

Update TTS settings during a session:

```python theme={null}
# Change voice mid-conversation
session.tts.update_options(voice_id=1234)

# Switch model
session.tts.update_options(model="mars-pro")

# Switch language
session.tts.update_options(language="es-es")
```

### Function Tools

Add custom capabilities to your agent using the `@function_tool` decorator. The LLM automatically discovers these functions and calls them based on user conversation.

```python theme={null}
from livekit.agents.llm import function_tool
from livekit.agents import RunContext

class MyAgent(Agent):
    def __init__(self) -> None:
        super().__init__(
            instructions="You are a helpful assistant that can look up weather.",
        )

    @function_tool
    async def lookup_weather(
        self,
        context: RunContext,
        location: str,
        latitude: str,
        longitude: str
    ):
        """Called when the user asks for weather related information.
        Ensure the user's location (city or region) is provided.
        When given a location, please estimate the latitude and longitude of the location and
        do not ask the user for them.

        Args:
            location: The location they are asking for
            latitude: The latitude of the location, do not ask user for it
            longitude: The longitude of the location, do not ask user for it
        """
        # Your weather lookup logic here
        return "sunny with a temperature of 70 degrees."
```

For more details, see the [LiveKit Function Tools documentation](https://docs.livekit.io/agents/logic/tools/).

### Custom HTTP Session

For advanced use cases, provide your own aiohttp session:

```python theme={null}
import aiohttp

async with aiohttp.ClientSession() as session:
    tts = camb.TTS(http_session=session)
    # Use TTS...
```

### Metrics and Logging

Track usage and performance:

```python theme={null}
from livekit.agents import metrics, MetricsCollectedEvent

usage_collector = metrics.UsageCollector()

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

# Get usage summary after session
summary = usage_collector.get_summary()
logger.info(f"Session usage: {summary}")
```

***

## Full Voice Agent Example

Here's a full example combining all features.

### Installation

```bash theme={null}
pip install livekit-plugins-camb 'livekit-agents[silero]' python-dotenv
```

### Code

```python theme={null}
import logging

from dotenv import load_dotenv

from livekit.agents import (
    Agent,
    AgentServer,
    AgentSession,
    JobContext,
    JobProcess,
    MetricsCollectedEvent,
    RunContext,
    cli,
    metrics,
    room_io,
)
from livekit.agents.llm import function_tool
from livekit.plugins import camb, silero
from livekit.plugins.turn_detector.multilingual import MultilingualModel

logger = logging.getLogger("basic-agent")

load_dotenv()


class MyAgent(Agent):
    def __init__(self) -> None:
        super().__init__(
            instructions="Your name is Kelly. You would interact with users via voice."
            "with that in mind keep your responses concise and to the point."
            "do not use emojis, asterisks, markdown, or other special characters in your responses."
            "You are curious and friendly, and have a sense of humor."
            "you will speak english to the user",
        )

    async def on_enter(self):
        # when the agent is added to the session, it'll generate a reply
        # according to its instructions
        # Keep it uninterruptible so the client has time to calibrate AEC
        self.session.generate_reply(allow_interruptions=False)

    @function_tool
    async def lookup_weather(
        self, context: RunContext, location: str, latitude: str, longitude: str
    ):
        """Called when the user asks for weather related information.
        Ensure the user's location (city or region) is provided.
        When given a location, please estimate the latitude and longitude of the location and
        do not ask the user for them.

        Args:
            location: The location they are asking for
            latitude: The latitude of the location, do not ask user for it
            longitude: The longitude of the location, do not ask user for it
        """
        logger.info(f"Looking up weather for {location}")
        return "sunny with a temperature of 70 degrees."


server = AgentServer()


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


server.setup_fnc = prewarm


@server.rtc_session()
async def entrypoint(ctx: JobContext):
    ctx.log_context_fields = {"room": ctx.room.name}

    session = AgentSession(
        stt="deepgram/nova-3",
        llm="openai/gpt-4.1-mini",
        tts=camb.TTS(),
        turn_detection=MultilingualModel(),
        vad=ctx.proc.userdata["vad"],
        preemptive_generation=True,
        resume_false_interruption=True,
        false_interruption_timeout=1.0,
    )

    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()
        logger.info(f"Usage: {summary}")

    ctx.add_shutdown_callback(log_usage)

    await session.start(
        agent=MyAgent(),
        room=ctx.room,
        room_options=room_io.RoomOptions(
            audio_input=room_io.AudioInputOptions(),
        ),
    )


if __name__ == "__main__":
    cli.run_app(server)
```

### Run

**Development mode** (opens playground in browser):

```bash theme={null}
python your_agent.py dev
```

**Production mode:**

```bash theme={null}
python your_agent.py start
```

Then connect via the [LiveKit Agents Playground](https://agents-playground.livekit.io/).

***

## Troubleshooting

### Common Issues

<AccordionGroup>
  <Accordion title="Invalid API Key Error">
    Ensure your `CAMB_API_KEY` environment variable is set correctly:

    ```bash theme={null}
    export CAMB_API_KEY=your_api_key_here
    ```

    Or pass it directly:

    ```python theme={null}
    tts=camb.TTS(api_key="your_api_key")
    ```
  </Accordion>

  <Accordion title="Voice Not Found">
    The voice ID must be an integer. Use `list_voices()` to find available voices:

    ```python theme={null}
    voices = await camb.list_voices()
    print(voices)
    ```
  </Accordion>

  <Accordion title="Timeout Errors">
    TTS synthesis can take time for longer texts. The plugin automatically uses a minimum 60-second timeout.

    For very long texts, consider breaking them into smaller chunks.
  </Accordion>

  <Accordion title="Audio Quality Issues">
    * Use `mars-pro` for highest quality (48kHz) or `mars-flash` for best latency (22.05kHz)
    * Ensure your network connection is stable
    * Use `pcm_s16le` format for lowest latency
  </Accordion>

  <Accordion title="Connection Errors">
    Check that you can reach the Camb.ai API:

    ```bash theme={null}
    curl -H "x-api-key: YOUR_KEY" https://client.camb.ai/apis/list-voices
    ```
  </Accordion>
</AccordionGroup>

### Debug Logging

Enable debug logging for detailed information:

```python theme={null}
import logging

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger("livekit.plugins.camb")
logger.setLevel(logging.DEBUG)
```

***

## Resources

* [LiveKit Agents Documentation](https://docs.livekit.io/agents/)
* [LiveKit Agents Playground](https://agents-playground.livekit.io/)
* [Camb.ai API Reference](/api-reference/endpoint/create-tts)
* [LiveKit Agents GitHub Repository](https://github.com/livekit/agents)
* [LiveKit Slack Community](https://livekit.io/join-slack)
