Skip to content

Commit 8e94036

Browse files
platform_audio
1 parent bbf0fdf commit 8e94036

8 files changed

Lines changed: 386 additions & 1 deletion

File tree

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ add_subdirectory(logging_levels/basic_usage logging_levels_basic_usage)
8989
add_subdirectory(logging_levels/custom_sinks logging_levels_custom_sinks)
9090
add_subdirectory(hello_livekit/sender hello_livekit_sender)
9191
add_subdirectory(hello_livekit/receiver hello_livekit_receiver)
92+
add_subdirectory(platform_audio)
9293
add_subdirectory(ping_pong/ping ping_pong_ping)
9394
add_subdirectory(ping_pong/pong ping_pong_pong)
9495
add_subdirectory(user_timestamped_video)

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,21 @@ For example:
7373
./build/basic_room/basic_room --url <ws-url> --token <token>
7474
```
7575

76+
### PlatformAudio
77+
78+
The `platform_audio` examples show microphone capture and speaker playout using
79+
WebRTC's platform Audio Device Module:
80+
81+
```bash
82+
./build/platform_audio/player/PlatformAudioPlayer <ws-url> <player-token>
83+
./build/platform_audio/sender/PlatformAudioSender <ws-url> <sender-token>
84+
```
85+
7686
### Supported platforms
7787

7888
Prebuilt SDKs are downloaded automatically for:
7989
* Windows: x64
8090
* macOS: x64, arm64 (Apple Silicon)
8191
* Linux: x64
8292

83-
If no matching SDK is available for your platform, CMake configuration will fail with a clear error.
93+
If no matching SDK is available for your platform, CMake configuration will fail with a clear error.

platform_audio/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright 2026 LiveKit, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
add_subdirectory(sender)
16+
add_subdirectory(player)

platform_audio/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# PlatformAudio
2+
3+
These examples demonstrate the platform Audio Device Module path:
4+
5+
- `PlatformAudioSender` publishes microphone audio with echo cancellation, noise suppression, and auto gain control.
6+
- `PlatformAudioPlayer` joins the same room and plays subscribed remote audio through the platform output device.
7+
8+
Build the collection, then run the player and sender with different participant tokens for the same room:
9+
10+
```bash
11+
./build/platform_audio/player/PlatformAudioPlayer <ws-url> <player-token>
12+
./build/platform_audio/sender/PlatformAudioSender <ws-url> <sender-token>
13+
```
14+
15+
Environment fallbacks:
16+
17+
```bash
18+
export LIVEKIT_URL=wss://your-livekit-host
19+
export LIVEKIT_PLAYER_TOKEN=<player-token>
20+
export LIVEKIT_SENDER_TOKEN=<sender-token>
21+
```
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Copyright 2026 LiveKit, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
add_executable(PlatformAudioPlayer
16+
main.cpp
17+
)
18+
19+
target_include_directories(PlatformAudioPlayer PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
20+
target_link_libraries(PlatformAudioPlayer PRIVATE ${LIVEKIT_CORE_TARGET})
21+
22+
livekit_copy_windows_runtime_dlls(PlatformAudioPlayer)

platform_audio/player/main.cpp

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*
2+
* Copyright 2026 LiveKit, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/// Plays subscribed room audio using PlatformAudio.
18+
///
19+
/// Usage:
20+
/// PlatformAudioPlayer <ws-url> <player-token>
21+
///
22+
/// Or via environment variables:
23+
/// LIVEKIT_URL, LIVEKIT_PLAYER_TOKEN
24+
25+
#include <atomic>
26+
#include <chrono>
27+
#include <csignal>
28+
#include <cstdlib>
29+
#include <exception>
30+
#include <iostream>
31+
#include <memory>
32+
#include <string>
33+
#include <thread>
34+
35+
#include "livekit/livekit.h"
36+
37+
using namespace livekit;
38+
39+
namespace {
40+
41+
std::atomic<bool> g_running{true};
42+
43+
void handleSignal(int) { g_running.store(false); }
44+
45+
std::string getenvOrEmpty(const char* name) {
46+
const char* value = std::getenv(name);
47+
return value ? std::string(value) : std::string{};
48+
}
49+
50+
void printUsage() {
51+
std::cerr << "[error] Usage: PlatformAudioPlayer <ws-url> <player-token>\n"
52+
<< " or set LIVEKIT_URL and LIVEKIT_PLAYER_TOKEN\n";
53+
}
54+
55+
class PlayerDelegate final : public RoomDelegate {
56+
public:
57+
void onParticipantConnected(Room&, const ParticipantConnectedEvent& event) override {
58+
if (event.participant) {
59+
std::cout << "[info] [platform-audio-player] Participant connected identity='" << event.participant->identity()
60+
<< "'\n";
61+
}
62+
}
63+
64+
void onTrackSubscribed(Room&, const TrackSubscribedEvent& event) override {
65+
if (!event.track || event.track->kind() != TrackKind::KIND_AUDIO) {
66+
return;
67+
}
68+
69+
const std::string participant_identity = event.participant ? event.participant->identity() : std::string("unknown");
70+
const std::string publication_name = event.publication ? event.publication->name() : event.track->name();
71+
std::cout << "[info] [platform-audio-player] Playing audio track '" << publication_name
72+
<< "' from participant identity='" << participant_identity << "'\n";
73+
}
74+
75+
void onTrackSubscriptionFailed(Room&, const TrackSubscriptionFailedEvent& event) override {
76+
const std::string participant_identity = event.participant ? event.participant->identity() : std::string("unknown");
77+
std::cerr << "[warn] [platform-audio-player] Audio subscription failed for participant identity='"
78+
<< participant_identity << "' track_sid='" << event.track_sid << "'\n";
79+
}
80+
};
81+
82+
} // namespace
83+
84+
int main(int argc, char* argv[]) {
85+
std::string url = getenvOrEmpty("LIVEKIT_URL");
86+
std::string player_token = getenvOrEmpty("LIVEKIT_PLAYER_TOKEN");
87+
88+
if (argc >= 3) {
89+
url = argv[1];
90+
player_token = argv[2];
91+
}
92+
93+
if (url.empty() || player_token.empty()) {
94+
printUsage();
95+
return 1;
96+
}
97+
98+
std::signal(SIGINT, handleSignal);
99+
#ifdef SIGTERM
100+
std::signal(SIGTERM, handleSignal);
101+
#endif
102+
103+
livekit::initialize(livekit::LogLevel::Info, livekit::LogSink::kConsole);
104+
105+
try {
106+
PlatformAudio platform_audio;
107+
108+
auto playout_devices = platform_audio.playoutDevices();
109+
std::cout << "[info] [platform-audio-player] Playout devices: " << playout_devices.size() << "\n";
110+
for (const auto& device : playout_devices) {
111+
std::cout << " [" << device.index << "] " << device.name << " id=" << device.id << "\n";
112+
}
113+
114+
auto room = std::make_unique<Room>();
115+
PlayerDelegate delegate;
116+
room->setDelegate(&delegate);
117+
118+
RoomOptions options;
119+
options.auto_subscribe = true;
120+
options.dynacast = false;
121+
122+
if (!room->connect(url, player_token, options)) {
123+
std::cerr << "[error] [platform-audio-player] Failed to connect\n";
124+
room.reset();
125+
livekit::shutdown();
126+
return 1;
127+
}
128+
129+
auto* local_participant = room->localParticipant();
130+
if (local_participant) {
131+
std::cout << "[info] [platform-audio-player] Connected as identity='" << local_participant->identity()
132+
<< "' room='" << room->roomInfo().name << "'\n";
133+
}
134+
135+
std::cout << "[info] [platform-audio-player] Waiting for remote audio; Ctrl-C to exit\n";
136+
while (g_running.load()) {
137+
std::this_thread::sleep_for(std::chrono::milliseconds(50));
138+
}
139+
140+
std::cout << "[info] [platform-audio-player] Disconnecting\n";
141+
room->setDelegate(nullptr);
142+
room.reset();
143+
} catch (const std::exception& error) {
144+
std::cerr << "[error] [platform-audio-player] " << error.what() << "\n";
145+
livekit::shutdown();
146+
return 1;
147+
}
148+
149+
livekit::shutdown();
150+
return 0;
151+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Copyright 2026 LiveKit, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
add_executable(PlatformAudioSender
16+
main.cpp
17+
)
18+
19+
target_include_directories(PlatformAudioSender PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
20+
target_link_libraries(PlatformAudioSender PRIVATE ${LIVEKIT_CORE_TARGET})
21+
22+
livekit_copy_windows_runtime_dlls(PlatformAudioSender)

0 commit comments

Comments
 (0)