本文将介绍设备如何接入 AI 对话服务。
前提条件
2. 购买了 腾讯云物联网开发平台 相关实例,开通并激活了 智能语音增值服务。
3. 在 物联网开发平台控制台 拿到了本 Demo 所需要的设备三元组(已经激活过了)。
4. 完成了 登录与注册 文档中跑通 tc_iot_login 登录功能。
警告:
AI 对话服务属于增值服务,必须开通此增值服务后激活设备 license 才可以正常使用。
接入步骤
步骤 1:初始化 AI 对话模块
回调 | 说明 |
on_receive_bot_audio | 接收机器人回复的音频帧,将数据送入设备扬声器播放。 |
on_receive_bot_text | 接收机器人回复的文本,可用于屏幕或日志展示。 |
on_receive_asr_text | 接收用户语音识别结果。 |
on_bot_state_changed | 机器人状态变化通知,例如监听、思考、播报和结束。 |
on_launch_call | 机器人触发联系人呼叫时回调,需要先注册联系人。 |
on_error | AI 对话过程中发生错误时回调。 |
#include <stdio.h>#include <string.h>#include "audio_device.h"#include "tc_iot_aitalk.h"static void on_bot_audio(const tc_iot_audio_frame *frame, void *user_data) {(void)user_data;if (!frame || !frame->data || frame->data_size == 0) {return;}if (audio_device_write(frame->data, frame->data_size, frame->codec) != 0) {printf("play bot audio failed\\\\n");}}static void on_aitalk_error(tc_iot_error_e code, const char *message, void *user_data) {(void)user_data;printf("aitalk error: %d, %s\\\\n", code, message ? message : "");}static tc_iot_error_e init_aitalk(void) {tc_iot_aitalk_observer_s observer = {0};observer.on_receive_bot_audio = on_bot_audio;observer.on_error = on_aitalk_error;tc_iot_aitalk_init_params_s params = {0};params.audio_option.codec = TC_IOT_AUDIO_CODEC_OPUS; // 音频编码传输格式,可选aac/opus/g72params.audio_option.sample_rate = TC_IOT_AUDIO_SAMPLE_RATE_16000; // 音频采样率默认16Kparams.audio_option.frame_duration_ms = 20; // g722/opus默认填20 aac默认64/* bot_id 为空时使用平台默认智能体配置; prompt_variables_json 是用户自定义信息 */return tc_iot_aitalk_init(¶ms, &observer, NULL);}
注意:
tc_iot_aitalk_init 必须在 tc_iot_login 登录成功后调用。音频的编码、采样率和帧长应与设备音频采集链路保持一致。步骤 2:注册联系人(可选)
如需让机器人根据语义触发联系人呼叫,请在开始对话前调用
tc_iot_aitalk_register_contacts。最多可注册 10 位联系人。static void on_register_contacts(tc_iot_error_e code, const char *message) {printf("register contacts: %d, %s\\\\n", code, message ? message : "");}static tc_iot_contact_s contacts[] = {{.user_id = "USER_ID", .user_name = "联系人名称"},};tc_iot_aitalk_register_contacts(contacts, 1, on_register_contacts);
步骤 3:开始对话并发送音频
调用
tc_iot_aitalk_start_speak 开始对话。接口为异步调用,请在回调返回成功后再启动麦克风采集。调用前,先按平台实现打开 audio_device_open。模式 | 说明 |
TC_IOT_AITALK_MODE_CONTINUOUS | 持续对话模式,适用于免按键交互场景。 |
TC_IOT_AITALK_MODE_PUSH_TO_TALK | 按键说话模式,适用于按住按键采集语音的场景(暂不支持)。 |
static void on_mic_captured(const uint8_t *data, uint32_t size,tc_iot_audio_codec_e codec, uint64_t pts_ms,void *user_data);static void on_start_speak(tc_iot_error_e code, const char *message) {if (code != TC_IOT_ERR_SUCCESS) {printf("start speak failed: %d, %s\\\\n", code, message ? message : "");return;}if (audio_device_start_capture(on_mic_captured, NULL) != 0) {printf("start capture failed\\\\n");}}tc_iot_aitalk_start_speak(TC_IOT_AITALK_MODE_CONTINUOUS, on_start_speak);
采集到音频后,组装
tc_iot_audio_frame 并调用 tc_iot_aitalk_send_audio 发送:static void on_mic_captured(const uint8_t *data, uint32_t size,tc_iot_audio_codec_e codec, uint64_t pts_ms,void *user_data) {(void)user_data;if (!data || size == 0) {return;}tc_iot_audio_frame frame = {0};frame.codec = codec; // 可以推送PCM由SDK内部编码、发送frame.sample_rate = TC_IOT_AUDIO_SAMPLE_RATE_16000;frame.channels = TC_IOT_AUDIO_CHANNEL_MONO;frame.frame_duration_ms = 20; // 根据实际情况填写frame.data = (uint8_t *)data;frame.data_size = size;frame.pts_ms = pts_ms;tc_iot_error_e rc = tc_iot_aitalk_send_audio(&frame);if (rc != TC_IOT_ERR_SUCCESS) {printf("send audio failed: %d\\\\n", rc);}}
如需直接发送文本,可调用
tc_iot_aitalk_send_text。步骤 4:中断和停止对话
机器人播报过程中,可调用
tc_iot_aitalk_interrupt 中断当前回复。结束对话时,先停止本地采集,再停止 AI 对话并释放模块资源。audio_device_stop_capture(); // 停止音频采集tc_iot_aitalk_stop_speak(); // 停止AI对话tc_iot_aitalk_deinit(); // Deinit 释放资源,完全退出AI对话服务
完整示例代码
以下示例保留 SDK 的真实 API 和关键参数校验;音频采集、播放、休眠等平台相关逻辑均以注释标出,请替换为芯片或操作系统提供的接口。
/* 登录和开始对话均为异步操作,回调中记录结果,主流程据此继续或退出。 */static volatile bool s_login_done = false;static volatile bool s_start_done = false;static volatile bool s_aitalk_error = false;static tc_iot_error_e s_login_result = TC_IOT_ERR_SUCCESS;static tc_iot_error_e s_start_result = TC_IOT_ERR_SUCCESS;static void on_login(tc_iot_error_e error_code, const char *error_message) {s_login_result = error_code;s_login_done = true;// 登录失败时,可在这里记录 error_message 并通知上层业务。}static void on_start_speak(tc_iot_error_e error_code, const char *error_message) {s_start_result = error_code;s_start_done = true;// 开始对话失败时,可在这里记录 error_message 并通知上层业务。}static void on_receive_bot_audio(const tc_iot_audio_frame *frame, void *user_data) {(void)user_data;if (!frame || !frame->data || frame->data_size == 0) {return;}// 这里收到的音频是经过解码后的PCM音频// 将 frame->data 推送到具体的音频设备播放。// 例如:调用芯片平台的扬声器播放、PCM 输出或音频框架接口。}static void on_receive_bot_text(const char *text, void *user_data) {(void)user_data;if (!text) {return;}// 将机器人回复文本显示到屏幕,或上传到您的业务服务。}static void on_receive_asr_text(const char *text, void *user_data) {(void)user_data;if (!text) {return;}// 将用户语音识别结果显示到屏幕,或用于本地业务处理。}static void on_bot_state_changed(tc_iot_aitalk_bot_state_e old_state,tc_iot_aitalk_bot_state_e new_state,void *user_data) {(void)old_state;(void)user_data;// 根据 new_state 更新设备指示灯、屏幕或其他交互状态。}static void on_aitalk_error(tc_iot_error_e error_code, const char *error_message,void *user_data) {(void)user_data;s_aitalk_error = true;// 记录 error_code 和 error_message,并停止或重试业务流程。}/** 在平台麦克风的数据回调中调用本函数。* data、size、codec 和 pts_ms 均来自当前平台的音频采集结果。*/static void on_mic_captured(const uint8_t *data, uint32_t size,tc_iot_audio_codec_e codec, uint64_t pts_ms,void *user_data) {(void)user_data;if (!data || size == 0) {return;}tc_iot_audio_frame frame = {0};frame.codec = codec;frame.sample_rate = TC_IOT_AUDIO_SAMPLE_RATE_16000;frame.channels = TC_IOT_AUDIO_CHANNEL_MONO;frame.frame_duration_ms = 20;frame.data = (uint8_t *)data;frame.data_size = size;frame.pts_ms = pts_ms;tc_iot_error_e rc = tc_iot_aitalk_send_audio(&frame);if (rc != TC_IOT_ERR_SUCCESS) {// 记录发送失败原因;必要时停止采集或触发重连。}}int main(void) {bool sdk_inited = false;bool aitalk_inited = false;bool speak_started = false;bool conversation_completed = false;tc_iot_error_e rc;// 1. 配置并初始化 SDK。tc_iot_config_s sdk_config = {0};sdk_config.storage_path = "./";sdk_config.log_level = TC_IOT_LOG_LEVEL_INFO;rc = tc_iot_init(&sdk_config);if (rc != TC_IOT_ERR_SUCCESS) {goto cleanup;}sdk_inited = true;// 2. 从安全配置中读取设备三元组并登录平台。tc_iot_device_info_s device_info = {0};device_info.product_id = get_product_id();device_info.device_id = get_device_name();device_info.device_secret = get_device_secret();device_info.region = "ap-guangzhou";s_login_done = false;rc = tc_iot_login(&device_info, on_login);if (rc != TC_IOT_ERR_SUCCESS) {goto cleanup;}// 等待 on_login 回调或超时;休眠接口请替换为具体平台实现。wait_until(&s_login_done, 30000);if (!s_login_done || s_login_result != TC_IOT_ERR_SUCCESS) {goto cleanup;}// 3. 注册 AI 对话事件回调并初始化模块。tc_iot_aitalk_observer_s observer = {0};observer.on_receive_bot_audio = on_receive_bot_audio;observer.on_receive_bot_text = on_receive_bot_text;observer.on_receive_asr_text = on_receive_asr_text;observer.on_bot_state_changed = on_bot_state_changed;observer.on_error = on_aitalk_error;tc_iot_aitalk_init_params_s init_params = {0};// 根据实际采集参数设置编码、采样率和单帧时长。init_params.audio_option = get_platform_audio_option();rc = tc_iot_aitalk_init(&init_params, &observer, NULL);if (rc != TC_IOT_ERR_SUCCESS) {goto cleanup;}aitalk_inited = true;// 4. 如需机器人触发联系人呼叫,在开始对话前注册联系人。// tc_iot_aitalk_register_contacts(contacts, contact_count, on_register_contacts);// 5. 初始化具体平台的麦克风和扬声器。// 麦克风采集到一帧音频后,调用 on_mic_captured() 发送给 AI 对话服务。// 6. 异步开始持续对话,成功后再启动麦克风采集。s_start_done = false;rc = tc_iot_aitalk_start_speak(TC_IOT_AITALK_MODE_CONTINUOUS, on_start_speak);if (rc != TC_IOT_ERR_SUCCESS) {goto cleanup;}wait_until(&s_start_done, 30000);if (!s_start_done || s_start_result != TC_IOT_ERR_SUCCESS) {goto cleanup;}speak_started = true;// 启动具体平台的麦克风采集流程。// 采集线程或回调中不要阻塞过久,按帧调用 on_mic_captured()。while (!s_aitalk_error && !is_exit_requested()) {// 使用具体平台的休眠、事件循环或任务调度机制。}conversation_completed = !s_aitalk_error;cleanup:// 先停止具体平台的麦克风采集和扬声器播放。if (speak_started) {tc_iot_aitalk_stop_speak();}if (aitalk_inited) {tc_iot_aitalk_deinit();}if (sdk_inited) {tc_iot_deinit();}return conversation_completed ? 0 : 1;}
注意:
常见问题
现象 | 排查建议 |
启动 AI 对话返回 -204 | 设备的 TWeTalk license 未激活,请确认已开通服务并完成设备 license 激活。 |
未收到机器人音频 | 确认 tc_iot_aitalk_start_speak 的回调已成功返回,且麦克风采集后持续调用了 tc_iot_aitalk_send_audio。 |
收到音频但没有声音 | 检查 on_receive_bot_audio 是否已将数据送入平台播放接口,并确认播放设备支持回调中的音频编码。 |
未触发联系人呼叫 | 确认在 tc_iot_aitalk_start_speak 前调用了 tc_iot_aitalk_register_contacts,且联系人信息有效。 |