LiveKit docs › Get Started › SDK platform quickstarts › C++

---

# C++ quickstart

> Get started with LiveKit using the C++ SDK.

## Overview

The C++ SDK connects native desktop, server, robotics, and embedded applications to LiveKit rooms.

### Supported platforms

The SDK is built and released for the following platforms:

| Platform | Architecture |
| Windows | x64 |
| Linux | x86_64 and ARM |
| macOS | x86_64 and ARM |
| Nvidia Jetson | ARM |
| Raspberry Pi | ARM |

If no prebuilt release asset matches your platform, `LiveKitSDK.cmake` fails during CMake configure. In that case, build the SDK from source and use `LIVEKIT_LOCAL_SDK_DIR`.

## Install the C++ SDK

The easiest way to consume the SDK is to use a prebuilt release. The [C++ example collection](https://github.com/livekit-examples/cpp-example-collection) includes a [CMake helper](https://github.com/livekit-examples/cpp-example-collection/blob/main/cmake/LiveKitSDK.cmake) that downloads the matching prebuilt SDK archive during CMake configure and makes `find_package(LiveKit CONFIG REQUIRED)` work. It also lets you point at a local C++ SDK install.

1. Copy [`cmake/LiveKitSDK.cmake`](https://github.com/livekit-examples/cpp-example-collection/blob/main/cmake/LiveKitSDK.cmake) into your project's `cmake/` directory.
2. Include the helper in your app's `CMakeLists.txt` file:

```cmake
cmake_minimum_required(VERSION 3.20)
project(livekit_cpp_quickstart LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

if(LIVEKIT_LOCAL_SDK_DIR)
  list(PREPEND CMAKE_PREFIX_PATH "${LIVEKIT_LOCAL_SDK_DIR}")
else()
  include(LiveKitSDK)
  livekit_sdk_setup(
    VERSION "${LIVEKIT_SDK_VERSION}"
    SDK_DIR "${CMAKE_BINARY_DIR}/_deps/livekit-sdk"
    GITHUB_TOKEN "$ENV{GITHUB_TOKEN}"
  )
endif()

find_package(LiveKit CONFIG REQUIRED)

add_executable(example example.cpp)
target_link_libraries(example PRIVATE LiveKit::livekit)

```
3. Configure and build your project:

```bash
cmake -S . -B build -DLIVEKIT_SDK_VERSION=latest
cmake --build build

```

> 💡 **Pin SDK versions**
> 
> Use a fixed version from the official [C++ SDK releases page](https://github.com/livekit/client-sdk-cpp/releases) for reproducible builds. The `latest` option queries the GitHub API and may need `GITHUB_TOKEN` in CI to avoid rate limits.

### Use a local SDK build

You may want to use a local SDK build to use a specific version of the SDK that is not yet released, or to test local changes to the SDK. To build the SDK from source, clone the [C++ SDK repository](https://github.com/livekit/client-sdk-cpp) with submodules and install it to a local prefix:

```bash
git clone --recurse-submodules https://github.com/livekit/client-sdk-cpp.git
cd client-sdk-cpp

# Build the SDK:
# --bundle installs the SDK bundle using 'cmake --install'
# --prefix specifies where to install the SDK
./build.sh release --bundle --prefix "$HOME/livekit-sdk"

```

Then configure your app with the local install prefix:

```bash
cmake -S . -B build -DLIVEKIT_LOCAL_SDK_DIR="$HOME/livekit-sdk"
cmake --build build

```

## Connecting to LiveKit

The following example connects to a room and publishes synthetic audio and video tracks. It generates a sine wave and a moving color pattern so you can verify publishing without device capture.

For a production app, make the following changes:

- [Generate tokens](https://docs.livekit.io/frontends/build/authentication/endpoint.md) on your server instead of embedding tokens in the app.
- Replace synthetic media generation with your own camera and microphone capture. For a complete SDL-based example, see [`simple_room`](https://github.com/livekit-examples/cpp-example-collection/tree/main/simple_room).

### Run an example

1. **Create a file** named `example.cpp` with the following content:

```cpp
#include <atomic>
#include <chrono>
#include <cmath>
#include <csignal>
#include <cstdint>
#include <cstdlib>
#include <exception>
#include <iostream>
#include <memory>
#include <thread>
#include <vector>

#include "livekit/livekit.h"

namespace {

std::atomic<bool> g_running{true};

void handleSignal(int) { g_running.store(false); }

void generateAudio(const std::shared_ptr<livekit::AudioSource>& audio_source) {
  constexpr int kSampleRate = 48000;
  constexpr int kChannels = 1;
  constexpr int kSamplesPer10Ms = kSampleRate / 100;
  constexpr double kFrequencyHz = 440.0;
  constexpr double kPi = 3.14159265358979323846;

  std::uint64_t sample_index = 0;

  while (g_running.load()) {
    std::vector<std::int16_t> samples(kSamplesPer10Ms * kChannels);
    for (int i = 0; i < kSamplesPer10Ms; ++i) {
      const double t = static_cast<double>(sample_index++) / kSampleRate;
      const double value = std::sin(2.0 * kPi * kFrequencyHz * t);
      samples[i] = static_cast<std::int16_t>(value * 16000.0);
    }

    livekit::AudioFrame frame(std::move(samples), kSampleRate, kChannels, kSamplesPer10Ms);
    audio_source->captureFrame(frame);
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
  }
}

void generateVideo(const std::shared_ptr<livekit::VideoSource>& video_source) {
  constexpr int kWidth = 1280;
  constexpr int kHeight = 720;
  constexpr int kFps = 30;

  int frame_count = 0;

  while (g_running.load()) {
    auto frame = livekit::VideoFrame::create(kWidth, kHeight, livekit::VideoBufferType::RGBA);
    std::uint8_t* pixels = frame.data();
    const auto hue = static_cast<std::uint8_t>((frame_count * 2) % 256);

    for (int y = 0; y < kHeight; ++y) {
      for (int x = 0; x < kWidth; ++x) {
        const int offset = (y * kWidth + x) * 4;
        pixels[offset] = static_cast<std::uint8_t>((x * 255) / kWidth);
        pixels[offset + 1] = static_cast<std::uint8_t>((y * 255) / kHeight);
        pixels[offset + 2] = hue;
        pixels[offset + 3] = 255;
      }
    }

    video_source->captureFrame(frame);
    ++frame_count;
    std::this_thread::sleep_for(std::chrono::milliseconds(1000 / kFps));
  }
}

} // namespace

int main() {
  const char* url = std::getenv("LIVEKIT_URL");
  const char* token = std::getenv("LIVEKIT_TOKEN");
  if (url == nullptr || token == nullptr) {
    std::cerr << "Set LIVEKIT_URL and LIVEKIT_TOKEN environment variables\n";
    return 1;
  }

  std::signal(SIGINT, handleSignal);

  livekit::initialize(livekit::LogLevel::Info);

  auto room = std::make_unique<livekit::Room>();
  livekit::RoomOptions room_options;
  room_options.auto_subscribe = true;

  if (!room->connect(url, token, room_options)) {
    std::cerr << "Failed to connect\n";
    livekit::shutdown();
    return 1;
  }

  std::cout << "Connected to room\n";

  auto audio_source = std::make_shared<livekit::AudioSource>(48000, 1);
  auto audio_track = livekit::LocalAudioTrack::createLocalAudioTrack("audio", audio_source);

  livekit::TrackPublishOptions audio_options;
  audio_options.source = livekit::TrackSource::SOURCE_MICROPHONE;

  try {
    if (auto lp = room->localParticipant().lock()) {
      lp->publishTrack(audio_track, audio_options);
    }
    else
    {
      std::cerr << "Failed to get local participant\n";
      return 1;
    }
    std::cout << "Published audio track\n";
  } catch (const std::exception& error) {
    std::cerr << "Failed to publish audio: " << error.what() << "\n";
    return 1;
  }

  auto video_source = std::make_shared<livekit::VideoSource>(1280, 720);
  auto video_track = livekit::LocalVideoTrack::createLocalVideoTrack("video", video_source);

  livekit::TrackPublishOptions video_options;
  video_options.source = livekit::TrackSource::SOURCE_CAMERA;

  try {
    if (auto lp = room->localParticipant().lock()) {
      lp->publishTrack(video_track, video_options);
    }
    else
    {
      std::cerr << "Failed to get local participant\n";
      return 1;
    }
    std::cout << "Published video track\n";
  } catch (const std::exception& error) {
    std::cerr << "Failed to publish video: " << error.what() << "\n";
    return 1;
  }

  std::thread audio_thread(generateAudio, audio_source);
  std::thread video_thread(generateVideo, video_source);

  std::cout << "Streaming synthetic audio and video. Press Ctrl+C to stop.\n";
  while (g_running.load()) {
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
  }

  if (audio_thread.joinable()) {
    audio_thread.join();
  }
  if (video_thread.joinable()) {
    video_thread.join();
  }

  room.reset();
  livekit::shutdown();
  return 0;
}

```
2. **Set environment variables** with your LiveKit server URL and access token:

```bash
export LIVEKIT_URL=wss://your-livekit-server.com
export LIVEKIT_TOKEN=your-access-token

```
3. **Run the example**:

```bash
./build/example

```

The program connects to a LiveKit room and streams a 440 Hz sine wave audio tone and an animated color gradient video. Press `Ctrl+C` to stop.

> ℹ️ **Capturing real media**
> 
> The SDK accepts raw audio and video frames from your application. It doesn't open the camera or microphone for you. For physical device capture, see the [`simple_room`](https://github.com/livekit-examples/cpp-example-collection/tree/main/simple_room) example, which uses SDL3.

## Permissions and entitlements

Most C++ applications don't need operating system permission prompts unless the app accesses physical microphones, cameras, screens, or other devices. Headless or synthetic sources don't require special device permissions.

Microphone or camera capture:

| Operating system | Required permissions |
| **macOS** | Add `NSMicrophoneUsageDescription` and `NSCameraUsageDescription` to your app bundle when applicable. |
| **Windows/Linux** | Device permissions are typically managed by the OS, desktop session, container runtime, or user group membership. |

Screen capture:

| Operating system | Required permissions |
| **macOS** | Add Screen Recording permission for your app in System Settings. |
| **Windows/Linux** | Screen capture permissions are typically managed by the OS, desktop session, display server, or portal implementation. |

## Next steps

The following resources are useful for getting started with LiveKit on C++.

- **[Generating tokens](https://docs.livekit.io/frontends/build/authentication/endpoint.md)**: Guide to generating authentication tokens for your users.

- **[Basic room example](https://github.com/livekit-examples/cpp-example-collection/tree/main/basic_room)**: Minimal C++ example for connecting and publishing synthetic audio and video.

- **[Simple room example](https://github.com/livekit-examples/cpp-example-collection/tree/main/simple_room)**: SDL-based C++ example with real microphone and camera capture.

- **[RPC example](https://github.com/livekit-examples/cpp-example-collection/tree/main/simple_rpc)**: C++ example for registering RPC handlers and calling remote participants.

- **[Data streams example](https://github.com/livekit-examples/cpp-example-collection/tree/main/simple_data_stream)**: C++ example for text and byte streams with topics, metadata, and chunked payloads.

- **[C++ SDK](https://github.com/livekit/client-sdk-cpp)**: LiveKit C++ SDK source code and releases.

- **[C++ SDK reference](https://docs.livekit.io/reference/client-sdk-cpp.md)**: LiveKit C++ SDK reference docs.

---

This document was rendered at 2026-06-07T11:33:36.128Z.
For the latest version of this document, see [https://docs.livekit.io/transport/sdk-platforms/cpp.md](https://docs.livekit.io/transport/sdk-platforms/cpp.md).

To explore all LiveKit documentation, see [llms.txt](https://docs.livekit.io/llms.txt).