生活物联网平台提供Linux版本的Link Visual设备端SDK,您可以基于该SDK开发Link Visual视频设备的直播、点播、语音对讲、抓图等功能。
前提条件
- 请您先完成Link Visual Demo体验,以提前熟悉整体流程。体验Link Visual请参见快速体验Link Visual。
- 已完成生活物联网平台SDK的开发。这部分请参见开发指导。
背景信息
Linux版本的Link Visual SDK的资源占用、平台支持和运行依赖如下。
项目 | 限制条件 |
---|---|
资源占用情况 |
|
平台支持 | 目前只能在支持C++11标准(GCC版本4.8.1以上)的Linux平台中使用。 |
运行依赖 | 依赖生活物联网平台SDK,您需要同时获取Link Visual SDK和生活物联网平台SDK来完成设备接入。
|
一、获取Link Visual SDK
Linux版本的Link Visual设备端SDK以静态库的形式提供,支持通过编译SDK接入不同芯片的设备,需要您发送邮件申请。
请按以下模板发送邮件至fangyu.hfy@alibaba-inc.com联系我们获取Link Visual设备端SDK。收到邮件后,我们会在收到邮件后的5个工作日内联系您。
- 邮件主题:获取固件升级SDK和操作说明文档
- 邮件内容:
公司名称: 公司地址: 联系人: 联系电话: 应用场景描述:
二、了解SDK目录结构及Demo源码
在开发Link Visual SDK前,建议您先了解整个SDK目录结构以及Link Visual Demo的源码,可以帮助您快速熟悉整个开发流程。
- 了解SDK目录结构
解压获取到的Link Visual SDK压缩包,并查看压缩包的内容。
# 解压压缩包,并查看压缩包内容(注:压缩包文件名含有版本等可变信息,执行命令时以实际压缩包名称为准) $ tar -xf link_visual_ipc_vxxx.tar.gz $ tree -L 2 link_visual_ipc_vxxx ├── CMakeLists.txt #基于cmake的编译的基础示例 ├── linkvisual # lv库和头文件 │ ├── liblink_visual_ipc.a # lv库(注:实际压缩包可能含有动态库) │ ├── link_visual_def.h # lv头文件 │ └── link_visual_ipc.h # lv头文件 ├── sample # 示例代码 │ ├── demo.c # 示例代码的入口文件 │ ├── demo.h # 示例代码的入口头文件 │ ├── ipc_operation # 示例伪造了ipc的功能,相关实现文件 │ └── sdk_api_operation # 示例中lv sdk的相关实现文件 ├── third_party # 三方库 │ ├── cJSON-1.7.7.tar.gz # JSON解析库,使用版本为1.7.7 │ ├── libevent-2.1.8-stable.tar.gz # libevent,使用版本为2.1.8 │ └── linkkit-sdk-c.tar.gz # 生活物联网平台SDK,提供生活物联网平台接入能力 └── version.txt # 版本说明
- 了解Demo源码
Link Visual Demo的下载请参见快速体验Link Visual。
# 代码取自文件 sample/demo.c int main(int argc, char* argv[]) { char product_key[PRODUCT_KEY_LEN + 1] = {0}; char device_name[DEVICE_NAME_LEN + 1] = {0}; char device_secret[DEVICE_SECRET_LEN + 1] = {0}; char product_secret[PRODUCT_SECRET_LEN + 1] = {0}; int ret = 0; #ifdef DUMMY_IPC /* 0.初始化虚拟IPC的功能 */ ret = dummy_ipc_start(&dummy_ipc_config); #endif // DUMMY_IPC /* 1. 初始化LinkVisual的资源 */ ret = linkvisual_client_init(product_key, device_name, device_secret, (lv_log_level_e) log_level); /* 2. 初始化linkkit的资源,并长连接到服务器 */ ret = linkkit_client_start(product_key, product_secret, device_name, device_secret); /* 3. 运行,等待服务器命令 */ while(1) { usleep(1000 * 500); } /* 4. linkkit长连接断开,并释放资源 */ linkkit_client_destroy(); /* 5. LinkVisual断开音视频连接,并释放资源 */ linkvisual_client_destroy(); #ifdef DUMMY_IPC /* 停止虚拟IPC的功能 */ dummy_ipc_stop(); #endif // DUMMY_IPC return 0; }
如上述代码所示,设备端Link Visual Demo共完成了3个模块的功能。- 启动了一个虚拟IPC,用于模拟IPC的出流功能。这部分功能仅用于测试,您无需过多关注其实现原理、细节等,实际产品中您需要替换成实际的IPC出流功能。
- 启动了生活物联网平台SDK,建立信令通道,用于接收各类命令,如直播命令等。此外配网、OTA等功能,也属于生活物联网平台SDK功能范畴。
- 启动了视频服务SDK,用于处理视频相关命令,如直播命令等,并建立媒体通道,发送视音频数据。
三、编译Link Visual SDK
- 配置环境。
编译依赖cmake等一些相关软件,这里以Ubuntu 16.04下安装编译环境为例。
$ sudo apt-get install -y build-essential make git gcc g++ cmake tree
- 编译cJSON。
- 编译libevent。
- 编译生活物联网平台SDK。
- 整理编译。
- 运行设备。
# 运行方式和Ubuntu Demo或Docker Demo类似,传入设备的激活凭证信息 $ ./link_visual_demo -p your_product_key -n your_product_name -s your_product_secret
四、API简述
由于Link Visual SDK依赖与生活物联网平台SDK,开发Link Visual SDK前,请确认已完成生活物联网平台SDK的开发。请参见开发指导。
- 生命周期功能
生命周期相关的API如下。
功能说明 API名称 SDK初始化 lv_init SDK停止 lv_destroy - SDK动态开关等其他功能
功能说明 API名称 生活物联网平台SDK消息注入 lv_linkkit_adapter SDK功能动态控制 lv_control - 直播、卡录像点播、云存等功能
功能说明 API名称 通知直播、点播服务已开启 lv_start_push_streaming_cb 通知直播、点播服务已结束 lv_stop_push_streaming_cb 推送视音频配置参数 lv_stream_send_config 推送视频数据 lv_stream_send_video 推送音频数据 lv_stream_send_audio 推流过程中命令控制(暂停等) lv_on_push_streaming_cmd_cb 点播的文件列表查询 lv_query_storage_record_cb 点播的文件列表按月查询 lv_query_storage_record_by_month_cb 录像文件播放结束 lv_post_file_close 预录数据结束 lv_post_pre_complete - 抓图功能
功能说明 API名称 图片上传 lv_post_alarm_image 通知上传图片 lv_trigger_pic_capture_cb - 语音对讲功能
功能说明 API名称 通知开启服务 lv_start_voice_intercom_cb 通知结束服务 lv_stop_voice_intercom_cb 开启服务 lv_voice_intercom_start_service 停止服务 lv_voice_intercom_stop_service 发送音频 lv_voice_intercom_send_audio 接收音频 lv_voice_intercom_receive_data_cb 接收音频参数配置 lv_voice_intercom_receive_metadata_cb
五、API详述-SDK生命周期
SDK生命周期管理相关的API如下。
- lv_init
接口名称 接口详情 描述 lv_init int lv_init(const lv_config_s *config) SDK初始化,该接口的使用说明如下。 - lv_init主要完成各个IPC功能的回调,以及一些配置类信息。
- lv_init会打印相关版本号信息,便于您追溯问题。
- 初始化失败时,一般不会与网络有关,请优先检查入参是否正确或者资源分配是否成功。
- lv_init注册了大量的回调函数,这些回调函数共用一个消息队列线程,因此建议您不要在回调中做过于耗时的操作。
- lv_init定义了日志类型log_level,建议对接初期将日志类型设置为LV_LOG_DEBUG。
- 推荐您在调用lv_init成功后再调用IOT_Linkkit_Connect。
请求参数说明如下。
参数 类型 说明 config lv_config_s* 配置参数结构体。 示例代码如下。
//新建一个配置结构体,并置空 lv_config_s config; memset(&config, 0, sizeof(lv_config_s)); //以下是设置具体的配置属性 //设备证书(ProductKey、DeviceName、DeviceSecret) memcpy(config.product_key, product_key.c_str(), product_key.length()); memcpy(config.device_name, device_name.c_str(), device_name.length()); memcpy(config.device_secret, device_secret.c_str(), device_secret.length()); //SDK的日志配置 config.log_level = LV_LOG_DEBUG; config.log_dest = LV_LOG_DESTINATION_STDOUT; //config.log_dest_file; //音视频推流服务 config.start_push_streaming_cb = startPushStreamingCallback; config.stop_push_streaming_cb = stopPushStreamingCallback; config.on_push_streaming_cmd_cb = onPushStreamingCmdCb; //语音对讲服务 config.start_voice_intercom_cb = startVoiceIntercomCallback; config.stop_voice_intercom_cb = stopVoiceIntercomCallback; config.voice_intercom_receive_metadata_cb = voice_intercom_receive_metadata_cb; config.voice_intercom_receive_data_cb = VoiceIntercomReceiveDataCallback; //获取存储录像列表 config.query_storage_record_cb = queryStorageRecordCallback; //触发设备抓图 config.trigger_pic_capture_cb = triggerPicCaptureCallback; //触发设备录像 config.trigger_record_cb = triggerRecordCallback; //初始化SDK,失败则退出 int ret = lv_init(&config); if (ret < 0) { return -1; }
- lv_destroy
接口名称 接口详情 描述 lv_destroy int lv_destroy(void); SDK销毁,该接口的使用说明如下。 - 推荐在调用lv_destroy前调用IOT_Linkkit_Close。
- 调用lv_destroy时,耗时会高达数秒。在正常的业务逻辑内,不建议您反复调用lv_destroy。
无请求参数。
示例代码如下。
//运行结束后 lv_destroy();
六、API详述-视频播放功能
视频播放分为直播、卡录像点播、云储存播放,在视音频数据传输的过程,SDK采用了同一套API来实现视频播放。相关API如下。
- lv_start_push_streaming_cb
接口名称 接口详情 描述 lv_start_push_streaming_cb typedef int (lv_start_push_streaming_cb)(int service_id, lv_stream_type_e type, const lv_stream_param_s *param) 回调函数,通知视频播放链路已经建立成功,并附带一些配置信息。收到此回调后,您应该根据配置信息初始化编码器,并开始推送音视频数据。 请求参数说明如下。
参数 类型 说明 service_id int 链路的ID。 type lv_stream_type_e 链路的类型,分为直播和卡录像点播。 param const lv_stream_param_s* 链路的参数,例如卡录像要点播的文件名称。 示例代码如下。
//demo,定义了回调函数start_push_streaming_cb作为lv_start_push_streaming_cb的实现 lv_start_push_streaming_cb = start_push_streaming_cb; //demo,回调函数startPushStreamingCallback int start_push_streaming_cb(int service_id, lv_stream_type_e cmd_type, const lv_stream_param_s *param) { if (cmd_type == LV_STREAM_CMD_LIVE) { //使用lv_stream_send_video/lv_stream_send_audio推送音视频数据; //实际使用中建议新建线程进行数据发送 ...... return 0; } else if (cmd_type == LV_STREAM_CMD_STORAGE_RECORD_BY_FILE) { //使用lv_stream_send_video/lv_stream_send_audio推送音视频数据 //实际使用中建议新建线程进行数据发送 ...... return 0; } return 0; }
- lv_stop_push_streaming_cb
接口名称 接口详情 描述 lv_stop_push_streaming_cb typedef int (*lv_stop_push_streaming_cb)(int service_id) 回调函数,通知视频播放链路已经断开。收到此回调后,您应该停止推送音视频数据。 请求参数说明如下。
参数 类型 说明 service_id int 链路的ID。 示例代码如下。
//demo,定义了回调函数stop_push_streaming_cb作为lv_start_push_streaming_cb的实现 lv_stop_push_streaming_cb = stop_push_streaming_cb; //demo,回调函数stop_push_streaming_cb int stop_push_streaming_cb(int service_id) { if (service_id == g_live_service_id) { //您停止推流 } else if (service_id == g_storage_record_service_id) { //您停止推流 } return 0; }
- lv_on_push_streaming_cmd_cb
接口名称 接口详情 描述 lv_on_push_streaming_cmd_cb typedef int (*lv_on_push_streaming_cmd_cb)(int service_id, lv_on_push_streaming_cmd_type_e cmd, const lv_on_push_streaming_cmd_param_s *param) 回调函数,通知视频播放链路建立期间,可以进行一些命令控制,例如要求发送I帧命令。 请求参数说明如下。
参数 类型 说明 service_id int 链路的ID。 cmd lv_on_push_streaming_cmd_type_e 控制命令,目前有开始播放、停止播放、暂停播放、恢复播放、定位、强制I帧。 param lv_on_push_streaming_cmd_param_s * 参数值和lv_on_push_streaming_cmd_type_e有关 示例代码如下。
//demo,定义了回调函数on_push_streaming_cmd_cb作为lv_on_push_streaming_cmd_cb的实现 on_push_streaming_cmd_cb = on_push_streaming_cmd_cb; int on_push_streaming_cmd_cb(int service_id, lv_on_push_streaming_cmd_type_e cmd, const lv_on_push_streaming_cmd_param_s *param) { if (cmd == LV_STORAGE_RECORD_START) { //卡录像开始推流 } else if (cmd == LV_STORAGE_RECORD_STOP) { //卡录像停止推流 } else if (cmd == LV_STORAGE_RECORD_PAUSE) { //卡录像暂停推流 } else if (cmd == LV_STORAGE_RECORD_UNPAUSE) { //卡录像恢复推流 } else if (cmd == LV_STORAGE_RECORD_SEEK) { //卡录像定位到某一段 } else if (cmd == LV_LIVE_REQUEST_I_FRAME) { //对于直播,需要强制生成一个I帧 } return 0; }
- lv_stream_send_config
接口名称 接口详情 描述 lv_stream_send_config int lv_stream_send_config(int service_id, unsigned int bitrate_kbps, double duration, const lv_video_param_s *video_param, const lv_audio_param_s *audio_param) 配置发送音视频的参数。 请求参数说明如下。
参数 类型 说明 service_id int 链路的ID。 bitrate_kbps unsigned int 链路的码流,设置的码流越大,内部音视频数据缓冲区越大。 duration double 文件时长,卡录像点播有效。 video_param const lv_video_param_s* 视频的参数集。 audio_param const lv_audio_param_s* 音频的参数集。 示例代码如下。
lv_video_param_s video_param; memset(&video_param, 0, sizeof(lv_video_param_s)); video_param.format = LV_VIDEO_FORMAT_H264; video_param.fps = 25; lv_audio_param_s audio_param; memset(&audio_param, 0, sizeof(lv_audio_param_s)); audio_param.format = LV_AUDIO_FORMAT_G711A; audio_param.channel = LV_AUDIO_CHANNEL_MONO; audio_param.sample_bits = LV_AUDIO_SAMPLE_BITS_16BIT; audio_param.sample_rate = LV_AUDIO_SAMPLE_RATE_8000; lv_stream_send_config(service_id, 1000, 0, &video_param, &audio_param);
- lv_stream_send_video
接口名称 接口详情 描述 lv_stream_send_video int lv_stream_send_video(int service_id, lv_video_format_e format,unsigned char* buffer, unsigned int buffer_len, bool key_frame, unsigned int timestamp_ms) 发送视频数据。 请求参数说明如下。
参数 类型 说明 service_id int 链路的ID。 format lv_video_format_e 视频编码类型 buffer unsigned char* 视频的数据。 buffer_len unsigned int 视频的数据长度。 key_frame bool 是否为关键帧。I帧为关键帧,P帧为非关键帧,不接受B帧。 timestamp_ms unsigned int 视频的时间戳。 示例代码如下。
//demo,这个函数回调输入视频帧数据 void linkvisual_client_video_handler(int service_id, lv_video_format_e format, unsigned char *buffer, unsigned int buffer_size, unsigned int present_time, int nal_type) { lv_stream_send_video(service_id, format, buffer, buffer_size, nal_type, present_time); }
- lv_stream_send_audio
接口名称 接口详情 描述 lv_stream_send_audio int lv_stream_send_audio(int service_id, lv_audio_format_e format,unsigned char* buffer, unsigned int buffer_len, unsigned int timestamp_ms) 发送音频数据。 请求参数说明如下。
参数 类型 说明 service_id int 链路的ID。 format lv_audio_format_e 音频编码类型 buffer unsigned char* 音频的数据。 buffer_len unsigned int 音频的数据长度。 timestamp_ms unsigned int 音频的时间戳。 示例代码如下。
//demo,这个函数回调输入音频帧数据 void linkvisual_client_audio_handler(int service_id, lv_audio_format_e format, unsigned char *buffer, unsigned int buffer_size, unsigned int present_time) { lv_stream_send_audio(service_id, format, buffer, buffer_size, present_time); }
- lv_query_storage_record_cb
接口名称 接口详情 描述 lv_query_storage_record_cb typedef void (lv_query_storage_record_cb)(unsigned int start_time, unsigned int stop_time, int num, const char *id, int (on_complete)(int num, const char *id, const lv_query_storage_record_response_s *response)) 回调函数,查询卡录像的文件信息。 请求参数说明如下。
参数 类型 说明 start_time unsigned int 查询录像的开始时间。 stop_time unsigned int 查询录像的结束时间。 num int 录像数量小于等于0的时候表示已查询全部的录像。 id const char * 查询的会话ID,需要回传。 on_complete 函数指针 将查询结果通过该函数同步返回。 示例代码如下。
int dummy_ipc_report_vod_list(unsigned int start_time, unsigned int stop_time, int num, const char *id, int (*on_complete)(int num, const char *id, const lv_query_storage_record_response_s *response)) { int answer_num = g_vod_media_file_group.size(); auto *response = new lv_query_storage_record_response_s[answer_num]; memset(response, 0, sizeof(lv_query_storage_record_response_s) * answer_num); double duration = 0; for (int i = 0; i < answer_num; i ++) { MediaParse::GetDuration(g_vod_media_file_group[i], duration); response[i].file_size = 0; response[i].record_type = LV_STORAGE_RECORD_INITIATIVE; snprintf(response[i].file_name, 64, g_vod_media_file_group[i].c_str(), i);//注意不要溢出 if (i == 0) { response[i].start_time = (int)start_time; response[i].stop_time = (int)start_time + (int)duration; } else { response[i].start_time = response[i - 1].stop_time; response[i].stop_time = response[i - 1].stop_time + (int)duration; } } int result = on_complete(answer_num, id, response); printf("dummy_ipc_report_vod_list result: %d\n", result); delete[] response; return 0; }
- 直播流程图
- 卡录像点播流程图
- 预录事件点播流程图
- 云存
云存分为事件触发云存和连续云存两种场景。您基于SDK实现直播功能即可同时实现云存功能,无需您额外开发。
视频播放功能的接口调用说明如下。
- 强制I帧命令发出时,为了保证尽可能快速的发出I帧,您应尽可能快的产生I帧,建议在300毫秒(ms)内完成
- 强制I帧命令发出时,您需要重新调用lv_stream_send_config发送流配置。
- 进行卡录像的定位操作时,为了尽可能快速的显示定位后的数据,您在定位操作后,应该尽可能快速的发出I帧,同时SDK在定位操作后也不在接收音频数据和视频的P帧数据,直到I帧到达。
- H264/H265的帧结构会有一定的要求,可以打印I帧的前256个字节进行查看,打印代码如下。
for (int i = 0; i < ((buffer_size > 256)?256:buffer_size); i++) { printf("%02x ", buffer[i]); if ((i + 1) % 30 == 0) { printf("\n"); } } printf("\n");
H264要求I帧为:
帧分隔符+SPS+帧分隔符+PPS+帧分隔符+IDR
。如下图所示。0x000001或者0x00000001是帧分隔符,0x67是SPS的开始,0x68是PPS的开始,0x65是IDR的开始。
H265要求I帧为:
帧分隔符+VPS+帧分隔符+SPS+帧分隔符+PPS+帧分隔符+IDR
,如下图所示。说明 音频目前支持G711A/LC-AAC编码方式,编码参数的支持需要参考头文件link_visual_def.h中的宏定义值。同一路流切换视频码流时(如主码流切为子码流、修改码流分辨率、H264/H265切换等),请保证切换后的第一帧为I帧,否则会引发花屏等现象。
七、API详述-图片服务
图片服务相关的API如下。
- lv_trigger_pic_capture_cb
接口名称 接口详情 描述 lv_trigger_pic_capture_cb typedef int (lv_trigger_pic_capture_cb)(const char *id) 通知设备开始抓取图片。 请求参数说明如下。
参数 类型 说明 id const char * 本次请求的ID,需要回传。 - lv_post_alarm_image
接口名称 接口详情 描述 lv_post_alarm_image int lv_post_alarm_image(const char *buffer, int buffer_len, lv_event_type_e type, const char *id) 发送图片和报警事件,适用于抓图回调后进行上报,或者设备主动发起上报。 请求参数说明如下。
参数 类型 说明 buffer const char * 图片数据。 buffer_len int 图片数据长度。 type lv_event_type_e 上报类型,分为抓图回调后进行上报和设备主动发起上报。 id const char * 抓图回调的ID回传,主动上报时传空字符串或者NULL。
抓图功能分为App端触发抓图请求和事件侦测触发设备端主动抓图两种场景。

调用图片服务相关接口的说明如下。
- 上传的最大图片大小为1MB。
- 图片上传的最小间隔为1秒,频繁触发的图片将会被丢弃。
- 图片会由SDK内部保存一份拷贝,并形成待发送的图片队列。图片队列的长度为5,在网络差的情况下,图片队列可能会满,满队列后新生成的图片将会被丢弃。
- SDK不限制图片的格式,只要云端或者从云端拉取图片的设备能够支持解析即可。推荐使用常见的图片格式,如,jpg格式。
八、API详述-语音对讲服务
语音对讲服务相关的API如下。
- lv_start_voice_intercom_cb
接口名称 接口详情 描述 lv_start_voice_intercom_cb typedef int (*lv_start_voice_intercom_cb)(int service_id) 回调函数,返回一路语音对讲服务链路已可以建立的通知。 请求参数说明如下。
参数 类型 说明 service_id int 链路的ID。 - lv_voice_intercom_start_service
接口名称 接口详情 描述 lv_voice_intercom_start_service int lv_voice_intercom_start_service(int service_id, const lv_audio_param_s *audio_param) 建立一路语音对讲链路,在收到语音对讲开始的回调后,调用该接口。 请求参数说明如下。
参数 类型 说明 service_id int 链路的ID。 audio_param const lv_audio_param_s * 设备的音频参数结构体。 示例代码如下。
//demo,start_voice_intercom_cb是lv_start_voice_intercom_cb的实际实现 lv_start_voice_intercom_cb = start_voice_intercom_cb; int start_voice_intercom_cb(int service_id) { //收到开始语音对讲请求时,主动开启对讲服务 lv_audio_param_s audio_param; memset(&audio_param, 0, sizeof(lv_audio_param_s)); audio_param.format = LV_AUDIO_FORMAT_G711A; audio_param.channel = LV_AUDIO_CHANNEL_MONO; audio_param.sample_bits = LV_AUDIO_SAMPLE_BITS_16BIT; audio_param.sample_rate = LV_AUDIO_SAMPLE_RATE_8000; int ret = lv_voice_intercom_start_service(service_id, &audio_param); return 0; }
- lv_stop_voice_intercom_cb
接口名称 接口详情 描述 lv_stop_voice_intercom_cb typedef int (*lv_stop_voice_intercom_cb)(int service_id) 回调函数,返回一路语音对讲服务链路已可以断开的通知。 请求参数说明如下。
参数 类型 说明 service_id int 链路的ID。 - lv_voice_intercom_stop_service
接口名称 接口详情 描述 lv_voice_intercom_stop_service int lv_voice_intercom_stop_service(int service_id) 断开一路语音对讲链路,在收到语音对讲结束的回调后,调用该接口。 请求参数说明如下。
参数 类型 说明 service_id int 链路的ID。 示例代码如下。
//demo,stop_voice_intercom_cb是lv_start_voice_intercom_cb的实际实现 lv_stop_voice_intercom_cb = stop_voice_intercom_cb; int stop_voice_intercom_cb(int service_id) { lv_voice_intercom_stop_service(service_id); }
- lv_voice_intercom_receive_metadata_cb
接口名称 接口详情 描述 lv_voice_intercom_receive_metadata_cb typedef int (lv_voice_intercom_receive_metadata_cb)(int service_id, const lv_audio_param_s *audio_param) 回调函数,通知语音对讲时,App发送的音频参数格式。 请求参数说明如下。
参数 类型 说明 service_id int 链路的ID。 audio_param const lv_audio_param_s * APP发送的音频格式结构体。 - lv_voice_intercom_receive_data_cb
接口名称 接口详情 描述 lv_voice_intercom_receive_data_cb typedef void (lv_voice_intercom_receive_data_cb)(const char *buffer, unsigned int buffer_len) 回调函数,语音对讲时,App发送的音频数据。 请求参数说明如下。
参数 类型 说明 buffer const char * APP发送的音频数据。 buffer_len int APP发送的音频数据长度。 - lv_voice_intercom_send_audio
接口名称 接口详情 描述 lv_voice_intercom_send_audio int lv_voice_intercom_send_audio(int service_id, const char *buffer, int buffer_len , unsigned int timestamp_ms) 向其中一路语音对讲链路发送音频数据。 请求参数说明如下。
参数 类型 说明 service_id int 链路的ID。 buffer const char * 设备音频数据。 buffer_len int 设备音频数据长度。 timestamp_ms unsigned int 设备音频时间戳。 示例代码如下。
void linkvisual_client_audio_handler(int service_id, lv_audio_format_e format, unsigned char *buffer, unsigned int buffer_size, unsigned int present_time) { lv_voice_intercom_send_audio(g_voice_intercom_service_id, buffer, buffer_size, present_time); }
语音对讲流程图如下:

九、后续操作
生成设备固件后,您可以将固件烧录到设备中,并使用App调试Link Visual功能。建议您直接使用公版App来调试。公版App的下载请参见云智能App介绍。