这是一个利用声音进行WebRTC信令的概念验证。适用于所有配备麦克风和扬声器的设备。在浏览器中运行。
附近的设备通过一系列音频音调交换必要的会话描述协议(SDP)数据,从而协商WebRTC连接。协商成功后,浏览器之间建立本地WebRTC连接,允许通过LAN交换数据。
观看演示视频(2分钟):
亲自尝试:ggerganov.github.io/wave-share
最新消息:
我已将声音数据传输算法提取到独立的库 ggwave 中。
它可以轻松嵌入其他项目。
WebRTC 技术允许运行在不同设备上的两个浏览器相互连接并交换数据,无需安装插件或下载应用程序。要建立连接,对等端需要交换联系信息(IP地址、网络端口、会话ID等)。这个过程称为“信令”。WebRTC规范并未定义信令的标准——联系信息的交换可以通过任何协议或技术实现。
在该项目中,信令通过声音完成。信令序列如下:

上述信令序列不涉及信令服务器。因此,使用声音信令的应用程序可以托管在静态网页上。唯一的要求是能够控制音频输出/捕获设备。
当前方法的一个明显限制(功能)是:只有附近的设备(例如同一房间内)才能相互建立连接。此外,设备必须连接在同一本地网络中,因为不支持NAT。
通过声音通信的数据包含初始化WebRTC连接所需的联系信息。这些数据以会话描述协议(SDP)格式存储。由于声音数据传输在带宽和鲁棒性方面存在显著限制,因此应尽可能传输最少的数据。因此,SDP会剥离所有无关信息,仅传输建立连接所需的核心数据。目前,包含最简SDP数据的声音数据包格式如下:
| 大小(字节) | 描述 |
|---|---|
| 1 | SDP类型 - 请求(Offer)或应答(Answer) |
| 1 | 数据包大小(字节,不包括ECC校验字节) |
| 4 | 发送对等端的IP地址 |
| 2 | 用于通信的网络端口 |
| 32 | 会话数据的SHA-256指纹 |
| 40 | ICE凭据 - 16字节用户名 + 24字节密码 |
| 32 | ECC纠正字节,用于在传输过程中纠正错误 |
音频数据包总大小为112字节。使用当前的音频编码算法,SDP数据包可在5-10秒内传输完毕(取决于使用的传输协议)。使用较慢的协议可以在嘈杂环境或通信设备相距较远时提供更可靠的传输。
当前方法采用多频频移键控(FSK)调制方案。待传输的数据首先被分割为4比特块。每次传输3个字节,使用6个音调,每个音调对应一个4比特块。这6个音调在4.5kHz范围内发射,该范围分为96个等间距频率:
所有协议:dF = 46.875 Hz。非超声波协议:F0 = 1875.000 Hz。超声波协议:F0 = 15000.000 Hz。
为方便起见,使用了一个简单的WebRTC技巧来自动检测机器的本地IP地址,这样您无需手动输入。然而,最新的WebRTC规范出于安全原因阻止了这种可能性,因此这一“功能”最终将在所有浏览器中失效。例如,在Safari上已不再有效。
wave.wasm您需要Emscripten编译器。运行 compile.sh 脚本。
wave-share重要提示: 该CLI工具是独立库 ggwave 的原型。请务必查看该库,因为它提供了更最新的应用示例,用于这种声音数据传输通信方式。
这是一个简单的工具,使用上述 wave-share 声音发送/接收协议来接收和发送数据。在标准输入中输入文本并按回车键进行传输。
# 构建
git clone https://github.com/ggerganov/wave-share
cd wave-share && mkdir build && cd build
cmake ..
make
# 运行
./wave-share
以下是一个简短视频,演示如何使用CLI工具:
| 频率(Hz) | 值(bits) | 频率(Hz) | 值(bits) | ... | 频率(Hz) | 值(bits) |
|---|
F0 + 00*dF | 块0: 0000 | F0 + 16*dF | 块1: 0000 | ... | F0 + 80*dF | 块5: 0000 |
F0 + 01*dF | 块0: 0001 | F0 + 17*dF | 块1: 0001 | ... | F0 + 81*dF | 块5: 0001 |
F0 + 02*dF | 块0: 0010 | F0 + 18*dF | 块1: 0010 | ... | F0 + 82*dF | 块5: 0010 |
| ... | ... | ... | ... | ... | ... | ... |
F0 + 14*dF | 块0: 1110 | F0 + 30*dF | 块1: 1110 | ... | F0 + 94*dF | 块5: 1110 |
F0 + 15*dF | 块0: 1111 | F0 + 31*dF | 块1: 1111 | ... | F0 + 95*dF | 块5: 1111 |