Skip to content

Instantly share code, notes, and snippets.

@GOROman
Last active January 7, 2025 14:50
Show Gist options
  • Save GOROman/cd8554584b9ce8381b111bf7565cbc9c to your computer and use it in GitHub Desktop.
Save GOROman/cd8554584b9ce8381b111bf7565cbc9c to your computer and use it in GitHub Desktop.
Using DataChannel in the OpenAI Realtime API Embedded SDK
#ifndef LINUX_BUILD
#include <driver/i2s.h>
#include <opus.h>
#endif
#include <esp_event.h>
#include <esp_log.h>
#include <string.h>
#include "main.h"
#define TICK_INTERVAL 15
PeerConnection *peer_connection = NULL;
#ifndef LINUX_BUILD
StaticTask_t task_buffer;
void oai_send_audio_task(void *user_data) {
oai_init_audio_encoder();
while (1) {
oai_send_audio(peer_connection);
vTaskDelay(pdMS_TO_TICKS(TICK_INTERVAL));
}
}
#endif
// ⭐️ OpenAI Realtime API Events Label
#define DATACHANNEL_NAME "oai-events"
// ⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️
// DataChannel オープン時に呼ばれるコールバック
// ⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️
static void onopen(void *user_data) {
ESP_LOGI(LOG_TAG, "⭐️ DataChannel opened");
/*
int peer_connection_create_datachannel(
PeerConnection* pc,
DecpChannelType channel_type,
uint16_t priority,
uint32_t reliability_parameter,
char* label,
char* protocol
);
See also...
https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createDataChannel
*/
int res = peer_connection_create_datachannel(peer_connection, DATA_CHANNEL_RELIABLE, 0, 0, DATACHANNEL_NAME, "");
printf("%d = peer_connection_create_datachannel(peer_connection, DATA_CHANNEL_RELIABLE, 0, 0, \"%s\", \"\"); \n", res, DATACHANNEL_NAME);
}
// ⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️
// DataChannel クローズ時に呼ばれるコールバック
// ⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️
static void onclose(void *user_data) {
ESP_LOGI(LOG_TAG, "⭐️ DataChannel closed");
}
// ⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️
// DataChannel 受信時に呼ばれるコールバック
// ⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️
void onmessage(char* msg, size_t len, void* userdata, uint16_t sid) {
ESP_LOGI(LOG_TAG, "⭐️ DataChannel message received: %.*s", len, msg);
}
static void oai_onconnectionstatechange_task(PeerConnectionState state,
void *user_data) {
ESP_LOGI(LOG_TAG, "PeerConnectionState: %s",
peer_connection_state_to_string(state));
if (state == PEER_CONNECTION_DISCONNECTED ||
state == PEER_CONNECTION_CLOSED) {
#ifndef LINUX_BUILD
esp_restart();
#endif
} else if (state == PEER_CONNECTION_CONNECTED) {
#ifndef LINUX_BUILD
StackType_t *stack_memory = (StackType_t *)heap_caps_malloc(
20000 * sizeof(StackType_t), MALLOC_CAP_SPIRAM);
xTaskCreateStaticPinnedToCore(oai_send_audio_task, "audio_publisher", 20000,
NULL, 7, stack_memory, &task_buffer, 0);
#endif
}
}
static void oai_on_icecandidate_task(char *description, void *user_data) {
char local_buffer[MAX_HTTP_OUTPUT_BUFFER + 1] = {0};
oai_http_request(description, local_buffer);
peer_connection_set_remote_description(peer_connection, local_buffer);
}
void oai_webrtc() {
PeerConfiguration peer_connection_config = {
.ice_servers = {},
.audio_codec = CODEC_OPUS,
.video_codec = CODEC_NONE,
// .datachannel = DATA_CHANNEL_NONE,
// ⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️
.datachannel = DATA_CHANNEL_STRING, // ⭐️ Using WebRTC DataChannel
// ⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️
.onaudiotrack = [](uint8_t *data, size_t size, void *userdata) -> void {
#ifndef LINUX_BUILD
oai_audio_decode(data, size);
#endif
},
.onvideotrack = NULL,
.on_request_keyframe = NULL,
.user_data = NULL,
};
peer_connection = peer_connection_create(&peer_connection_config);
if (peer_connection == NULL) {
ESP_LOGE(LOG_TAG, "Failed to create peer connection");
#ifndef LINUX_BUILD
esp_restart();
#endif
}
peer_connection_oniceconnectionstatechange(peer_connection,
oai_onconnectionstatechange_task);
peer_connection_onicecandidate(peer_connection, oai_on_icecandidate_task);
// ⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️
peer_connection_ondatachannel(peer_connection, onmessage, onopen, onclose); // ⭐️ Added callback
// ⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️
peer_connection_create_offer(peer_connection);
while (1) {
peer_connection_loop(peer_connection);
vTaskDelay(pdMS_TO_TICKS(TICK_INTERVAL));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment