实时预览与对讲

更新时间:2024-06-25 05:50:43下载pdf

涂鸦 IPC 开发框架支持 P2P 实时预览WebRTC 预览 两种预览模式。

  • P2P 实时预览

    涂鸦实时预览与对讲,基于自研 P2P(Peer-to-peer)技术,建立设备和 App 之间点对点、安全加密的数据传输通路,实现了设备端音视频数据的实时预览和对讲功能。

  • WebRTC 预览

    WebRTC(Web Real-Time Communication),即网页即时通信技术。涂鸦支持 WebRTC 能力,能够与支持 WebRTC 的浏览器、音箱等建立连接,实时传输音视频数据。

技术原理

P2P

P2P 技术的出现,主要是为了解决,两台不同局域网下的设备,由于 NAT(网络地址转换)的存在,无法通过局域网 IP 地址,直连通信的问题。

P2P 通信的双方,通过标准的 STUN(Session Traversal Utilities for NAT))协议,向 STUN 服务器发送请求,获取自身的公网 IP。当通信的双方,获取到公网 IP 地址后,即可通过公网 IP 直连通信。

AppSTUN 服务器设备STUN 绑定请求1STUN 绑定回应2STUN 绑定请求3STUN 绑定回应4公网 IP 直连5AppSTUN 服务器设备对讲流程

然而,P2P 并不能穿透所有的 NAT,在部分 NAT 类型下,无法穿透成功,即无法直连通信。不同类型的 NAT,穿透性如下:

NAT 类型 全锥型 受限锥型 端口受限锥型 对称型
全锥型 可以 可以 可以 可以
受限锥型 可以 可以 可以 可以
端口受限锥型 可以 可以 可以 不可以
对称型 可以 可以 不可以 不可以

针对 P2P 直连无法穿透的场景,可以通过云端服务器进行转发。

云端转发
P2P直连
192.168.2.1地址
192.168.1.1地址
云端
192.168.1.120
P2P穿透
192.168.2.110

涂鸦自研 P2P 技术,在 P2P 传输通道上,对音视频数据进行了 AES 加密,保证了数据的安全传输。

WebRTC

WebRTC 基于已有的 P2P 技术,在 P2P 传输通道上,实现了安全的数据传输。

  • 第一阶段,通过 P2P 协议,创建数据传输通道。
  • 第二阶段,DTLS(Datagram Transport Layer Security)协议,是基于 UDP 之上的安全传输协议,通过 DTLS 协议,通信双方协商出用于数据传输的密钥。
  • 第三阶段,基于 DTLS 协商出的密钥,结合 SRTP(Secure Real-time Transport Protocol)安全实时传输协议,完成音视频数据的加密传输。
Web设备P2P 穿透1P2P 穿透2DTLS 协商3DTLS 协商成功4SRTP 实时数据传输5Web设备对讲流程

功能特性

  • 支持高标清切换,App 或 Web 端根据不同的视频分辨率切换高标清通道。
  • 支持双向对讲,设备端麦克风采集的音频发送给 App 或 Web 端,App 或 Web 端的对讲音频发送给设备后,通过设备端扬声器播放。
  • 支持状态通知,通过事件回调,将当前的实时预览状态通知给您,例如开始预览、结束预览、切换清晰度等。
  • 支持数据加密。
  • 支持通信双方身份验证,确保连接的合法性。

相关文件

  • tuya_ipc_media_adapter.h
  • tuya_ipc_media_stream.h
  • tuya_ipc_media_stream_event.h

功能接入流程

涂鸦的音视频业务,基本都涉及到网络、时间等基础业务,所以正常的音视频业务,需要等待 MQTT 上线以及同步到时间,然后才进行初始化启动。但是在低功耗设备上,MQTT 本身上线需要时间,在这个等待上线的阶段,可以将音视频的部分业务(不依赖网络的部分)先启动,以提升出流速度。

常供电设备

常供电设备一般采用涂鸦 Demo 中的示例流程,顺序启动即可。参考下图:

涂鸦 SDK 初始化
tuya_ipc_sdk_init
媒体抽象层初始化
tuya_ipc_media_adapter_init
tuya_ipc_media_adapter_set_media_info
环形缓冲区初始化
tuya_ipc_ring_buffer_init
涂鸦 SDK 启动
tuya_ipc_start_sdk
等待 MQTT 上线
获取到云端时间
音视频业务启动
tuya_ipc_media_stream_init

低功耗设备

低功耗设备设备可以创建单独的线程去启动音视频业务。参考下图:

涂鸦 SDK 初始化
tuya_ipc_sdk_init
媒体抽象层初始化
tuya_ipc_media_adapter_init
tuya_ipc_media_adapter_set_media_info
环形缓冲区初始化
tuya_ipc_ring_buffer_init
涂鸦 SDK 启动
tuya_ipc_start_sdk
音视频业务启动
tuya_ipc_media_stream_init

针对低功耗设备,未激活时,请勿提前启动音视频业务。音视频业务启动中,需要读取设备的一些激活信息,若读取失败,会导致后续的拉流失败,需要重启才能恢复。所以可以通过 tuya_ipc_get_register_status 判断当前是 E_IPC_ACTIVEATED 状态后才启动音视频业务。

功能设计介绍

App 实时预览设备画面,可以分为两个大部分:

  1. 连接建立

    主要在设备和 App 直接建立一个可用的网络链路,用于后续协议、数据的收发。

  2. 业务协议交互及音视频收发

    设备和 App 可以进行一些信令交互(开始预览、切换清晰度等),也可以进行音视频数据的收发。

下文按照一次 App 预览请求的流程顺序,介绍内部的一些设计思路和问题排查方式。

连接建立流程

此阶段对应于 App 上展示的 正在构建加密通道 阶段:

实时预览与对讲

App 和设备建立连接的大致流程如下:

App云服务MQTT 服务设备MQTT 上线,订阅对应的 MQTT协议号1MQTT 上线,订阅对应的 MQTT 协议号2拉取建立连接所需的配置信息3返回配置信息4MQTT 报文 1:请求建立同设备的连接5转发 MQTT 报文 16MQTT 报文2:回复连接建立请求7转发 MQTT 报文 28收集 IP 地址9收集 IP 地址10MQTT 报文 3:发送 App 的 IP 地址11转发 MQTT 报文 312MQTT 报文 4:发送 App 的 IP地址13转发 MQTT 报文 414尝试建立同设备的连接15尝试建立同 App 的连接16连接建立17App云服务MQTT 服务设备App 和设备建立连接流程

连接资源申请

每路 App 和设备的连接均会消耗内存资源和连接路数。以 Linux 为例,具体消耗情况如下:

连接方式 内存消耗 连接路数消耗
P2P 1MB 1
WebRTC 1.5MB 1

在音视频业务初始化时,您可以根据自己的硬件规格来设定同时支持的连接路数(一般建议 3~5 路为宜)和可供音视频业务消耗的内存大小。若超过以上限制,新建连接会被强制关闭。

  • 最大连接路数设置方式

    tuya_ipc_media_stream_init 时,设置参数 MEDIA_STREAM_VAR_T:max_client_num

  • 最大内存资源设置方式

    tuya_ipc_media_adapter_init 时,设置参数 TUYA_IPC_MEDIA_ADAPTER_VAR_T:available_media_memory

鉴权流程

App设备:信令线程连接数量管理判断会话数量是否超过限制,超过则关闭会话1鉴权过程发送鉴权信息2鉴权。若失败,则关闭会话3App设备:信令线程鉴权流程

因为音视频数据大部分涉及隐私,故 App 和设备建立连接后,会进行一次鉴权,保证此 App 用户有权限查看设备的视频。

鉴权需要以下两个关键信息,均由涂鸦 SDK 内部管理:

  • P2P 密码
  • 设备的激活信息

以上任一信息错误,均会导致鉴权失败,进而引起关闭会话。

音视频数据收发

此阶段对应于 App 上展示的 正在获取视频流 界面:

实时预览与对讲

连接建立,设备和 App 的交互主要有信令交互、数据收发等流程。

  • 信令交互。主要进行清晰度设置、预览开关、音频开关等。

    App设备:信令线程设备:数据收发线程设备:您的代码拉流指令交互设置清晰度1将 App 的操作回调通知到您2同步到数据收发线程3返回结果4预览开始5将 App 的操作回调通知到您6同步到数据收发线程7返回结果8开启伴音9将 App 的操作回调通知到您10同步到数据收发线程11返回结果12App设备:信令线程设备:数据收发线程设备:您的代码预览信令交互流程
  • 数据收发。根据信令的交互,向 App 发送对应的音视频数据。

    App设备:数据收发线程设备:环形缓冲区设备:您的代码前置:输入音视频数据将音视频数据放入环形缓冲区1loop预览数据发送根据分辨率,取对应通道的 I 帧2发送给 App3循环取音视频数据4发送给 App5loopApp设备:数据收发线程设备:环形缓冲区设备:您的代码数据收发流程
  • 对讲。将 App 对讲数据发送给设备,并由客户进行播放。

    App设备:信令线程设备:数据收发线程设备:您的代码对讲流程打开播放器1通知您的代码,打开播放器2返回结果3循环发送音频数据4回调给客户播放5异步播放音频,切勿阻塞6loop关闭播放器7通知您的代码,关闭播放器8返回结果9App设备:信令线程设备:数据收发线程设备:您的代码对讲流程

上面流程有两点需要关注:

  • App 预览时,建议提前往环形缓冲区放入音视频数据,否则会延缓出流速度
  • 播放对讲音频,请勿阻塞播放,保证快速返回,否则会导致接收 App 对讲音频异常

连接关闭

正常情况下,App 退出预览界面,会主动发起关闭会话的请求。还有一些异常情况,也会引起设备关闭会话:

  • 数据链路长时间无数据发送(20 分钟),触发僵尸检测,关闭会话。
  • P2P 链路无心跳数据(30 秒左右),触发网络断开,关闭会话。

连接资源的回收需要时间,App 上快速的退出预览,再进入,有可能会因为连接资源未完成回收,导致极短时间内多占用一路连接。

典型性能指标和异常

  • 出流速度

    通过大数据分析,常供电设备的出流速度基本在 2.5 秒左右。

  • 延迟

    此数据受网络影响较大。实验室数据分析,延迟一般在 250~400 毫秒之间。

  • 卡顿

    设备 SDK 和 App 均采用多个缓冲区,来对抗网络的抖动,保证播放流畅性。在网络抖动较大或者网络较差时,可能会有卡顿现象。

  • 跳帧

    若设备的码率大于设备与 App 之间的带宽,会导致数据堆积,此时会发生跳帧现象。当临时的网络变差,导致数据发送较慢时,也会发生此现象。

  • 花屏

    涂鸦 SDK 内部采用多种算法,对抗网络丢包,保证传输的可靠性。在您的音视频数据正常的情况下,App 预览不会发生花屏现象。Web 端采用 WebRTC 框架,在网络较差,丢包严重的情况下,可能会有花屏出现。

音视频数据要求

  • 视频

    建议分辨率和编码等级(Profile)与对应的编码格式(H264、H265 等)要求匹配,否则在某些性能较低的手机上,会因为资源不足,而产生解码异常。

  • 音频

    每次送入的音频数据大小不可超过 800 字节

  • 时间 PTS

    若在放入环形缓冲区前,提供了 PTS,请使用微秒时间。

故障排查

连接失败

可以根据如下现象来判断连接失败:

  • App 上显示构建加密通道失败
  • 设备日志(DEBUG 级别)没有 listen ok 或者 __p2p_deal_with_listen 的日志打印。

在排查问题前,需要先了解如何识别上述 MQTT 消息:

  • 如何判断设备收到 MQTT 消息

    设备日志(DEBUG 级别)中存在 Rev MQTT: "的打印,后面的内容即为 MQTT 消息内容。

  • 如何判断收到的 MQTT 消息是 App 发出的建立连接需要的报文

    MQTT 消息中,存在 "protocol":302 的打印,意为 302 号 MQTT 消息。302 号 MQTT 消息是流媒体使用的协议。

  • 如何判断设备是否发出去建立连接需要的 MQTT 报文

    设备日志(DEBUG 级别)中存在 Send MQTT Msg.P:302 的打印

然后参考 连接建立流程 步骤序号,按照以下步骤排查:

  1. MQTT 链路是否通畅,排查是否有 MQTT 消息的交互

    App 或者设备 MQTT 不通,会导致后续的所有 MQTT 报文无法交互。

  2. 第 3 步是否拿到连接配置信息

    此处需要依赖 App 日志排查,也可以简单根据是否走到第 5 步来确认。

  3. 设备是否收到连接请求报文(第 5 步和第 6 步是否正常)

    连接请求的 MQTT 消息一般会比较长,导致无法完全打印。可以是否收到包含 tcp_token"、 tokensdp` 等字段的 302 号 MQTT 消息。

  4. 设备是否发出连接请求回复报文(第 7 步是否正常)

    可以查看设备是否发出去了 302 号 MQTT 协议,其中包含 "type":"answer""tcp_token"sdp等字段。

  5. 设备是否收到了 App 的 IP 地址(第 11 步和第 12 步是否正常)

    查看设备是否收到了包含 "type":"candidate" 302 号 MQTT 协议。

  6. 设备是否发出去了自己的 IP 地址(第 13 步是否正常)

    查看设备是否发出了包含 "type":"candidate" 302 号 MQTT 协议。

  7. 若以上步骤均无问题,请 提交工单 联系涂鸦排查问题。

会话满

可以根据设备日志来判断会话满

  • 设备日志出现 incoming connection refused 或者 alloc resource failed 或者 no value able session please check process

  • App 提示设备忙线

    会话路数管理,基本不受您的代码影响,若频繁出现,可以按照以下顺序处理:

    • 是否存在其他设备在拉流,计算下拉流数量是否超过限制,若是,则为正常,否则往下继续排查。
    • 是否是智能生活 App,若不是,则建议使用智能生活 App 进行复现。
    • 智能生活 App 频繁出现路数满,联系涂鸦的技术人员排查。

鉴权失败

可以根据如下现象来判断鉴权失败:

  • 设备日志打印 auth failed
  • App 日志中出现错误码 -105

排查方向:

  1. 是否收到鉴权信息

    若设备日志中,出现 get userinfo timeout 或者 get userinfo error ,说明接收 App 鉴权信息出错。

  2. 设备本地维护的 P2P 密码是否正确

    设备日志中(DEBUG 级别)出现 get p2p passwd =,后面的字符串即为 P2P password(此字段仅用于设备和 App 的鉴权,且仅为鉴权所需的部分信息,无需担心日志泄露造成安全隐患)。若此字段不以 ad 开头,则为错误密码。P2P password 出现错误,需要排查设备 DB 文件是否正常。

  3. App 清除缓存后,重试是否恢复

    App 可能会使用缓存的 P2P 密码或者设备激活信息,用来鉴权。删除缓存后,使用云端提供的信息,如果能成功,则需要排查 App 的缓存策略是否符合当前场景要求。

数据收发失败

当 App 长时间处于 正在获取视频流 界面,最终提示 获取视频流失败 时,一般是信令交互或者数据收发出现了问题。

参考 音视频业务流程,按照以下步骤排查:

  1. 信令是否正确

    可以通过音视频服务的事件回调来判断当前收到了哪些指令,例如开始拉流、开启伴音等。指令为枚举型 MEDIA_STREAM_EVENT_E,可以参考名称定义来确定其功能。

  2. 数据发送线程是否正常

    设备日志(DEBUG 级别)是否周期打印 media send proc alive,若有周期性打印,说明线程工作正常。

  3. 环形缓冲区数据读取是否正常

    观察设备日志(DEBUG 级别),是否突然出现大量 tuya_ring_buffer.c 文件中的打印,若存在打印,说明音视频数据放入环形缓冲区有问题。

  4. 发送帧数量统计是否变化

    观察设备日志(DEBUG 级别)是否周期性打印 session send video cnt (发送视频帧数量)和 session send audio cnt (发送音频数量),若数量持续增加,说明在正常发送数据。

  5. 若以上步骤均无问题,请 提交工单 联系涂鸦排查问题。

常见问题

App 预览时,为什么一直显示构建加密通道,无法出流?

  • 设备 MQTT 可能离线,设备未收到 App 的连接请求。
  • 设备或 App 网络问题。

App 预览时,为什么构建加密通道立刻报错,提示 设备忙线 错误?

同时预览的连接数量,已达到 tuya_ipc_media_stream_init 接口设置的最大值 max_client_num

App 预览时,为什么一直在获取视频流转圈,无法出流?

  • 音视频编码参数设置错误,与实际值不一致,请检查 tuya_ipc_media_adapter_set_media_info 接口设置的参数。
  • 环形缓存 ring buffer 未塞入音视频流。
  • 设备网络较差。

App 预览时,视频为什么卡顿?

  • 设备网络较差。
  • 环形缓存 ring buffer 塞入的音视频时间戳存在问题,timestamp 时间戳要求毫秒量级,pts 时间戳要求微秒量级。

App 预览时,为什么出流速度很慢?

  • 低功耗设备,确认下系统启动时间是否太慢
  • 低功耗设备,确认下 P2P 启动是否太晚
  • 低功耗设备,确认下 mqtt 上线是否太慢
  • 环形缓冲区数据是否已提前放入视频数据

如何判断设备开始和结束预览?

  • MEDIA_STREAM_EVENT_CB 回调产生 MEDIA_STREAM_LIVE_VIDEO_START事件,表示预览开始。
  • MEDIA_STREAM_EVENT_CB 回调产生 MEDIA_STREAM_LIVE_VIDEO_STOP事件,表示预览结束。

IOS,直接杀掉 App 进程,设备无法即时感知预览结束?

App 上正常退出预览时,App 向设备发送关闭连接请求,设备收到 MEDIA_STREAM_LIVE_VIDEO_STOP 预览结束事件。IOS 上直接杀掉 App 进程,App 不会向设备发送关闭连接请求,需要等待设备心跳超时,超时时间大约 1~2 分钟。

为什么 WebRTC 无法播放音频?

  • WebRTC 对音频编码方式存在限制,只支持 PCM 和 G711U 格式。
  • WebRTC 对音频采样率存在限制,PCM 格式支持 8K 和 16K,G711U 只支持 8K 采样率。
  • PCM 格式,音频帧大小设置为 640 字节,G711U 格式,音频帧大小设置为 320 字节。

设备如何区分 App 预览和 WebRTC 预览?

MEDIA_STREAM_LIVE_VIDEO_START 预览开始事件中,通过C2C_TRANS_CTRL_VIDEO_START 结构体中的 type字段区分:

  • type = TRANSFER_SOURCE_TYPE_P2P,表示 App 预览。
  • type = TRANSFER_SOURCE_TYPE_WEBRTC,表示 WebRTC 预览。

Web 端预览时,为什么开启对讲按钮,设备端未收到对讲数据?

检查一下 Web 端,是否打开麦克风权限。