
Безсерверный, одноранговый, локальный обмен файлами через звук
Концепт-доказательство для сигнализации WebRTC через звук. Работает на всех устройствах, имеющих микрофон + динамики. Выполняется в браузере.
Близлежащие устройства устанавливают WebRTC-соединение, обмениваясь необходимыми данными протокола SDP (Session Description Protocol) через последовательность звуковых тонов. После успешной договорённости между браузерами устанавливается локальное WebRTC-соединение, позволяющее обмениваться данными по LAN.
Посмотрите в действии (видео 2 мин.):
Попробуйте сами: ggerganov.github.io/wave-share
Последние новости:
Я выделил алгоритм передачи данных через звук в отдельную библиотеку ggwave.
Её легко встраивать в другие проекты.
Технология WebRTC позволяет двум браузерам на разных устройствах соединяться друг с другом и обмениваться данными. Нет необходимости устанавливать плагины или загружать приложения. Для инициализации соединения пиры обмениваются контактной информацией (IP-адрес, сетевые порты, идентификатор сессии и т.д.). Этот процесс называется «сигнализацией». Спецификация WebRTC не определяет стандарта для сигнализации — обмен контактами может быть реализован с помощью любого протокола или технологии.
В этом проекте сигнализация осуществляется через звук. Последовательность сигнализации выглядит так:

Описанная последовательность сигнализации не требует сервера сигнализации. Поэтому приложение, использующее сигнализацию через звук, может, например, обслуживаться статической веб-страницей. Единственное требование — иметь контроль над устройствами вывода/захвата звука.
Очевидное ограничение (особенность) текущего подхода в том, что только близлежащие устройства (например, в одной комнате) могут установить соединение друг с другом. Более того, устройства должны быть подключены к одной локальной сети, так как NAT недоступен.
Данные, передаваемые через звук, содержат контактную информацию, необходимую для инициализации WebRTC-соединения. Эти данные хранятся в формате Session Description Protocol (SDP). Поскольку передача данных через звук имеет существенные ограничения по пропускной способности и надёжности, желательно передавать как можно меньше данных. Поэтому SDP очищается от всей нерелевантной информации, и передаются только основные данные, необходимые для установки соединения. В настоящее время звуковой пакет, содержащий минимальные необходимые данные SDP, имеет следующий формат:
Общий размер звукового пакета — 112 байт. С помощью текущего алгоритма кодирования звука пакет SDP может быть передан за 5–10 секунд (в зависимости от используемого протокола передачи). Использование более медленных протоколов обеспечивает более надёжную передачу в шумной обстановке или если связывающиеся устройства находятся далеко друг от друга.
В текущем подходе используется мультичастотная схема модуляции FSK (Frequency-Shift Keying). Передаваемые данные сначала разбиваются на 4-битовые части. В каждый момент времени передаются 3 байта с помощью 6 тонов — по одному тону на каждую 4-битовую часть. 6 тонов излучаются в диапазоне 4.5 кГц, разделённом на 96 равномерно расположенных частот:
Для всех протоколов: dF = 46.875 Гц. Для неультразвуковых протоколов: F0 = 1875.000 Гц. Для ультразвуковых протоколов: F0 = 15000.000 Гц.
Для удобства используется простой WebRTC-хак для автоматического определения локального IP-адреса вашего компьютера, чтобы не вводить его вручную. Однако последняя спецификация WebRTC запрещает это по соображениям безопасности, поэтому со временем эта «фишка» перестанет работать во всех браузерах. Например, она больше не работает в Safari.
wave.wasmВам понадобится компилятор Emscripten. Запустите скрипт compile.sh.
wave-shareВажно: Этот CLI-инструмент был прототипом для ныне самостоятельной библиотеки ggwave. Обязательно посмотрите её, так как в ней есть более актуальные примеры применения этого типа связи «данные через звук».
Это простой инструмент, который принимает и отправляет данные с помощью описанного протокола wave-share tx/rx. Введите текст на стандартном вводе и нажмите Enter для передачи.
# сборка
git clone https://github.com/ggerganov/wave-share
cd wave-share && mkdir build && cd build
cmake ..
make
# запуск
./wave-share
Вот короткое видео, демонстрирующее использование CLI-инструмента:
| Размер, [байт] | Описание |
|---|
| 1 | Тип SDP — приглашение или ответ |
| 1 | Размер пакета в байтах (без байтов коррекции ошибок ECC) |
| 4 | IP-адрес передающего пира |
| 2 | Сетевой порт, используемый для связи |
| 32 | SHA-256 отпечаток данных сессии |
| 40 | ICE-учётные данные — 16 байт имени пользователя + 24 байта пароля |
| 32 | Корректирующие байты ECC для исправления ошибок при передаче |
| Частота, [Гц] | Значение, [биты] | Частота, [Гц] | Значение, [биты] | ... | Частота, [Гц] | Значение, [биты] |
|---|
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 |