Last active
January 7, 2025 14:50
-
-
Save GOROman/cd8554584b9ce8381b111bf7565cbc9c to your computer and use it in GitHub Desktop.
Using DataChannel in the OpenAI Realtime API Embedded SDK
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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