diff --git a/.token_helpers/gen_and_set.bash b/.token_helpers/gen_and_set.bash
index b933a24f..0e855e90 100755
--- a/.token_helpers/gen_and_set.bash
+++ b/.token_helpers/gen_and_set.bash
@@ -16,8 +16,8 @@
# Generate a LiveKit access token via `lk` and set LIVEKIT_TOKEN (and LIVEKIT_URL)
# for your current shell session.
#
-# source examples/tokens/gen_and_set.bash --id PARTICIPANT_ID --room ROOM_NAME [--view-token]
-# eval "$(bash examples/tokens/gen_and_set.bash --id ID --room ROOM [--view-token])"
+# source .token_helpers/gen_and_set.bash --id PARTICIPANT_ID --room ROOM_NAME [--view-token]
+# eval "$(bash .token_helpers/gen_and_set.bash --id ID --room ROOM [--view-token])"
#
# Optional env: LIVEKIT_API_KEY, LIVEKIT_API_SECRET, LIVEKIT_VALID_FOR.
diff --git a/.token_helpers/set_data_track_test_tokens.bash b/.token_helpers/set_data_track_test_tokens.bash
index b9bf99b8..d3520e4f 100755
--- a/.token_helpers/set_data_track_test_tokens.bash
+++ b/.token_helpers/set_data_track_test_tokens.bash
@@ -16,8 +16,8 @@
# Generate two LiveKit access tokens via `lk` and set the environment variables
# required by src/tests/integration/test_data_track.cpp.
#
-# source examples/tokens/set_data_track_test_tokens.bash
-# eval "$(bash examples/tokens/set_data_track_test_tokens.bash)"
+# source .token_helpers/set_data_track_test_tokens.bash
+# eval "$(bash .token_helpers/set_data_track_test_tokens.bash)"
#
# Exports:
# LK_TOKEN_TEST_A
diff --git a/README.md b/README.md
index e9228565..25558314 100644
--- a/README.md
+++ b/README.md
@@ -559,6 +559,10 @@ lk token create \
--grant '{"canPublish":true,"canSubscribe":true,"canPublishData":true}'
```
+# Deprecation
+- livekit_bridge (bridge/ folder) is deprecated. Avoid using it. Migrate to the base SDK. This will be removed on 06/01/2026.
+- setOn*FrameCallback with TrackSource is deprecated. Use track name instead. This will be removed on 06/01/2026.
+
| LiveKit Ecosystem |
diff --git a/bridge/README.md b/bridge/README.md
index a2c2acf8..44de95d1 100644
--- a/bridge/README.md
+++ b/bridge/README.md
@@ -38,12 +38,12 @@ mic->pushFrame(pcm_data, samples_per_channel);
cam->pushFrame(rgba_data, timestamp_us);
// 4. Receive frames from a remote participant
-bridge.setOnAudioFrameCallback("remote-peer", livekit::TrackSource::SOURCE_MICROPHONE,
+bridge.setOnAudioFrameCallback("remote-peer", "mic",
[](const livekit::AudioFrame& frame) {
// Called on a background reader thread
});
-bridge.setOnVideoFrameCallback("remote-peer", livekit::TrackSource::SOURCE_CAMERA,
+bridge.setOnVideoFrameCallback("remote-peer", "cam",
[](const livekit::VideoFrame& frame, int64_t timestamp_us) {
// Called on a background reader thread
});
@@ -117,9 +117,9 @@ Reader threads are managed by `Room` internally. They are created when a matchin
### Callback Registration Timing
-Callbacks are keyed by `(participant_identity, track_source)`. You can register them **after connecting** but before the remote participant has joined the room. `Room` stores the callback and automatically wires it up when the matching track is subscribed.
+Callbacks are keyed by `(participant_identity, track_name)`. You can register them **after connecting** but before the remote participant has joined the room. `Room` stores the callback and automatically wires it up when the matching track is subscribed.
-> **Note:** Only one callback may be set per `(participant_identity, track_source)` pair. Calling `setOnAudioFrameCallback` or `setOnVideoFrameCallback` again with the same identity and source will silently replace the previous callback. If you need to fan-out a single stream to multiple consumers, do so inside your callback.
+> **Note:** Only one callback may be set per `(participant_identity, track_name)` pair. Calling `setOnAudioFrameCallback` or `setOnVideoFrameCallback` again with the same identity and track name will silently replace the previous callback. If you need to fan-out a single stream to multiple consumers, do so inside your callback.
This means the typical pattern is:
@@ -128,7 +128,7 @@ This means the typical pattern is:
livekit::RoomOptions options;
options.auto_subscribe = true;
bridge.connect(url, token, options);
-bridge.setOnAudioFrameCallback("robot-1", livekit::TrackSource::SOURCE_MICROPHONE, my_callback);
+bridge.setOnAudioFrameCallback("robot-1", "mic", my_callback);
// When robot-1 joins and publishes a mic track, my_callback starts firing.
```
@@ -149,10 +149,10 @@ bridge.setOnAudioFrameCallback("robot-1", livekit::TrackSource::SOURCE_MICROPHON
| `isConnected()` | Returns whether the bridge is currently connected. |
| `createAudioTrack(name, sample_rate, num_channels, source)` | Create and publish a local audio track with the given `TrackSource` (e.g. `SOURCE_MICROPHONE`, `SOURCE_SCREENSHARE_AUDIO`). Returns an RAII `shared_ptr`. |
| `createVideoTrack(name, width, height, source)` | Create and publish a local video track with the given `TrackSource` (e.g. `SOURCE_CAMERA`, `SOURCE_SCREENSHARE`). Returns an RAII `shared_ptr`. |
-| `setOnAudioFrameCallback(identity, source, callback)` | Register a callback for audio frames from a specific remote participant + track source. |
-| `setOnVideoFrameCallback(identity, source, callback)` | Register a callback for video frames from a specific remote participant + track source. |
-| `clearOnAudioFrameCallback(identity, source)` | Clear the audio callback for a specific remote participant + track source. Stops and joins the reader thread if active. |
-| `clearOnVideoFrameCallback(identity, source)` | Clear the video callback for a specific remote participant + track source. Stops and joins the reader thread if active. |
+| `setOnAudioFrameCallback(identity, track_name, callback)` | Register a callback for audio frames from a specific remote participant + track name. |
+| `setOnVideoFrameCallback(identity, track_name, callback)` | Register a callback for video frames from a specific remote participant + track name. |
+| `clearOnAudioFrameCallback(identity, track_name)` | Clear the audio callback for a specific remote participant + track name. Stops and joins the reader thread if active. |
+| `clearOnVideoFrameCallback(identity, track_name)` | Clear the video callback for a specific remote participant + track name. Stops and joins the reader thread if active. |
| `performRpc(destination_identity, method, payload, response_timeout?)` | Blocking RPC call to a remote participant. Returns the response payload. Throws `livekit::RpcError` on failure. |
| `registerRpcMethod(method_name, handler)` | Register a handler for incoming RPC invocations. The handler returns an optional response payload or throws `livekit::RpcError`. |
| `unregisterRpcMethod(method_name)` | Unregister a previously registered RPC handler. |
@@ -263,6 +263,6 @@ The bridge is designed for simplicity and currently only supports limited audio
- Simulcast tuning
- Video format selection (RGBA is the default; no format option yet)
- Custom `RoomOptions` or `TrackPublishOptions`
-- **One callback per (participant, source):** Only a single callback can be registered for each `(participant_identity, track_source)` pair. Re-registering with the same key silently replaces the previous callback. To fan-out a stream to multiple consumers, dispatch from within your single callback.
+- **One callback per (participant, track_name):** Only a single callback can be registered for each `(participant_identity, track_name)` pair. Re-registering with the same key silently replaces the previous callback. To fan-out a stream to multiple consumers, dispatch from within your single callback.
For advanced use cases, use the full `client-sdk-cpp` API directly, or expand the bridge to support your use case.
diff --git a/bridge/include/livekit_bridge/livekit_bridge.h b/bridge/include/livekit_bridge/livekit_bridge.h
index 1f2d44a6..c2275dd9 100644
--- a/bridge/include/livekit_bridge/livekit_bridge.h
+++ b/bridge/include/livekit_bridge/livekit_bridge.h
@@ -37,7 +37,6 @@ namespace livekit {
class Room;
class AudioFrame;
class VideoFrame;
-enum class TrackSource;
} // namespace livekit
namespace livekit_bridge {
@@ -88,12 +87,10 @@ using VideoFrameCallback = livekit::VideoFrameCallback;
* mic->pushFrame(pcm_data, samples_per_channel);
* cam->pushFrame(rgba_data, timestamp_us);
*
- * bridge.setOnAudioFrameCallback("remote-participant",
- * livekit::TrackSource::SOURCE_MICROPHONE,
+ * bridge.setOnAudioFrameCallback("remote-participant", "mic",
* [](const livekit::AudioFrame& f) { process(f); });
*
- * bridge.setOnVideoFrameCallback("remote-participant",
- * livekit::TrackSource::SOURCE_CAMERA,
+ * bridge.setOnVideoFrameCallback("remote-participant", "cam",
* [](const livekit::VideoFrame& f, int64_t ts) { render(f); });
*
* // Unpublish a single track mid-session:
@@ -207,59 +204,59 @@ class LiveKitBridge {
/**
* Set the callback for audio frames from a specific remote participant
- * and track source.
+ * and track name.
*
* Delegates to Room::setOnAudioFrameCallback. The callback fires on a
* dedicated reader thread owned by Room whenever a new audio frame is
* received.
*
- * @note Only **one** callback may be registered per (participant, source)
- * pair. Calling this again with the same identity and source will
+ * @note Only **one** callback may be registered per (participant, track_name)
+ * pair. Calling this again with the same identity and track_name will
* silently replace the previous callback.
*
* @param participant_identity Identity of the remote participant.
- * @param source Track source (e.g. SOURCE_MICROPHONE).
+ * @param track_name Name of the remote track.
* @param callback Function to invoke per audio frame.
*/
void setOnAudioFrameCallback(const std::string &participant_identity,
- livekit::TrackSource source,
+ const std::string &track_name,
AudioFrameCallback callback);
/**
* Register a callback for video frames from a specific remote participant
- * and track source.
+ * and track name.
*
* Delegates to Room::setOnVideoFrameCallback.
*
- * @note Only **one** callback may be registered per (participant, source)
- * pair. Calling this again with the same identity and source will
+ * @note Only **one** callback may be registered per (participant, track_name)
+ * pair. Calling this again with the same identity and track_name will
* silently replace the previous callback.
*
* @param participant_identity Identity of the remote participant.
- * @param source Track source (e.g. SOURCE_CAMERA).
+ * @param track_name Name of the remote track.
* @param callback Function to invoke per video frame.
*/
void setOnVideoFrameCallback(const std::string &participant_identity,
- livekit::TrackSource source,
+ const std::string &track_name,
VideoFrameCallback callback);
/**
* Clear the audio frame callback for a specific remote participant + track
- * source.
+ * name.
*
* Delegates to Room::clearOnAudioFrameCallback.
*/
void clearOnAudioFrameCallback(const std::string &participant_identity,
- livekit::TrackSource source);
+ const std::string &track_name);
/**
* Clear the video frame callback for a specific remote participant + track
- * source.
+ * name.
*
* Delegates to Room::clearOnVideoFrameCallback.
*/
void clearOnVideoFrameCallback(const std::string &participant_identity,
- livekit::TrackSource source);
+ const std::string &track_name);
// ---------------------------------------------------------------
// RPC (Remote Procedure Call)
diff --git a/bridge/src/livekit_bridge.cpp b/bridge/src/livekit_bridge.cpp
index b15587ec..8cf661c9 100644
--- a/bridge/src/livekit_bridge.cpp
+++ b/bridge/src/livekit_bridge.cpp
@@ -238,7 +238,7 @@ LiveKitBridge::createVideoTrack(const std::string &name, int width, int height,
// ---------------------------------------------------------------
void LiveKitBridge::setOnAudioFrameCallback(
- const std::string &participant_identity, livekit::TrackSource source,
+ const std::string &participant_identity, const std::string &track_name,
AudioFrameCallback callback) {
std::lock_guard lock(mutex_);
if (!room_) {
@@ -246,12 +246,12 @@ void LiveKitBridge::setOnAudioFrameCallback(
"ignored\n";
return;
}
- room_->setOnAudioFrameCallback(participant_identity, source,
+ room_->setOnAudioFrameCallback(participant_identity, track_name,
std::move(callback));
}
void LiveKitBridge::setOnVideoFrameCallback(
- const std::string &participant_identity, livekit::TrackSource source,
+ const std::string &participant_identity, const std::string &track_name,
VideoFrameCallback callback) {
std::lock_guard lock(mutex_);
if (!room_) {
@@ -259,26 +259,26 @@ void LiveKitBridge::setOnVideoFrameCallback(
"ignored\n";
return;
}
- room_->setOnVideoFrameCallback(participant_identity, source,
+ room_->setOnVideoFrameCallback(participant_identity, track_name,
std::move(callback));
}
void LiveKitBridge::clearOnAudioFrameCallback(
- const std::string &participant_identity, livekit::TrackSource source) {
+ const std::string &participant_identity, const std::string &track_name) {
std::lock_guard lock(mutex_);
if (!room_) {
return;
}
- room_->clearOnAudioFrameCallback(participant_identity, source);
+ room_->clearOnAudioFrameCallback(participant_identity, track_name);
}
void LiveKitBridge::clearOnVideoFrameCallback(
- const std::string &participant_identity, livekit::TrackSource source) {
+ const std::string &participant_identity, const std::string &track_name) {
std::lock_guard lock(mutex_);
if (!room_) {
return;
}
- room_->clearOnVideoFrameCallback(participant_identity, source);
+ room_->clearOnVideoFrameCallback(participant_identity, track_name);
}
// ---------------------------------------------------------------
diff --git a/bridge/tests/test_livekit_bridge.cpp b/bridge/tests/test_livekit_bridge.cpp
index 43c8f6fb..e75690bc 100644
--- a/bridge/tests/test_livekit_bridge.cpp
+++ b/bridge/tests/test_livekit_bridge.cpp
@@ -101,12 +101,10 @@ TEST_F(LiveKitBridgeTest, SetAndClearAudioCallbackBeforeConnectDoesNotCrash) {
LiveKitBridge bridge;
EXPECT_NO_THROW({
- bridge.setOnAudioFrameCallback("remote-participant",
- livekit::TrackSource::SOURCE_MICROPHONE,
+ bridge.setOnAudioFrameCallback("remote-participant", "mic",
[](const livekit::AudioFrame &) {});
- bridge.clearOnAudioFrameCallback("remote-participant",
- livekit::TrackSource::SOURCE_MICROPHONE);
+ bridge.clearOnAudioFrameCallback("remote-participant", "mic");
}) << "set/clear audio callback before connect should be safe (warns)";
}
@@ -115,11 +113,10 @@ TEST_F(LiveKitBridgeTest, SetAndClearVideoCallbackBeforeConnectDoesNotCrash) {
EXPECT_NO_THROW({
bridge.setOnVideoFrameCallback(
- "remote-participant", livekit::TrackSource::SOURCE_CAMERA,
+ "remote-participant", "cam",
[](const livekit::VideoFrame &, std::int64_t) {});
- bridge.clearOnVideoFrameCallback("remote-participant",
- livekit::TrackSource::SOURCE_CAMERA);
+ bridge.clearOnVideoFrameCallback("remote-participant", "cam");
}) << "set/clear video callback before connect should be safe (warns)";
}
@@ -127,10 +124,8 @@ TEST_F(LiveKitBridgeTest, ClearNonExistentCallbackIsNoOp) {
LiveKitBridge bridge;
EXPECT_NO_THROW({
- bridge.clearOnAudioFrameCallback("nonexistent",
- livekit::TrackSource::SOURCE_MICROPHONE);
- bridge.clearOnVideoFrameCallback("nonexistent",
- livekit::TrackSource::SOURCE_CAMERA);
+ bridge.clearOnAudioFrameCallback("nonexistent", "mic");
+ bridge.clearOnVideoFrameCallback("nonexistent", "cam");
}) << "Clearing a callback that was never registered should be a no-op";
}
diff --git a/include/livekit/room.h b/include/livekit/room.h
index e65d7d1f..841ec121 100644
--- a/include/livekit/room.h
+++ b/include/livekit/room.h
@@ -240,13 +240,6 @@ class Room {
// Frame callbacks
// ---------------------------------------------------------------
- /**
- * @brief Sets the audio frame callback via SubscriptionThreadDispatcher.
- */
- void setOnAudioFrameCallback(const std::string &participant_identity,
- TrackSource source, AudioFrameCallback callback,
- const AudioStream::Options &opts = {});
-
/**
* @brief Sets the audio frame callback via SubscriptionThreadDispatcher.
*/
@@ -255,13 +248,6 @@ class Room {
AudioFrameCallback callback,
const AudioStream::Options &opts = {});
- /**
- * @brief Sets the video frame callback via SubscriptionThreadDispatcher.
- */
- void setOnVideoFrameCallback(const std::string &participant_identity,
- TrackSource source, VideoFrameCallback callback,
- const VideoStream::Options &opts = {});
-
/**
* @brief Sets the video frame callback via SubscriptionThreadDispatcher.
*/
@@ -279,23 +265,12 @@ class Room {
VideoFrameEventCallback callback,
const VideoStream::Options &opts = {});
- /**
- * @brief Clears the audio frame callback via SubscriptionThreadDispatcher.
- */
- void clearOnAudioFrameCallback(const std::string &participant_identity,
- TrackSource source);
/**
* @brief Clears the audio frame callback via SubscriptionThreadDispatcher.
*/
void clearOnAudioFrameCallback(const std::string &participant_identity,
const std::string &track_name);
- /**
- * @brief Clears the video frame callback via SubscriptionThreadDispatcher.
- */
- void clearOnVideoFrameCallback(const std::string &participant_identity,
- TrackSource source);
-
/**
* @brief Clears the video frame callback via SubscriptionThreadDispatcher.
*/
diff --git a/include/livekit/subscription_thread_dispatcher.h b/include/livekit/subscription_thread_dispatcher.h
index c647c565..d6d61d33 100644
--- a/include/livekit/subscription_thread_dispatcher.h
+++ b/include/livekit/subscription_thread_dispatcher.h
@@ -71,7 +71,7 @@ using DataFrameCallbackId = std::uint64_t;
* registration requests here, and then calls \ref handleTrackSubscribed and
* \ref handleTrackUnsubscribed as room events arrive.
*
- * For each registered `(participant identity, TrackSource)` pair, this class
+ * For each registered `(participant identity, track name)` pair, this class
* may create a dedicated \ref AudioStream or \ref VideoStream and a matching
* reader thread. That thread blocks on stream reads and invokes the
* registered callback with decoded frames.
@@ -93,23 +93,6 @@ class SubscriptionThreadDispatcher {
/// Stops all active readers and clears all registered callbacks.
~SubscriptionThreadDispatcher();
- /**
- * Register or replace an audio frame callback for a remote subscription.
- *
- * The callback is keyed by remote participant identity plus \p source.
- * If the matching remote audio track is already subscribed, \ref Room may
- * immediately call \ref handleTrackSubscribed to start a reader.
- *
- * @param participant_identity Identity of the remote participant.
- * @param source Track source to match.
- * @param callback Function invoked for each decoded audio frame.
- * @param opts Options used when creating the backing
- * \ref AudioStream.
- */
- void setOnAudioFrameCallback(const std::string &participant_identity,
- TrackSource source, AudioFrameCallback callback,
- const AudioStream::Options &opts = {});
-
/**
* Register or replace an audio frame callback for a remote subscription.
*
@@ -128,23 +111,6 @@ class SubscriptionThreadDispatcher {
AudioFrameCallback callback,
const AudioStream::Options &opts = {});
- /**
- * Register or replace a video frame callback for a remote subscription.
- *
- * The callback is keyed by remote participant identity plus \p source.
- * If the matching remote video track is already subscribed, \ref Room may
- * immediately call \ref handleTrackSubscribed to start a reader.
- *
- * @param participant_identity Identity of the remote participant.
- * @param source Track source to match.
- * @param callback Function invoked for each decoded video frame.
- * @param opts Options used when creating the backing
- * \ref VideoStream.
- */
- void setOnVideoFrameCallback(const std::string &participant_identity,
- TrackSource source, VideoFrameCallback callback,
- const VideoStream::Options &opts = {});
-
/**
* Register or replace a video frame callback for a remote subscription.
*
@@ -183,18 +149,6 @@ class SubscriptionThreadDispatcher {
VideoFrameEventCallback callback,
const VideoStream::Options &opts = {});
- /**
- * Remove an audio callback registration and stop any active reader.
- *
- * If an audio reader thread is active for the given key, its stream is
- * closed and the thread is joined before this call returns.
- *
- * @param participant_identity Identity of the remote participant.
- * @param source Track source to clear.
- */
- void clearOnAudioFrameCallback(const std::string &participant_identity,
- TrackSource source);
-
/**
* Remove an audio callback registration and stop any active reader.
*
@@ -207,18 +161,6 @@ class SubscriptionThreadDispatcher {
void clearOnAudioFrameCallback(const std::string &participant_identity,
const std::string &track_name);
- /**
- * Remove a video callback registration and stop any active reader.
- *
- * If a video reader thread is active for the given key, its stream is
- * closed and the thread is joined before this call returns.
- *
- * @param participant_identity Identity of the remote participant.
- * @param source Track source to clear.
- */
- void clearOnVideoFrameCallback(const std::string &participant_identity,
- TrackSource source);
-
/**
* Remove a video callback registration and stop any active reader.
*
@@ -237,32 +179,30 @@ class SubscriptionThreadDispatcher {
* \ref Room calls this after it has processed a track-subscription event and
* updated its publication state. If a matching callback registration exists,
* the dispatcher creates the appropriate stream type and launches a reader
- * thread for the `(participant, source)` key.
+ * thread for the `(participant, track_name)` key.
*
* If no matching callback is registered, this is a no-op.
*
* @param participant_identity Identity of the remote participant.
- * @param source Track source associated with the subscription.
+ * @param track_name Track name associated with the subscription.
* @param track Subscribed remote track to read from.
*/
void handleTrackSubscribed(const std::string &participant_identity,
- TrackSource source, const std::string &track_name,
+ const std::string &track_name,
const std::shared_ptr