videosdk/iot-sdk

0.3.0

Latest
uploaded 5 days ago
IoTSdk is a lightweight ESP-IDF component that enables ESP32-based IoT devices to participate in real-time meetings through the VideoSDK platform. It provides seamless integration for joining meetings and publishing/subscribing to audio and video.

Readme

# IoT SDK

Official ESP32 SDK of [videosdk.live](https://videosdk.live).

Add live audio and video calling to ESP32-S3 boards. The device joins the same meeting as a phone or a browser. It sends whatever the microphone and camera pick up, and on a board with a speaker and a screen it plays back what the others are sending.

## Features

- Send audio and video from the on-board microphone and camera. Both boards can do this.
- Receive audio and video. This needs a speaker and a display, so Korvo-2 only.
- Send and receive text or binary messages during a call, on either board.
- Create a meeting, join it, and leave it.
- Switch the log verbosity between normal and debug at runtime.

Audio is sent as PCMA, PCMU, or Opus. Video is sent as JPEG.

## Supported boards

| Feature | XIAO ESP32-S3 (Sense) | ESP32-S3-Korvo-2 v3.0 |
|---------|:---:|:---:|
| Send audio | ✅ | ✅ |
| Receive audio | ❌ | ✅ |
| Send video | ✅ | ✅ |
| Receive video | ❌ | ✅ |
| Send & receive messages | ✅ | ✅ |

Both boards can send. Only the Korvo-2 can receive, since the XIAO has no speaker and no screen; there, `startSubscribeAudio()` and `startSubscribeVideo()` return `DEVICE_NOT_SUPPORTED`. The board is picked at build time (see [Configure](#3-configure-menuconfig)).

## Prerequisites

- **ESP-IDF 5.4+** 
- A valid [Video SDK Account](https://app.videosdk.live/)
- Python >= 3.11

## Use the IoT SDK component

### 1. Set up ESP-IDF

Follow **Step 1** of the VideoSDK [ESP-IDF setup guide](https://docs.videosdk.live/iot/guide/video-and-audio-calling-api-sdk/quickstart/quick-start#step-1-setup-for-esp-idf) to install the toolchain. You do not need to run the project-creation commands. Once the environment is ready, continue from Step 2 below.

```bash
# In every new shell, activate the ESP-IDF environment
source ~/esp/esp-idf/export.sh
```

### 2. Add the IoT SDK component

In your project's `main/idf_component.yml`, declare the component:

```yaml
dependencies:
  idf:
    version: '>=5.4.0'
  mdns: '*'
  protocol_examples_common:
    path: ${IDF_PATH}/examples/common_components/protocol_examples_common
  videosdk/iot-sdk:
    version: '*'
  # other components
```

Or add it from the terminal. You can pin a specific version, or use `*` to always pull the latest:

```bash
cd <your project path>

# Pin an exact version (recommended for reproducible builds)
idf.py add-dependency "videosdk/iot-sdk==0.3.0"

# Or always use the latest published version
idf.py add-dependency "videosdk/iot-sdk*"
```
### 3. Configure (menuconfig)

Set your board target, Wi-Fi, and VideoSDK credentials:

```
1. <!-- Run this command to set your board as the target -->
idf.py set-target esp32s3

2. <!-- Run this command to do menuconfig -->

idf.py menuconfig

         a. Inside Example Connection Configuration:
                |
                |———> WIFI SSID          <!-- replace it with your WiFi name -->
                |———> WIFI Password      <!-- replace it with your WiFi password -->
            And click S to save and again enter

         b. Inside VideoSDK Configuration:
                |
                |———> Auth token (JWT)    <!-- paste your VideoSDK token -->
                |———> Meeting / room ID   <!-- the meeting you want to join -->
            And click S to save and again enter

         c. Inside the Partition table:
                |
                |———> Partition table (custom partition table CSV)
                      |———> Enable Custom partition table CSV

         d. Adjust the flash size inside Serial flasher config
            (the examples ship an 8 MB config; the 4 MB factory app needs it)
                | ——> flash size: 8MB
            And click S to save and again enter

         e. Inside SET Microcontroller:
                        |——> Audio hardware board (example: ESP32-S3-Korvo-2)
                            |——> Select your board name
                                    |———> ESP32-S3-Korvo-2
                                    |———> ESP32-S3-XIAO   (default)
                        |——> Speaker output volume (0-100)   [Korvo-2 only]

         f. Inside VideoSDK Logging:
                |
                |———> Log verbosity   <!-- Normal (default) or Debug -->

Then press "S" to save and press "Enter" to confirm, then "Esc" or "q" to exit menuconfig.

```


### 4. Build & flash

```bash
idf.py build
idf.py -p <PORT> flash monitor
```

## Usage

Include the header and call the API from one task. It is not thread-safe.

```c
#include "videosdk.h"
#include "sdkconfig.h"

void app_main(void)
{
    // ... init NVS, netif, event loop, and connect Wi-Fi first ...

    // Optional. Follow the "VideoSDK Logging" menuconfig choice. Call before init().
#ifdef CONFIG_VIDEOSDK_LOG_MODE_DEBUG
    videosdk_set_log_mode(VIDEOSDK_LOG_DEBUG);
#endif

    init_config_t cfg = {
        .meetingID     = CONFIG_VIDEOSDK_MEETING_ID,
        .token         = CONFIG_VIDEOSDK_TOKEN,
        .displayName   = "ESP32S3-Device",  // user configurable
        .participantId = "",               // "" gets you a random id
        .audioCodec    = AUDIO_CODEC_PCMA, // or AUDIO_CODEC_PCMU / AUDIO_CODEC_OPUS
        .videoCodec    = VIDEO_CODEC_JPEG, // or VIDEO_CODEC_NONE for no video
    };
    if (init(&cfg) != RESULT_OK) {
        return;
    }

    // Start whichever directions you need, in any order. Each call returns a
    // result_t: RESULT_OK on success, or an error such as DEVICE_NOT_SUPPORTED
    // when the board can't do that direction.
    result_t result_publish_audio = startPublishAudio();
    printf("startPublishAudio: %d\n", result_publish_audio);

    result_t result_subscribe_audio = startSubscribeAudio();
    printf("startSubscribeAudio: %d\n", result_subscribe_audio);

    result_t result_publish_video = startPublishVideo();
    printf("startPublishVideo: %d\n", result_publish_video);

    result_t result_subscribe_video = startSubscribeVideo();
    printf("startSubscribeVideo: %d\n", result_subscribe_video);

    while (1) {
        vTaskDelay(pdMS_TO_TICKS(10));
    }

    // leave() shuts every direction down.
}
```

`init()` copies the strings in `init_config_t`, so you can free your own buffers as soon as it returns.

### Application messages

Text and binary messages travel alongside the media streams. Open the channel with `startMessageChannel()` before you call `sendMessage()`. To receive, register a handler.

```c
#include "videosdk.h"

// Runs on an SDK task. Don't block here, and copy anything you want to keep.
static void on_data_message(const uint8_t *data, size_t len, int is_binary, uint16_t sid)
{
    if (is_binary) {
        printf("binary message, %u bytes\n", (unsigned)len);
    } else {
        printf("text message: %.*s\n", (int)len, (const char *)data);
    }
}

// Optional. Fires when signaling comes up or goes away.
static void on_connection_state(bool connected, void *user)
{
    if (!connected) {
        // Session is gone. leave() and rejoin.
    }
}

void messaging_example(void)
{
    // Register handlers after init() but before the start* calls.
    setDataMessageHandler(on_data_message);
    setConnectionStateHandler(on_connection_state, NULL);

    if (startMessageChannel() != RESULT_OK) {
        return;
    }

    const char *text = "hello from esp32";
    sendMessage((const uint8_t *)text, strlen(text), /* is_binary */ 0);

    const uint8_t blob[4] = {0xDE, 0xAD, 0xBE, 0xEF};
    sendMessage(blob, sizeof(blob), /* is_binary */ 1);

    stopMessageChannel();
}
```

`sendMessage()` takes at most 24000 bytes per message. It returns `DATA_CHANNEL_NOT_STARTED` if the channel was never opened, or `DATA_CHANNEL_QUEUE_FULL` when the outgoing queue backs up. Passing `NULL` to either handler setter clears it.

## API reference

All declarations live in [`include/videosdk.h`](include/videosdk.h).

### `init_config_t`

| Field | Type | Notes |
|-------|------|-------|
| `meetingID` | `char *` | The meeting ID to join.|
| `token` | `char *` | VideoSDK JWT auth token. |
| `displayName` | `char *` | Name shown in the meeting. |
| `participantId` | `char *` | This device's peer id. `""` or `NULL` gives you a random 8-char id. |
| `audioCodec` | `audio_codec_t` | `AUDIO_CODEC_PCMA`, `AUDIO_CODEC_PCMU`, or `AUDIO_CODEC_OPUS`. |
| `videoCodec` | `video_codec_t` | `VIDEO_CODEC_NONE` (no video) or `VIDEO_CODEC_JPEG`. |

### Functions

| Function | Description |
|----------|-------------|
| `create_meeting_result_t create_meeting(char *token)` | Create a meeting. Returns a malloc'd `room_id` that the caller frees. |
| `void videosdk_set_log_mode(videosdk_log_mode_t mode)` | Set log verbosity (`VIDEOSDK_LOG_NORMAL` or `VIDEOSDK_LOG_DEBUG`). Call before `init()`. |
| `result_t init(init_config_t *cfg)` | Initialize the session and the board. Call once, before anything else. |
| `result_t startPublishAudio(void)` | Capture the microphone and send it to the meeting. |
| `result_t startPublishVideo(void)` | Capture the camera and send it to the meeting. |
| `result_t startSubscribeAudio(void)` | Receive remote audio and play it on the speaker. Korvo-2 only. |
| `result_t startSubscribeVideo(void)` | Receive remote video and show it on the display. Korvo-2 only. |
| `result_t stopPublishAudio()` | Stop publishing audio. |
| `result_t stopSubscribeAudio()` | Stop subscribing to audio. |
| `void setSpeakerVolume(int volume)` | Set playback volume, 0 to 100 (out-of-range values are clamped). Korvo-2 only. |
| `result_t startMessageChannel(void)` | Open the message channel. Needed before `sendMessage()`. |
| `result_t sendMessage(const uint8_t *data, size_t len, int is_binary)` | Send a text or binary message. `len` is capped at 24000 bytes. |
| `result_t stopMessageChannel(void)` | Close the message channel. |
| `void setDataMessageHandler(data_message_cb_t cb)` | Set the incoming-message handler. `NULL` clears it. |
| `void setConnectionStateHandler(connection_state_cb_t cb, void *user)` | Set the connection-state handler. `NULL` clears it. |
| `result_t leave()` | Leave the meeting and stop every direction that was started. |

Directions are independent, so start them in any combination and any order. Callbacks run on SDK tasks, so don't block in them, and copy any buffer you want to keep.

### Result codes

`RESULT_OK` (0) means success. Errors fall in the `3001` to `3026` range, for example `DEVICE_NOT_SUPPORTED`, `AUDIO_CODEC_INIT_FAILED`, `DTLS_HANDSHAKE_FAILED`, `INIT_NOT_CALLED`, `DUPLICATE_ID`, `DATA_CHANNEL_NOT_STARTED` and `DATA_CHANNEL_QUEUE_FULL`. The header lists them all.


## Documentation

- For more details, see the [VideoSDK Documentation](https://docs.videosdk.live/iot/guide/video-and-audio-calling-api-sdk/concept-and-architecture).

Links

Target

To add this component to your project, run:

idf.py add-dependency "videosdk/iot-sdk^0.3.0"

download archive

Stats

  • Archive size
    Archive size ~ 2.24 MB
  • Downloaded in total
    Downloaded in total 25 times
  • Downloaded this version
    This version: 0 times

Badge

videosdk/iot-sdk version: 0.3.0
|