三个关键组成部分,一个目标
从技术底层来看,Timmy 的设计很务实: Flutter 用于应用本身, WebRTC 用于实时音视频,以及 Firebase 用于协调。 我不想搭建一个让所有内容都经过云端的大型平台。每个部分掌握的信息都应尽可能少,同时又能与其他部分可靠协作。
WebRTC:默认加密的直连方式
WebRTC(Web 实时通信)负责在宝宝端和家长端设备之间传输音频和视频。 理想情况下,数据会 直接在两台设备之间传输,采用点对点方式,中间不经过媒体服务器。
每个 WebRTC 连接默认都会使用 DTLS-SRTP。即使有人截获网络数据包,也无法读出音频或视频内容。这种加密是协议的一部分,不能在 WebRTC 中随意关闭。
对我来说,这一点很重要:婴儿房的音视频不该传到我的服务器,而应只在你的设备之间传输。
通过 Firebase Firestore 进行信令
在 WebRTC 启动前,两台设备需要先找到彼此,并协商如何建立连接。 这一过程称为 信令。Timmy 为此使用 Google 的云数据库 Firebase Firestore。
交换的只有技术连接数据:
- SDP 提议和应答: 说明设备的能力,例如支持的编解码器、分辨率等。
- ICE 候选项: 设备之间可用于互相连接的网络路径。
音频和视频不会进入 Firebase。Firestore 只传递技术连接数据。 Timmy 还会对这一信令层加密,因此 Firestore 不会成为存放明文 SDP 和 ICE 的地方。
TURN 服务器:直连不可用时
有些网络会阻止直接连接,例如严格的防火墙或某些移动运营商网络。 这时 WebRTC 需要一个 TURN 中继 (Traversal Using Relays around NAT,即使用中继穿越 NAT)。
Timmy 会先尝试本地 TURN 服务器;本地中继不可用或负载过高时,则使用 Cloudflare 作为备用。中继只转发加密数据包,拿不到音频或视频的密钥;WebRTC 加密依然有效。
TURN 凭据由 Firebase Cloud Function 提供,且仅在 24 小时内有效。 在婴儿监护器应用中使用长期有效的凭据,我觉得风险太高。
Nearby Connections:设备自动发现彼此
为了避免在宝宝端和家长端设备之间进行繁琐设置,Timmy 使用 Nearby Connections。 Google 通过蓝牙和 Wi‑Fi 提供这一发现层。
Timmy 的自动配对 无需手动输入代码:设备会自动发现彼此,并找到同一个会合点来交换密钥。 如果自动配对失败,你也可以输入一个由 4 个字符组成的代码。 配对码不会离开设备;Firestore 只能看到一个密码学哈希值(SHA-256),并将其用作文档标识符。
匿名身份验证
Timmy 使用 Firebase 匿名身份验证。首次启动时,每台设备都会获得一个临时匿名 ID。 无需账号、电子邮箱地址或密码。这个 ID 仅用于执行 Firestore 规则:只有已通过身份验证的设备才能读取或写入会话数据。
架构:谁发送,谁接收
Timmy 有两种模式:
- 宝宝模式(发送端): 设备通过麦克风采集声音,并经由 WebRTC 发送到家长端设备。也可以开启摄像头,视频同样会直接发送。
- 家长模式(接收端): 设备接收音频和视频,显示摄像头画面,并提供按住说话功能,可向宝宝端设备发送简短语音消息。
按住说话、摄像头开关等控制功能使用 DataChannel,这是另一条 WebRTC 通道,用于在设备之间直接发送小型加密消息。
为什么选择 Flutter?
Flutter 是 Google 推出的跨平台应用框架。对 Timmy 来说,这意味着许多逻辑只需编写一次,就能同时用于 Android 和 iOS。 Timmy 已推出 Android 版,iOS 版也即将发布。重复代码越少,可能出现错误的地方也就越少。
总结
技术原则很简单:Timmy 只应接触它真正需要的数据。 WebRTC 保护音视频,Firebase 协调连接建立,TURN 只能看到加密数据包,Nearby Connections 则让配对更省心。
好的技术会悄然融入日常生活。它默默发挥作用,不会把婴儿房变成一个云端项目。