Skip to content

Commit 550bec8

Browse files
chenosaurusladvoc
andauthored
Improve ESP32 docs (#12)
* move examples up * tweak name * Add additional documentation --------- Co-authored-by: Jacob Gelman <[email protected]>
1 parent f590cc7 commit 550bec8

File tree

3 files changed

+158
-10
lines changed

3 files changed

+158
-10
lines changed

README.md

Lines changed: 142 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,20 @@ Use this SDK to add realtime video, audio and data features to your ESP32 projec
2020

2121
- **Supported chipsets**: ESP32-S3 and ESP32-P4
2222
- **Bidirectional audio**: Opus encoding, acoustic echo cancellation (AEC)
23-
- **Bidirectional video**: *coming soon*
23+
- **Bidirectional video**: *video support coming soon*
2424
- **Real-time data**: data packets, remote method calls (RPC)
2525

26-
## Installation
26+
## Examples
27+
28+
One of the best ways to get started with LiveKit is by reviewing the examples and choosing one as a starting point for your project:
29+
30+
### [Voice AI Agent](./examples/voice_agent/README.md)
31+
32+
Conversational AI voice agent that interacts with hardware based on user requests.
33+
34+
## Basic usage
35+
36+
### Installation
2737

2838
In your application's IDF component manifest, add LiveKit as a Git dependency:
2939

@@ -35,14 +45,139 @@ dependencies:
3545
version: <current version tag>
3646
```
3747
38-
Please be sure to pin to a specific version tag as subsequent 0.x.x releases may have breaking changes. In the future, this SDK will be added to the [ESP component registry](https://components.espressif.com).
48+
Please be sure to pin to a specific version tag, as subsequent 0.x.x releases may have breaking changes. In the future, this SDK will be added to the [ESP component registry](https://components.espressif.com).
3949
40-
## Examples
50+
With LiveKit added as a dependency to your application, include the LiveKit header and invoke
51+
`livekit_system_init` early in your application's main function:
4152

42-
One of the best ways to get started with LiveKit is by reviewing the examples and choosing one as a starting point for your project:
53+
```c
54+
#include "livekit.h"
55+
56+
void app_main(void)
57+
{
58+
livekit_system_init();
59+
// Your application code...
60+
}
61+
```
62+
63+
### Configure media pipeline
64+
65+
LiveKit for ESP32 puts your application in control of the media pipeline; your application configures a capturer and/or renderer and provides their handles when creating a room.
66+
67+
#### Capturer: input from camera/microphone
68+
69+
- Required for rooms which will publish media tracks
70+
- Created using the Espressif [*esp_capture*](./components/third_party/esp-webrtc-solution/components/esp_capture/README.md) component
71+
- Capture audio capture over I2S, video from MIPI CSI or DVI cameras
72+
- After configuration, you will provide the `esp_capture_handle_t` when creating a room
73+
74+
#### Renderer: output to display/speaker
75+
76+
- Required for rooms which will subscribe to media tracks
77+
- Created using the Espressif [*av_render*](./components/third_party/esp-webrtc-solution/components/av_render/README.md) component
78+
- Playback audio over I2S, video on LCD displays supported by *esp_lcd*
79+
- After configuration, you will provide the `av_render_handle_t` when creating a room
80+
81+
Please refer to the [examples](#examples) in this repository, which support many popular development boards via the Espressif [*codec_board*](./components/third_party/esp-webrtc-solution/components/codec_board/README.md) component.
82+
83+
### Create room
84+
85+
Create a room object, specifying your capturer, renderer, and handlers for room events:
86+
87+
```c
88+
static livekit_room_handle_t room_handle = NULL;
89+
90+
livekit_room_options_t room_options = {
91+
.publish = {
92+
.kind = LIVEKIT_MEDIA_TYPE_AUDIO,
93+
.audio_encode = {
94+
.codec = LIVEKIT_AUDIO_CODEC_OPUS,
95+
.sample_rate = 16000,
96+
.channel_count = 1
97+
},
98+
.capturer = my_capturer
99+
},
100+
.subscribe = {
101+
.kind = LIVEKIT_MEDIA_TYPE_AUDIO,
102+
.renderer = my_renderer
103+
},
104+
.on_state_changed = on_state_changed,
105+
.on_participant_info = on_participant_info
106+
};
107+
if (livekit_room_create(&room_handle, &room_options) != LIVEKIT_ERR_NONE) {
108+
ESP_LOGE(TAG, "Failed to create room object");
109+
}
110+
```
111+
112+
This example does not show all available fields in room options—please refer to the [API reference](https://livekit.github.io/client-sdk-esp32/group__Lifecycle.html#structlivekit__room__options__t)
113+
for an extensive list.
114+
115+
Typically, you will want to create the room object early in your application's lifecycle, and connect/disconnect as necessary based on user interaction.
116+
117+
### Connect room
43118

44-
- [Voice Agent](./examples/voice_agent/README.md): conversational AI voice agent that interacts with hardware based on user requests.
45-
- *More examples coming soon*
119+
With a room room handle, connect by providing a server URL and token:
120+
121+
```c
122+
livekit_room_connect(room_handle, "<your server URL>", "<token>");
123+
```
124+
125+
The connect method is asynchronous; use your `on_state_changed` handler provided in room options
126+
to get notified when the connection is established or fails (e.g. due to an expired token, etc.).
127+
128+
Once connected, media exchange will begin:
129+
130+
1. If a capturer was provided, video and/or audio tracks will be published.
131+
2. If a renderer was provided, the first video and/or audio tracks in the room will be subscribed to.
132+
133+
### Real-time data
134+
135+
In addition to real-time audio and video, LiveKit offers several methods for exchange real-time data between participants in a room.
136+
137+
#### Remote method call (RPC)
138+
139+
Define an RPC handler:
140+
141+
```c
142+
static void get_cpu_temp(const livekit_rpc_invocation_t* invocation, void* ctx)
143+
{
144+
float temp = board_get_temp();
145+
char temp_string[16];
146+
snprintf(temp_string, sizeof(temp_string), "%.2f", temp);
147+
livekit_rpc_return_ok(temp_string);
148+
}
149+
```
150+
151+
Register the handler on the room to allow it to be invoked by remote participants:
152+
153+
```c
154+
livekit_room_rpc_register(room_handle, "get_cpu_temp", get_cpu_temp);
155+
```
156+
157+
> [!TIP]
158+
> In the [*voice_agent*](./examples/voice_agent/) example, RPC is used to allow an AI agent to interact
159+
> with hardware by defining a series of methods for the agent to invoke.
160+
161+
#### User packets
162+
163+
Publish a user packet containing a raw data payload under a specific topic:
164+
165+
```c
166+
const char* command = "G5 I0 J3 P0 Q-3 X2 Y3";
167+
168+
livekit_payload_t payload = {
169+
.bytes = (uint8_t*)command,
170+
.size = strlen(command)
171+
};
172+
livekit_data_publish_options_t options = {
173+
.payload = &payload,
174+
.topic = "gcode",
175+
.lossy = false,
176+
.destination_identities = (char*[]){ "printer-1" },
177+
.destination_identities_count = 1
178+
};
179+
livekit_room_publish_data(room_handle, &options);
180+
```
46181

47182
## Documentation
48183

components/livekit/include/livekit.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -368,9 +368,7 @@ typedef struct {
368368
///
369369
/// Example usage:
370370
/// @code
371-
/// const char* command = "G5 I0 J3 P0 Q-3 X2 Y3";
372-
///
373-
/// livekit_payload_t payload = {
371+
/// livekit_data_payload_t payload = {
374372
/// .bytes = (uint8_t*)command,
375373
/// .size = strlen(command)
376374
/// };

examples/voice_agent/main/example.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,21 @@ void join_room()
154154
if (connect_res != LIVEKIT_ERR_NONE) {
155155
ESP_LOGE(TAG, "Failed to connect to room");
156156
}
157+
158+
const char* command = "G5 I0 J3 P0 Q-3 X2 Y3";
159+
160+
livekit_data_payload_t payload = {
161+
.bytes = (uint8_t*)command,
162+
.size = strlen(command)
163+
};
164+
livekit_data_publish_options_t options = {
165+
.payload = &payload,
166+
.topic = "gcode",
167+
.lossy = false,
168+
.destination_identities = (char*[]){ "printer-1" },
169+
.destination_identities_count = 1
170+
};
171+
livekit_room_publish_data(room_handle, &options);
157172
}
158173

159174
void leave_room()

0 commit comments

Comments
 (0)