基础实现流程
更新时间: 2026/05/28 17:08:52
本文介绍使用网易云信嵌入式 SDK(NERTC SDK)完成 AI 对话功能的核心实现步骤,包括 SDK 的初始化、事件监听、建立与结束 AI 对话(session)等关键操作。
名词解释
- NERTC SDK:网易云信嵌入式实时通信软件开发工具包,专为硬件设备设计的轻量级音视频通信解决方案,提供实时音频传输、AI 对话、语音识别等核心功能。
- 引擎:NERTC SDK 的核心控制实例,负责管理整个 AI 对话 session 的生命周期,包括初始化配置、session 建立、媒体流处理等所有底层操作的统一入口。
- AI 对话 session:设备与云端 AI 服务之间的一次实时对话会话,由
nertc_join建立底层会话后,再通过nertc_start_ai_with_config正式开启。 - 用户:AI 对话 session 中的参与者,由唯一的用户 ID(uid)标识。设备侧用户通过音频流与 AI 服务进行实时交互。
- AI 服务:云端智能对话服务,提供语音识别、自然语言理解、对话生成和语音合成等 AI 能力,实现与用户的智能语音交互。
- ASR 服务:自动语音识别(Automatic Speech Recognition)服务,将用户的语音实时转换为文字字幕,为用户提供可视化的语音内容显示。
- 安全模式:AI 对话 session 建立前的身份验证机制。安全模式下需要通过业务服务器生成的有效凭证(Token)进行身份验证。与安全模式相对的是调试模式,调试模式下可直接建立 session,但存在串 session 风险,仅适用于概念验证的原型阶段。更多有关两种模式对比的详情,请参考《音视频通话 2.0》基础 Token 鉴权。
此处的 Token 是指会话身份凭证,与大语言模型的自然语言文本基本单位 token 概念不同。
准备工作
根据本文操作前,请确保您已经完成了以下工作:
- 获取 NERTC SDK。
- 获取设备授权码 License。
- 在测试开发阶段,建议在 网易云信控制台 中为您的应用开通 调试模式,此时建立 AI 对话 session 无需进行凭证(Token)校验。应用正式上线前,请务必切换为 安全模式,以保障业务安全。详细说明请参考《音视频通话 2.0》Token 鉴权。
流程概述
本文中实现 AI 对话功能实现的完整时序如下:
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#AFDDFF', 'primaryTextColor': '#5409DA', 'primaryBorderColor': '#4E71FF', 'lineColor': '#4E71FF', 'secondaryColor': '#FF9149', 'tertiaryColor': '#F8FAFC' }}}%%
sequenceDiagram
participant App as 应用程序
participant SDK as 嵌入式 NERTC SDK
participant Engine as NERTC 引擎
participant Server as 云端服务
participant AI as AI 服务
Note over App, AI: 第一步:创建和初始化
App->>SDK: 配置 SDK 参数<br> (app_key, device_id, event_handler)
App->>SDK: 配置音频参数
App->>SDK: nertc_create_engine_with_config()
SDK-->>App: 返回引擎实例
App->>Engine: nertc_init_engine()
Engine-->>App: 初始化结果
Note over App, AI: 第二步:实现监听函数
App->>Engine: 设置回调函数
Note over App, AI: 第三步:建立 AI 对话 session
App->>Engine: nertc_join(token, channel_name, uid)
Engine->>Server: 发送 session 建立请求
Server->>Engine: 验证并处理建立请求
Note over App, AI: 第四步:开启 AI 对话
App->>Engine: nertc_start_ai(ai_config)
Engine->>AI: 连接 AI 服务
AI-->>Engine: AI 服务就绪
Engine->>App: AI 开启结果
opt 开启实时字幕
App->>Engine: nertc_start_asr_caption(asr_config)
Engine->>Server: 连接 ASR 服务
Server-->>Engine: ASR 服务就绪
Engine->>App: ASR 开启结果
end
Note over App, AI: 第五步:结束 AI 对话 session
App->>Engine: nertc_leave()
Engine->>Server: 发送 session 结束请求
Engine->>AI: 断开 AI 服务连接
Server-->>Engine: 确认结束
AI-->>Engine: 断开连接确认
Engine->>App: session 结束完成
第一步:创建和初始化
在进行任何操作之前,您必须先创建一个 NERTC SDK 引擎实例。通过调用 nertc_create_engine_with_config 和 nertc_init_engine 方法来完成创建和初始化。此过程在应用的生命周期中通常仅需执行一次。
初始化时,您需要在 nertc_sdk_configuration_t 结构体中配置以下关键信息:
-
app_key:填入您在准备工作中获取到的 App Key。 -
device_id:设备的唯一标识符,由客户端负责生成和维护。该标识符需要确保在设备级别的唯一性和持久性。 -
event_handler:在引擎初始化阶段通过nertc_sdk_engine_config_t配置nertc_sdk_event_handle_t类型的事件回调句柄,用于接收 SDK 在运行过程中的各类事件通知。 -
audio_config:如果您计划使用 本地 AEC 方案,需要在此配置音频的采集参数,如采样率、声道数等。 -
licence_cfg:设置用于设备鉴权的 Licence。C++// 1 - SDK 全局配置和创建引擎: nertc_sdk_configuration_t sdk_config = { 0 }; nertc_sdk_configuration_init(&sdk_config); sdk_config.app_key = MY_APPKEY; sdk_config.device_id = MY_DEVICE_ID; sdk_config.force_unsafe_mode = true; // License 配置 sdk_config.licence_cfg.license = MY_LICENSE; // 音频配置: 如果采用本地 AEC 方案,需要配置采样率、声道数、帧时长等参数。 // 如果采用服务端 AEC,请重点关注 OnJoin 回调返回的 recommended_config,并按推荐参数采集和发送音频。 sdk_config.audio_config.sample_rate = 16000; sdk_config.audio_config.frame_duration = OPUS_FRAME_DURATION_MS; sdk_config.audio_config.channels = 1; sdk_config.audio_config.samples_per_channel = 160; sdk_config.audio_config.codec_type = NERTC_SDK_AUDIO_CODEC_TYPE_OPUS; // 可选配置: sdk_config.optional_config.device_performance_level = NERTC_SDK_DEVICE_LEVEL_NORMAL; sdk_config.optional_config.prefer_use_psram = MY_CONFIG_PSRAM_ENABLED ? true : false; sdk_config.optional_config.enable_server_aec = MY_DEVICE_AEC_ENABLED ? false : true; // 日志配置: sdk_config.log_cfg.log_level = NERTC_SDK_LOG_INFO; engine_ = nertc_create_engine_with_config(&sdk_config); if (!engine_) { ESP_LOGE(TAG, "NERtcSDK failed to create engine"); return; } // 2 - 引擎配置和初始化 nertc_sdk_engine_config_t engine_config = {}; nertc_sdk_engine_config_init(&engine_config); // 工作模式: engine_config.engine_mode = MY_ENABLE_PTT ? NERTC_SDK_ENGINE_MODE_PTT : NERTC_SDK_ENGINE_MODE_AI; // 事件回调: engine_config.event_handler.on_error = OnError; engine_config.event_handler.on_license_expire_warning = OnLicenseExpireWarning; engine_config.event_handler.on_channel_status_changed = OnChannelStatusChanged; engine_config.event_handler.on_join = OnJoin; engine_config.event_handler.on_disconnect = OnDisconnect; engine_config.event_handler.on_user_joined = OnUserJoined; engine_config.event_handler.on_user_left = OnUserLeft; engine_config.event_handler.on_user_audio_start = OnUserAudioStart; engine_config.event_handler.on_user_audio_stop = OnUserAudioStop; engine_config.event_handler.on_asr_caption_result = OnAsrCaptionResult; engine_config.event_handler.on_ai_data = OnAiData; engine_config.event_handler.on_audio_encoded_data = OnAudioData; // 用户数据(可选): engine_config.user_data = this; // 初始化引擎 int ret = nertc_init_engine(engine_, &engine_config); if (ret != 0) { RTC_LOGE(TAG, "Failed to initialize NERtcSDK, error: %d", ret); } else { RTC_LOGI(TAG, "Successfully initialized NERtcSDK."); }
第二步:实现监听函数
您需要根据上一步中设置的回调,实现对应的处理函数。这些函数是 SDK 与您的应用进行异步通信的桥梁。
C++void MyAPPClass::OnJoin(const nertc_sdk_callback_context_t* ctx,
uint64_t cid, uint64_t uid,
nertc_sdk_error_code_e code,
uint64_t elapsed,
const nertc_sdk_recommended_config_t* recommended_config) {
if (code == 0) {
RTC_LOGI(TAG, "Successfully created AI session %llu with uid %llu.", cid, uid);
} else {
RTC_LOGE(TAG, "Failed to create AI session, error: %d", code);
}
}
void MyAPPClass::OnAudioEncodedData(const nertc_sdk_callback_context_t* ctx,
uint64_t uid,
nertc_sdk_media_stream_e stream_type,
nertc_sdk_audio_encoded_frame_t* encoded_frame,
bool is_mute_packet) {
RTC_LOGD(TAG, "Received audio data from user %llu.", uid);
// 在此处处理接收到的音频数据,例如解码和播放
}
// ... 实现其他必要的监听函数
第三步:建立 AI 对话
初始化成功后,调用 nertc_join 方法建立 AI 对话 session 的底层会话。建立成功后,设备即可进入后续 AI 对话流程。
| 参数 | 说明 |
|---|---|
token |
安全认证签名(NERTC Token)。
|
channel_name |
会话名称,长度为 1 ~ 64 字节,目前支持以下 89 个字符:a-z, A-Z, 0-9, space, !#$%&()+-:;≤.,>? @[]^_{| }~"。相同 channel_name 的请求会进入同一个对话 session。 |
uid |
用户的唯一标识 ID,必须在当前 session 内唯一。请在您的业务服务器上自行管理和维护。 |
成功建立 AI 对话 session 后,SDK 会触发 on_join 回调。
如果音频采用 云端 AEC 方案,您需要特别关注并保存在 on_join 回调中返回的 recommended_config。后续采集和发送音频流时,必须依据该配置进行,以确保 AEC 效果。
C++void MyAPPClass::StartSession() {
// 使用从业务服务器获取的 Token
auto ret = nertc_join(engine_, MY_CHANNEL_NAME, MY_TOKEN, MY_UID);
if (ret != 0) {
RTC_LOGE(TAG, "Create AI session failed, error: %d", ret);
} else {
RTC_LOGI(TAG, "Create AI session success");
}
}
void MyAPPClass::OnJoin(const nertc_sdk_callback_context_t* ctx,
uint64_t cid,
uint64_t uid,
nertc_sdk_error_code_e code,
uint64_t elapsed,
const nertc_sdk_recommended_config_t* recommended_config) {
RTC_LOGI(TAG, "NERtcSDK OnJoin: %llu, %llu, %d, %llu", cid, uid, code, elapsed);
// 如果是云端 AEC 方案,保存服务器推荐的音频配置
if (recommended_config) {
server_sample_rate_ = recommended_config->recommended_audio_config.sample_rate;
samples_per_channel_ = recommended_config->recommended_audio_config.samples_per_channel;
server_frame_duration_ = (samples_per_channel_ * 1000) / server_sample_rate_;
}
}
第四步:开启 AI 对话
AI 对话
当用户通过语音唤醒或手动操作触发对话时,调用 nertc_start_ai_with_config 接口来正式开启 AI 对话。
C++// 开启 AI 对话
nertc_sdk_start_ai_config_t ai_config = { 0 }; // 可按需配置
nertc_sdk_start_ai_config_init(&ai_config);
auto ret = nertc_start_ai_with_config(engine_, &ai_config);
if (ret != 0) {
RTC_LOGE(TAG, "Start AI failed, error: %d", ret);
} else {
RTC_LOGI(TAG, "Start AI success");
}
实时字幕
同时,您可以根据业务需求调用 nertc_start_asr_caption 来开启实时字幕功能。
C++// 开启实时字幕
nertc_sdk_asr_caption_config_t asr_config = { 0 }; // 可按需配置
nertc_sdk_asr_caption_config_init(&asr_config);
ret = nertc_start_asr_caption(engine_, &asr_config);
if (ret != 0) {
RTC_LOGE(TAG, "Start ASR caption failed, error: %d", ret);
} else {
RTC_LOGI(TAG, "Start ASR caption success");
}
上传语音
网易云信提供了三种 回声消除 AEC 方案:云端 AEC 方案、本地 AEC 方案、无 AEC 方案。此处以云端 AEC 方案为例,介绍如何上传语音数据。您也可以根据自身需求,选择其他 AEC 方案上传语音数据。
C++// 发送麦克风采集的音频流
void MyAPPClass::SendAudioData(const std::vector<uint8_t>& opus_payload) {
nertc_sdk_audio_encoded_frame_t encoded_frame = { 0 };
nertc_sdk_audio_encoded_frame_init(&encoded_frame);
encoded_frame.data = const_cast<unsigned char*>(opus_payload.data());
encoded_frame.length = opus_payload.size();
encoded_frame.payload_type = NERTC_SDK_AUDIO_ENCODE_OPUS;
nertc_sdk_audio_config_t audio_config = { 0 };
nertc_sdk_audio_config_init(&audio_config);
audio_config.sample_rate = 16000;
audio_config.frame_duration = 20;
audio_config.channels = 1;
audio_config.samples_per_channel = 320;
audio_config.codec_type = NERTC_SDK_AUDIO_CODEC_TYPE_OPUS;
nertc_push_audio_encoded_frame(engine_, NERTC_SDK_MEDIA_MAIN_AUDIO,
audio_config, 100, &encoded_frame);
}
// 接收并处理云端 AI 音频,同时根据实际 AEC 方案回传参考帧
void MyAPPClass::OnAudioEncodedData(const nertc_sdk_callback_context_t* ctx,
uint64_t uid,
nertc_sdk_media_stream_e stream_type,
nertc_sdk_audio_encoded_frame_t* encoded_frame,
bool is_mute_packet) {
ESP_LOGI(TAG, "NERtcSDK OnAudioEncodedData");
std::vector<uint8_t> payload_vector;
if (encoded_frame->data) {
payload_vector.assign(encoded_frame->data, encoded_frame->data + encoded_frame->length);
// 在此处解码并播放云端返回的音频数据
PlayAudio(payload_vector);
// 如果您的 AEC 方案需要参考帧,可在播放后按需调用该接口
nertc_push_audio_reference_frame(engine_, NERTC_SDK_MEDIA_MAIN_AUDIO,
encoded_frame, nullptr);
}
}
// 支持自动打断,同时支持手动打断
void MyAPPClass::ManualInterrupt() {
nertc_ai_manual_interrupt(engine_);
}
状态监听
获取 AI 文本转语音(TTS)状态可以通过监听以下接口实现:
C++void MyAPPClass::OnAiData(const nertc_sdk_callback_context_t* ctx, nertc_sdk_ai_data_result_t* ai_data) {
std::string type(ai_data->type, ai_data->type_len);
std::string data(ai_data->data, ai_data->data_len);
// 可以打印出类似以下的 log:
// NERtcSDK OnAiData type:event data:audio.agent.speech_started
// NERtcSDK OnAiData type:event data:audio.agent.speech_stopped
ESP_LOGI(TAG, "NERtcSDK OnAiData, type=%s data=%s", type.c_str(), data.c_str());
}
第五步:结束 AI 对话
当对话结束时,调用 nertc_leave 方法结束当前 AI 对话 session 并停止数据传输。
如果确认不再需要 NERTC SDK 实例,可以调用 nertc_destroy_engine 方法来释放资源。
C++// 结束 AI 对话 session
nertc_leave(engine_);
// 销毁引擎实例
if (engine_) {
nertc_destroy_engine(engine_);
engine_ = nullptr;
}
下一步
参考 配置 AEC 方案 选择 AI 对话过程中的音频回声消除功能。




