生活物联网平台提供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和操作说明文档
邮件内容:
公司名称: 公司地址: 联系人: 联系电话: 应用场景描述:
我们给您提供Link Visual SDK时会一并提供配套版本的生活物联网平台SDK,您无需单独下载生活物联网平台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,用于处理视频相关命令,如直播命令等,并建立媒体通道,发送视音频数据。
这3个模块的功能之间的关系如下图所示(以直播数据转发为例)。
三、编译Link Visual SDK
配置环境。
编译依赖cmake等一些相关软件,这里以Ubuntu 16.04下安装编译环境为例。
$ sudo apt-get install -y build-essential make git gcc g++ cmake tree
编译cJSON。
进入third_party目录,并解压cJSON-1.7.7。
$ cd third_party # 解压代码压缩包 $ tar -xf cJSON-1.7.7.tar.gz $ cd cJSON-1.7.7
在Makefile文件中加入工具链的声明,并替换成对应的交叉编译工具链。
CC = arm-linux-gcc LD = arm-linux-ld AR = arm-linux-ar
编译cJSON,并确认是否生成了libcjson.a,以及头文件cJSON.h是否存在。
$ make # 确认libcjosn.a和相关头文件已存在 $ ls lib*.a $ ls *.h
编译libevent。
在third_party目录里解压libevent。
$ cd third_party # 解压代码压缩包 $ tar -xf libevent-2.1.8-stable.tar.gz
编译libevent。
$ cd libevent-2.1.8-stable # 配置编译条件,注意host和cc需要改为对应的交叉编译工具链信息,编译条件可根据自身需求调整 $ ./configure --host=arm-linux CC=arm-linux-gcc --enable-static --disable-samples --disable-openssl $ make # 编译 $ ls .libs/libevent.* # 确认是否有libevent.a生成
编译生活物联网平台SDK。
在third_party目录里解压ali-smartliving-device-sdk-c。
$ cd third_party $ tar -xf ali-smartliving-device-sdk-c-1.4.tar.gz; #解压代码压缩包 $ cd ali-smartliving-device-sdk-c
修改src/board/config.ubuntu.x86来准备交叉编译。
CROSS_PREFIX :=arm-linux- #在最后加上CROSS_PREFIX :=交叉编译工具链路径前缀(请替换成对应的交叉编译工具链)
选择Ubuntu编译,并确认生成库libiot_tls.a/libiot_sdk.a/libiot_hal.a。
# 这里选择ubuntu对应的数字,一般是数字6 $ make reconfig $ make # 确认有libiot_tls.a/libiot_sdk.a/libiot_hal.a $ ls output/lib/*.a # 确认有如iot_import.h等头文件 $ tree include
整理编译。
返回到SDK解压后的文件夹根目录,修改CMakeLists.txt里的TOOLCHAINS_PREFIX参数值。
set(TOOLCHAINS_PREFIX "arm-linux-" CACHE STRING "set the toolchain") #第二个参数设置为交叉编译工具链前缀(请替换成对应的交叉编译工具链)
执行编译操作。
# 建立一个build文件夹,用于归类编译产物 $ mkdir -p build # 进入build目录,使用根目录的CMakeLists.txt进行cmake $ cd build $ cmake .. # 编译并安装运行所需相关文件 $ make $ make install
编译(compilation)时,您可以添加
-std=c++11
来支持C++和C++11。链接(linking)时,您可以在链接选项中添加
-lstdc++
来支持C++和C++11。链接(linking)时,库的连接顺序为:link_visual_ipc、iot_sdk cjson、iot_hal、iot_tls pthread、rt。
运行设备。
# 运行方式和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介绍。