diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..f9d7ca0
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,38 @@
+# Copyright 2026 LiveKit
+#
+# 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.
+
+# Rust build output (huge; rebuilt inside image)
+client-sdk-rust/target/
+
+# Git and IDE
+.git
+.gitignore
+.gitmodules
+.cursor
+.vscode
+*.swp
+*~
+
+# Build outputs and caches
+build/
+*.log
+__pycache__/
+
+# Docker
+Dockerfile
+.dockerignore
+
+# Docs and misc (optional; uncomment if you never need these in the image)
+# README.md
+# *.md
diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml
index a0a92e6..ee510c1 100644
--- a/.github/workflows/builds.yml
+++ b/.github/workflows/builds.yml
@@ -7,12 +7,14 @@ on:
- src/**
- include/**
- examples/**
+ - bridge/**
- client-sdk-rust/**
- CMakeLists.txt
- build.sh
- build.cmd
- vcpkg.json
- CMakePresets.json
+ - docker/Dockerfile
- .github/workflows/**
pull_request:
branches: ["main"]
@@ -20,12 +22,14 @@ on:
- src/**
- include/**
- examples/**
+ - bridge/**
- client-sdk-rust/**
- CMakeLists.txt
- build.sh
- build.cmd
- vcpkg.json
- CMakePresets.json
+ - docker/Dockerfile
- .github/workflows/**
workflow_dispatch:
@@ -246,3 +250,25 @@ jobs:
else
./build.sh clean-all || true
fi
+
+ docker-build:
+ name: Build (docker-linux-x64)
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout (with submodules)
+ uses: actions/checkout@v4
+ with:
+ submodules: recursive
+ fetch-depth: 0
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Build Docker image
+ run: docker build -t livekit-cpp-sdk:${{ github.sha }} . -f docker/Dockerfile
+
+ - name: Build SDK inside Docker
+ run: |
+ docker run --rm livekit-cpp-sdk:${{ github.sha }} bash -c \
+ 'cd /client-sdk-cpp && chmod +x build.sh && ./build.sh release-examples'
diff --git a/README.md b/README.md
index fcd8178..eb473f2 100644
--- a/README.md
+++ b/README.md
@@ -14,13 +14,7 @@
Use this SDK to add realtime video, audio and data features to your C++ app. By connecting to LiveKit Cloud or a self-hosted server, you can quickly build applications such as multi-modal AI, live streaming, or video calls with just a few lines of code.
-## Build & Installation Guide
-
-This page covers how to build and install the LiveKit C++ Client SDK for real-time audio/video communication.
-
----
-
-### ๐ฆ Requirements
+## ๐ฆ Requirements
- **CMake** โฅ 3.20
- **Rust / Cargo** (latest stable toolchain)
- **Git LFS** (required for examples)
@@ -31,19 +25,19 @@ This page covers how to build and install the LiveKit C++ Client SDK for real-ti
**Platform-Specific Requirements:**
-#### For Building the SDK:
+### For Building the SDK:
- **Windows:** Visual Studio 2019+, vcpkg
- **Linux:** `sudo apt install libprotobuf-dev libssl-dev` (protobuf 3.x)
- **macOS:** `brew install protobuf` (protobuf 3.x)
-#### For Using the Pre-built SDK:
+### For Using the Pre-built SDK:
- **Windows:** โ
All dependencies included (DLLs bundled) - ready to use
- **Linux:** โ ๏ธ Requires `libprotobuf` and `libssl-dev`; deploy `liblivekit_ffi.so` with your executable
- **macOS:** โ ๏ธ Requires `protobuf`; deploy `liblivekit_ffi.dylib` with your executable
> **Note**: If the SDK was built with Protobuf 6.0+, you also need `libabsl-dev` (Linux) or `abseil` (macOS).
-### ๐งฉ Clone the Repository
+## ๐งฉ Clone the Repository
Make sure to initialize the Rust submodule (`client-sdk-rust`):
@@ -57,9 +51,9 @@ cd client-sdk-cpp
git submodule update --init --recursive
```
-### โ๏ธ BUILD
+## โ๏ธ BUILD
-#### Quick Build (Using Build Scripts)
+### Quick Build (Using Build Scripts)
**Linux/macOS:**
```bash
@@ -71,6 +65,17 @@ git submodule update --init --recursive
./build.sh release-tests # Build Release with tests
```
**Windows**
+Using build scripts:
+```powershell
+.\build.cmd clean # Clean CMake build artifacts
+.\build.cmd clean-all # Deep clean (C++ + Rust + generated files)
+.\build.cmd debug # Build Debug version
+.\build.cmd release # Build Release version
+.\build.cmd debug-tests # Build Debug with tests
+.\build.cmd release-tests # Build Release with tests
+```
+
+### Windows build using cmake/vcpkg
```bash
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE="$PWD/vcpkg/scripts/buildsystems/vcpkg.cmake" # Generate Makefiles in build folder
# Build (Release or Debug)
@@ -86,17 +91,7 @@ You must install protobuf via vcpkg (so CMake can find ProtobufConfig.cmake and
.\vcpkg\vcpkg install protobuf:x64-windows
```
-**Windows:**
-```powershell
-.\build.cmd clean # Clean CMake build artifacts
-.\build.cmd clean-all # Deep clean (C++ + Rust + generated files)
-.\build.cmd debug # Build Debug version
-.\build.cmd release # Build Release version
-.\build.cmd debug-tests # Build Debug with tests
-.\build.cmd release-tests # Build Release with tests
-```
-
-#### Advanced Build (Using CMake Presets)
+### Advanced Build (Using CMake Presets)
For more control and platform-specific builds, see the detailed instructions in [README_BUILD.md](README_BUILD.md).
@@ -128,7 +123,24 @@ cmake --build --preset macos-release
๐ **For complete build instructions, troubleshooting, and platform-specific notes, see [README_BUILD.md](README_BUILD.md)**
-### ๐งช Run Example
+### Building with Docker
+The Dockerfile COPYs folders/files required to build the CPP SDK into the image.
+ **NOTE:** this has only been tested on Linux
+```bash
+docker build -t livekit-cpp-sdk . -f docker/Dockerfile
+docker run -it --network host livekit-cpp-sdk:latest bash
+```
+
+__NOTE:__ if you are building your own Dockerfile, you will likely need to set the same `ENV` variables as in `docker/Dockerfile`, but to the relevant directories:
+```bash
+export CC=$HOME/gcc-14/bin/gcc
+export CXX=$HOME/gcc-14/bin/g++
+export LD_LIBRARY_PATH=$HOME/gcc-14/lib64:$LD_LIBRARY_PATH
+export PATH=$HOME/.cargo/bin:$PATH
+export PATH=$HOME/cmake-3.31/bin:$PATH
+```
+
+## ๐งช Run Example
### Generate Tokens
Before running any participant, create JWT tokens with the proper identity and room name, example
@@ -136,7 +148,7 @@ Before running any participant, create JWT tokens with the proper identity and r
lk token create -r test -i your_own_identity --join --valid-for 99999h --dev --room=your_own_room
```
-#### SimpleRoom
+### SimpleRoom
```bash
./build/examples/SimpleRoom --url $URL --token
@@ -164,7 +176,7 @@ If the E2EE keys do not match between participants:
Press Ctrl-C to exit the example.
-#### SimpleRpc
+### SimpleRpc
The SimpleRpc example demonstrates how to:
- Connect multiple participants to the same LiveKit room
- Register RPC handlers (e.g., arrival, square-root, divide, long-calculation)
@@ -172,7 +184,7 @@ The SimpleRpc example demonstrates how to:
- Handle success, application errors, unsupported methods, and timeouts
- Observe round-trip times (RTT) for each RPC call
-##### ๐ Generate Tokens
+#### ๐ Generate Tokens
Before running any participant, create JWT tokens with **caller**, **greeter** and **math-genius** identities and room name.
```bash
lk token create -r test -i caller --join --valid-for 99999h --dev --room=your_own_room
@@ -180,7 +192,7 @@ lk token create -r test -i greeter --join --valid-for 99999h --dev --room=your_o
lk token create -r test -i math-genius --join --valid-for 99999h --dev --room=your_own_room
```
-##### โถ Start Participants
+#### โถ Start Participants
Every participant is run as a separate terminal process, note --role needs to match the token identity.
```bash
./build/examples/SimpleRpc --url $URL --token --role=math-genius
@@ -191,7 +203,7 @@ The caller will automatically:
- Print round-trip times
- Annotate expected successes or expected failures
-#### SimpleDataStream
+### SimpleDataStream
- The SimpleDataStream example demonstrates how to:
- Connect multiple participants to the same LiveKit room
- Register text stream and byte stream handlers by topic (e.g. "chat", "files")
@@ -201,14 +213,14 @@ The caller will automatically:
- Measure and print one-way latency on the receiver using sender timestamps
- Receive streamed chunks and reconstruct the full payload on the receiver
-##### ๐ Generate Tokens
+#### ๐ Generate Tokens
Before running any participant, create JWT tokens with caller and greeter identities and your room name.
```bash
lk token create -r test -i caller --join --valid-for 99999h --dev --room=your_own_room
lk token create -r test -i greeter --join --valid-for 99999h --dev --room=your_own_room
```
-##### โถ Start Participants
+#### โถ Start Participants
Start the receiver first (so it registers stream handlers before messages arrive):
```bash
./build/examples/SimpleDataStream --url $URL --token
@@ -312,7 +324,7 @@ and a **ROS2 bridge** that maps `LogLevel` to `RCLCPP_*` macros.
---
-### ๐งช Integration & Stress Tests
+## ๐งช Integration & Stress Tests
The SDK includes integration and stress tests using Google Test (gtest).
@@ -330,7 +342,7 @@ The SDK includes integration and stress tests using Google Test (gtest).
.\build.cmd release-tests
```
-#### Run Tests
+### Run Tests
After building, run tests using ctest or directly:
@@ -348,7 +360,7 @@ ctest --output-on-failure
./build-debug/bin/livekit_stress_tests --gtest_filter="*MaxPayloadStress*"
```
-#### Test Types
+### Test Types
| Executable | Description |
|------------|-------------|
@@ -376,7 +388,7 @@ lk token create -r test -i rpc-caller --join --valid-for 99999h --dev --room=rpc
lk token create -r test -i rpc-receiver --join --valid-for 99999h --dev --room=rpc-test-room
```
-#### Test Coverage
+### Test Coverage
- **SDK Initialization**: Initialize/shutdown lifecycle
- **Room**: Room creation, options, connection
@@ -384,21 +396,21 @@ lk token create -r test -i rpc-receiver --join --valid-for 99999h --dev --room=r
- **RPC**: Round-trip calls, max payload (15KB), timeouts, errors, concurrent calls
- **Stress Tests**: High throughput, bidirectional RPC, memory pressure
-### ๐งฐ Recommended Setup
-#### macOS
+## ๐งฐ Recommended Setup
+### macOS
```bash
brew install cmake protobuf rust
```
-#### Ubuntu / Debian
+### Ubuntu / Debian
```bash
sudo apt update
sudo apt install -y cmake protobuf-compiler build-essential
curl https://sh.rustup.rs -sSf | sh
```
-### ๐ ๏ธ Development Tips
-#### Update Rust version
+## ๐ ๏ธ Development Tips
+### Update Rust version
```bash
cd client-sdk-cpp
git fetch origin
@@ -417,19 +429,19 @@ git -C client-sdk-rust/yuv-sys submodule update --init --recursive --checkout
git submodule status --recursive
```
-#### If yuv-sys fails to build
+### If yuv-sys fails to build
```bash
cargo clean -p yuv-sys
cargo build -p yuv-sys -vv
```
-#### Full clean (Rust + C++ build folders)
+### Full clean (Rust + C++ build folders)
In some cases, you may need to perform a full clean that deletes all build artifacts from both the Rust and C++ folders:
```bash
./build.sh clean-all
```
-#### Clang format
+### Clang format
CPP SDK is using clang C++ format
```bash
brew install clang-format
diff --git a/docker/Dockerfile b/docker/Dockerfile
new file mode 100644
index 0000000..647f46f
--- /dev/null
+++ b/docker/Dockerfile
@@ -0,0 +1,123 @@
+# Copyright 2026 LiveKit
+#
+# 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.
+#
+# Build with:
+# docker build -t livekit-cpp-sdk . -f docker/Dockerfile
+# From repo root.
+# Run with:
+# docker run -it --network host livekit-cpp-sdk:latest bash
+
+FROM ubuntu:22.04
+
+ENV DEBIAN_FRONTEND=noninteractive
+ENV HOME=/root
+
+# Install make, pkg-config, and base build deps (pkg-config + libglib2.0-dev for Rust glib-sys, libasound2-dev for alsa-sys)
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ ca-certificates \
+ curl \
+ git \
+ libasound2-dev \
+ libclang-dev \
+ libdrm-dev \
+ libglib2.0-dev \
+ libssl-dev \
+ libunwind-dev \
+ libusb-1.0-0-dev \
+ libva-dev \
+ make \
+ ninja-build \
+ pkg-config \
+ wget \
+ xz-utils \
+ && rm -rf /var/lib/apt/lists/*
+
+# Install GCC 14 first (slow; keep early for better layer caching)
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ build-essential \
+ flex \
+ libgmp-dev \
+ libmpc-dev \
+ libmpfr-dev \
+ && rm -rf /var/lib/apt/lists/*
+
+RUN cd $HOME \
+ && wget https://ftp.gnu.org/gnu/gcc/gcc-14.2.0/gcc-14.2.0.tar.xz \
+ && tar xf gcc-14.2.0.tar.xz \
+ && cd gcc-14.2.0 \
+ && ./configure --prefix=$HOME/gcc-14 --enable-languages=c,c++ --disable-multilib --disable-bootstrap \
+ && make -j$(nproc) \
+ && make install \
+ && cd $HOME \
+ && rm -rf gcc-14.2.0 gcc-14.2.0.tar.xz
+
+RUN mkdir -p /home/installs && cp -a $HOME/gcc-14/bin/* /home/installs/
+
+ENV CC=$HOME/gcc-14/bin/gcc
+ENV CXX=$HOME/gcc-14/bin/g++
+ENV LD_LIBRARY_PATH=$HOME/gcc-14/lib64
+
+# Install CMake 3.31.5 for current architecture (prefix dir must exist before installer runs)
+# TARGETARCH is set by Docker BuildKit when building (amd64 -> x86_64, arm64 -> aarch64)
+ARG TARGETARCH
+RUN mkdir -p $HOME/cmake-3.31 \
+ && CMAKE_ARCH=$(case "$TARGETARCH" in amd64) echo x86_64 ;; arm64) echo aarch64 ;; *) echo "$TARGETARCH" ;; esac) \
+ && wget -q "https://github.com/Kitware/CMake/releases/download/v3.31.5/cmake-3.31.5-linux-${CMAKE_ARCH}.sh" \
+ -O cmake-installer.sh \
+ && chmod +x cmake-installer.sh \
+ && ./cmake-installer.sh --skip-license --prefix=$HOME/cmake-3.31 \
+ && rm cmake-installer.sh
+
+ENV PATH=$HOME/cmake-3.31/bin:$PATH
+
+# Install Rust (non-interactive)
+RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \
+ && . $HOME/.cargo/env && rustup default stable
+
+ENV PATH=$HOME/.cargo/bin:$PATH
+
+# Deps for SDL (X11 + OpenGL/GLX for FindOpenGL)
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ libgl1-mesa-dev \
+ libx11-dev \
+ libxcursor-dev \
+ libxext-dev \
+ libxfixes-dev \
+ libxi-dev \
+ libxrandr-dev \
+ && rm -rf /var/lib/apt/lists/*
+
+# Copy project source (build context = repo root)
+WORKDIR /client-sdk-cpp
+RUN mkdir -p /client-sdk-cpp
+COPY src /client-sdk-cpp/src
+COPY include /client-sdk-cpp/include
+COPY bridge /client-sdk-cpp/bridge
+COPY build.sh /client-sdk-cpp/build.sh
+COPY CMakePresets.json /client-sdk-cpp/CMakePresets.json
+COPY build.cmd /client-sdk-cpp/build.cmd
+COPY client-sdk-rust /client-sdk-cpp/client-sdk-rust
+COPY data /client-sdk-cpp/data
+COPY examples /client-sdk-cpp/examples
+COPY cmake /client-sdk-cpp/cmake
+COPY CMakeLists.txt /client-sdk-cpp/CMakeLists.txt
+COPY build.h.in /client-sdk-cpp/build.h.in
+COPY build.sh /client-sdk-cpp/build.sh
+COPY build.cmd /client-sdk-cpp/build.cmd
+
+# Configure Rust linker: use full GCC path so liblto_plugin.so is found (not /home/installs/ which has no plugin)
+RUN mkdir -p /client-sdk-cpp/client-sdk-rust/.cargo \
+ && printf '%s\n' '[target.x86_64-unknown-linux-gnu]' 'linker = "/root/gcc-14/bin/g++"' \
+ '[target.aarch64-unknown-linux-gnu]' 'linker = "/root/gcc-14/bin/g++"' > /client-sdk-cpp/client-sdk-rust/.cargo/config.toml
+