Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# Make "include(LiveKitSDK)" search in ./cmake
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

set(LIVEKIT_SDK_VERSION "latest" CACHE STRING "LiveKit C++ SDK version (e.g. 0.2.0 or latest)")
set(LIVEKIT_SDK_VERSION "latest" CACHE STRING "LiveKit C++ SDK version (e.g. 1.3.0 or latest)")
set(LIVEKIT_LOCAL_SDK_DIR "" CACHE PATH "Path to a local LiveKit SDK install prefix (skips download)")

if(LIVEKIT_LOCAL_SDK_DIR)
Expand Down Expand Up @@ -82,6 +82,7 @@ endfunction()
include(ExampleDeps)

add_subdirectory(basic_room)
add_subdirectory(token_source)
add_subdirectory(simple_room)
add_subdirectory(simple_rpc)
add_subdirectory(simple_data_stream)
Expand Down
98 changes: 64 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,78 +1,107 @@
# cpp-example-collection

This repository contains a collection of small, self-contained examples for the
[LiveKit C++ SDK](https://github.com/livekit/client-sdk-cpp).

The goal of these examples is to demonstrate common usage patterns of the
LiveKit C++ SDK (connecting to a room, publishing tracks, RPC, data streams,
etc.) without requiring users to build the SDK from source.


## How the SDK is provided

These examples **automatically download a prebuilt LiveKit C++ SDK release**
from GitHub at CMake configure time.

This is handled by the cmake helper: [LiveKitSDK.cmake ](https://github.com/livekit-examples/cpp-example-collection/cmake/LiveKitSDK.cmake)
This is handled by the CMake helper:
[`LiveKitSDK.cmake`](https://github.com/livekit-examples/cpp-example-collection/blob/main/cmake/LiveKitSDK.cmake).

## Selecting a LiveKit SDK version
By default, CMake resolves `LIVEKIT_SDK_VERSION=latest` to the newest GitHub
release and downloads the matching archive for your platform. The extracted SDK
lands under **build/_deps/livekit-sdk/**.

By default, the examples download the **latest released** LiveKit C++ SDK.
## Building the examples

You can pin a specific SDK version using the `LIVEKIT_SDK_VERSION` CMake option.
Run these from the repository root. All examples — including
[`token_source/`](token_source/) — build together in one pass.

### Examples
### macOS / Linux

Use the latest release:
```bash
cmake -S . -B build
# Or use a specific version (recommended for reproducibility):
cmake -S . -B build -DLIVEKIT_SDK_VERSION=0.2.0
cmake --build build
```

Reconfigure to change versions:
```bash
rm -rf build
cmake -S . -B build -DLIVEKIT_SDK_VERSION=0.3.1
### Windows (Visual Studio generator)

```powershell
cmake -S . -B build
cmake --build build --config Release
```

Build against a local SDK:
The token source examples require LiveKit C++ SDK **v1.3.0** or newer. If
configure succeeds but those targets fail to compile, pin the SDK version
explicitly:

```bash
rm -rf build
# install the SDK into $HOME/livekit-sdk-install (or any other directory)
cmake --install <sdk-build-dir> --prefix $HOME/livekit-sdk-install

# build the examples against the local SDK
cmake -S . -B build -DLIVEKIT_LOCAL_SDK_DIR=$HOME/livekit-sdk-install
cmake -S . -B build -DLIVEKIT_SDK_VERSION=1.3.0
cmake --build build
```

### Selecting an SDK version

Pin a specific release with `-DLIVEKIT_SDK_VERSION`:

### Building the examples
#### macOS / Linux
```bash
cmake -S . -B build # add -DLIVEKIT_SDK_VERSION=0.2.0 if using a specific version
cmake --build build
cmake -S . -B build -DLIVEKIT_SDK_VERSION=1.3.0
```

#### Windows (Visual Studio generator)
```powershell
cmake -S . -B build # add -DLIVEKIT_SDK_VERSION=0.2.0 if using a specific version
cmake --build build --config Release
When changing versions, remove the build directory first so CMake re-downloads
the SDK:

```bash
rm -rf build
cmake -S . -B build -DLIVEKIT_SDK_VERSION=1.3.0
```

The Livekit Release SDK is downloaded into **build/_deps/livekit-sdk/**
### Build against a local SDK

### Running the examples
Use this when validating an unreleased `client-sdk-cpp` commit, or when a
release tag exists but its prebuilt archives are not yet published:

After building, example binaries are located under:
```bash
build/<example-name>/
git clone --recurse-submodules https://github.com/livekit/client-sdk-cpp.git
cd client-sdk-cpp
./build.sh release --bundle --prefix "$HOME/livekit-sdk-install"

cd /path/to/cpp-example-collection
rm -rf build
cmake -S . -B build -DLIVEKIT_LOCAL_SDK_DIR="$HOME/livekit-sdk-install"
cmake --build build
```

### Troubleshooting configure

- **Start from a clean build directory** after a failed configure or download:
`rm -rf build`
- **GitHub API rate limits** when resolving `latest`: pin
`-DLIVEKIT_SDK_VERSION=1.3.0`, or export `GITHUB_TOKEN` and re-run configure.
- **404 on SDK download**: the release may not have platform archives yet. Pin
an older release that does, or use `-DLIVEKIT_LOCAL_SDK_DIR` as above.

## Running the examples

After building, example binaries are located under `build/<example-name>/`.

For example:

```bash
./build/basic_room/basic_room --url <ws-url> --token <token>
```

See [`token_source/README.md`](token_source/README.md) for the token-source
examples.

### PlatformAudio

The `platform_audio` examples show microphone capture and speaker playout using
Expand All @@ -86,8 +115,9 @@ WebRTC's platform Audio Device Module:
### Supported platforms

Prebuilt SDKs are downloaded automatically for:
* Windows: x64
* macOS: x64, arm64 (Apple Silicon)
* Linux: x64

- Windows: x64
- macOS: x64, arm64 (Apple Silicon)
- Linux: x64

If no matching SDK is available for your platform, CMake configuration will fail with a clear error.
45 changes: 45 additions & 0 deletions token_source/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Copyright 2026 LiveKit, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# One executable per token source type. Each shares token_source_common.h for
# the logging delegate and the connect/observe session loop.

# Resolve the SDK lib directory so -llivekit_ffi is found at link time.
get_filename_component(_lk_cmake_dir "${LiveKit_DIR}" DIRECTORY) # .../lib/cmake
get_filename_component(_lk_lib_dir "${_lk_cmake_dir}" DIRECTORY) # .../lib

set(_token_source_examples
token_source_literal token_source_literal.cpp
token_source_endpoint token_source_endpoint.cpp
token_source_sandbox token_source_sandbox.cpp
token_source_custom token_source_custom.cpp
token_source_caching token_source_caching.cpp
)

list(LENGTH _token_source_examples _count)
math(EXPR _last "${_count} - 1")
foreach(_i RANGE 0 ${_last} 2)
list(GET _token_source_examples ${_i} _target)
math(EXPR _src_idx "${_i} + 1")
list(GET _token_source_examples ${_src_idx} _src)

add_executable(${_target} ${_src})
target_include_directories(${_target} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(${_target} PRIVATE ${LIVEKIT_CORE_TARGET})
target_link_directories(${_target} PRIVATE "${_lk_lib_dir}")

livekit_copy_windows_runtime_dlls(${_target})
endforeach()

unset(_token_source_examples)
125 changes: 125 additions & 0 deletions token_source/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Token Source Examples

These examples show the different ways to obtain the credentials
(**WebSocket URL** + **participant JWT**) the SDK needs to join a room. Each
example builds its own executable, constructs a single kind of
[`TokenSource`](https://github.com/livekit/client-sdk-cpp/blob/main/include/livekit/token_source.h),
connects to a room, logs participant join/leave for a few seconds, then
disconnects.

> Token sources are for the **initial connection only**. Once connected, the
> LiveKit server refreshes the session token internally — your token source is
> not called again unless you connect again. See the SDK's
> [authentication docs](https://github.com/livekit/client-sdk-cpp/blob/main/docs/authentication.md).

## Types

| Type | Example | When to use |
| --- | --- | --- |
| `LiteralTokenSource` | `token_source_literal.cpp` | You already have a URL + JWT (minted out of band, e.g. `lk token create`). The SDK consumes them as-is. |
| `EndpointTokenSource` | `token_source_endpoint.cpp` | Recommended for production. The SDK POSTs request options to your backend token endpoint, which returns the URL + a fresh JWT. API keys stay server-side. |
| `SandboxTokenSource` | `token_source_sandbox.cpp` | Local development only. Uses LiveKit Cloud's sandbox token server. Not for production. |
| `CustomTokenSource` | `token_source_custom.cpp` | You have an internal auth/token system. Plug in your own async callback that returns credentials. |
| `CachingTokenSource` | `token_source_caching.cpp` | A decorator that adds JWT-aware caching around any configurable source (endpoint/sandbox/custom) to cut down on fetch calls. |

`LiteralTokenSource` is *fixed* (no per-call options); the others are
*configurable* and accept
[`TokenRequestOptions`](https://github.com/livekit/client-sdk-cpp/blob/main/include/livekit/token_source.h)
(room name, participant identity, agent dispatch, ...).

## Configuring the Examples

All inputs come from environment variables, so no secrets or sandbox IDs are committed to source.

| Variable | Used by | Notes |
| --- | --- | --- |
| `LIVEKIT_URL` | literal, custom | WebSocket URL, e.g. `ws://localhost:7880`. |
| `LIVEKIT_TOKEN` | literal, custom | Participant JWT. |
| `LIVEKIT_TOKEN_ENDPOINT` | endpoint, caching | Token endpoint URL. Default `http://127.0.0.1:3000/createToken`. |
| `LIVEKIT_TOKEN_ENDPOINT_METHOD` | endpoint, caching | Optional HTTP method (default `POST`). |
| `LIVEKIT_TOKEN_ENDPOINT_HEADERS` | endpoint, caching | Optional newline-separated `Name: Value` headers. |
| `LIVEKIT_SANDBOX_ID` | sandbox | Required. Sandbox ID from LiveKit Cloud. |
| `LIVEKIT_AGENT_NAME` | sandbox | Optional agent to dispatch into the room. |
| `LIVEKIT_AGENT_METADATA` | sandbox | Optional metadata for the dispatched agent. |

These examples require LiveKit C++ SDK **v1.3.0** or newer. Build them with the
rest of the repo — see the root [README](../README.md#building-the-examples).

## Running the Examples

### Prerequisites

#### LiveKit Server

Start a development server via:

```bash
livekit-server --dev
```

#### Token Sources

For literal and custom, generate a development token with the
[LiveKit CLI](https://docs.livekit.io/home/cli/cli-setup/) (a dev server started
with `livekit-server --dev` uses `devkey` / `secret`):

```bash
export LIVEKIT_TOKEN=$(lk token create \
--api-key devkey --api-secret secret \
-i my-participant --join --room my-room \
--valid-for 24h --token-only)
```

For the endpoint and caching examples, run a local token server such as
[token-server-node](https://github.com/livekit-examples/token-server-node). This can be run via:

```bash
cd <path-to>/token-server-node
LIVEKIT_URL=ws://localhost:7880 LIVEKIT_API_KEY=devkey LIVEKIT_API_SECRET=secret PORT=3000 pnpm start
```

For sandbox, create a **Token Server** sandbox in [LiveKit Cloud](https://cloud.livekit.io)
(Sandbox → create from the token-server template), then copy the sandbox ID
(`token-server-xxxxxx`). See the
[sandbox token server docs](https://docs.livekit.io/frontends/build/authentication/sandbox-token-server/)
for setup details. Do not use this in production.

```bash
export LIVEKIT_SANDBOX_ID=token-server-xxxxxx
# optional: dispatch a registered agent into the room with metadata
# export LIVEKIT_AGENT_NAME=my-agent
# export LIVEKIT_AGENT_METADATA='{"greeting": "hello from cpp"}'
```

### Executing

The built binaries live under `build/token_source/`:

```bash
# Literal: bring your own URL + token
export LIVEKIT_URL=ws://localhost:7880
export LIVEKIT_TOKEN=<participant-jwt>
./build/token_source/token_source_literal
```

```bash
# Endpoint / caching: point at your token endpoint
export LIVEKIT_TOKEN_ENDPOINT=http://127.0.0.1:3000/createToken
./build/token_source/token_source_endpoint
./build/token_source/token_source_caching
```

```bash
# Sandbox: development-only, ID from the environment
export LIVEKIT_SANDBOX_ID=<your-sandbox-id>
export LIVEKIT_AGENT_NAME=<your-agent-name> # optional
export LIVEKIT_AGENT_METADATA=<your-agent-metadata> # optional
./build/token_source/token_source_sandbox
```

```bash
# Custom: callback returns credentials (this example reads the env)
export LIVEKIT_URL=ws://localhost:7880
export LIVEKIT_TOKEN=<participant-jwt>
./build/token_source/token_source_custom
```
Loading
Loading