VoIP Contest: Round 2

Перейти к английской версии документа

Задача этапа

Реализовать систему для качественных аудиозвонков между двумя пользователями с заданным интерфейсом, опираясь на данные системы для тестирования.

К участию приглашаются все желающие. Вы можете прислать свою работу даже если не принимали участия в первом этапе.

Входные данные

  1. Библиотека libtgvoip. В конкурсе будет использоваться исходный код по состоянию на коммит f775311.
  2. Публичный интерфейс звонков между двумя пользователями в заголовочном файле TgVoip.h. Через этот интерфейс библиотека подключена в тестирующем консольном клиенте tgvoipcall, он же в ближайшем времени будет использован и в мобильных клиентах.
  3. Набор утилит и звуковых файлов для тестирования и оценки качества звонков.
  4. Telegram API не требуется.

Задание

Условия

  • Использовать только C++ (за исключением скриптов сборки и тестирования), с прицелом на code portability. Будет плюсом, если библиотека собирается под Android.
  • Допускается изменять протокол обмена данными, а также использовать альтернативный/самописный протокол. При этом необходимо не терять E2E-шифрование (открытые голосовые данные не должны уходить ни на какой сервер, их ключ шифрования должен быть наследован от encryption_key, передаваемого в библиотеку). Сохранение совместимости с текущей реализацией будет плюсом.
  • Допускается игнорирование параметра адреса и тега Relay-сервера Telegram, использование своего/стороннего промежуточного Relay-сервера (STUN, TURN, xirsys, etc). При отправке работы рекомендуется использовать хостинг в Амстердаме или центральной Европе, чтобы при тестировании минимизировать задержку у жюри.
  • Допустимо использовать сторонний код только с GPL-совместимыми лицензиями.
  • За рамками конкурса остаются P2P (TgVoipEndpointType::Inet, TgVoipEndpointType::Lan), TCP Relay (TgVoipEndpointType::TcpRelay), SOCKS proxy (TgVoipProxy), Data saving mode (TgVoipDataSaving), Traffic stats (TgVoipTrafficStats), а также функции setGlobalServerConfig, onSignalBarsUpdated, setMuteMicrophone, флаг TGVOIP_USE_CUSTOM_CRYPTO. Они не будут использоваться/учитываться при тестировании, их можно игнорировать.
  • Обязательно необходимо поддержать TgVoipState, onStateUpdated, TgVoipAudioDataCallbacks.
  • Необходимо уделить особое внимание потокобезопасности кода, стараться избегать дедлоков.

Примечания

  • P2P должен быть принудительно выключен на стороне библиотеки.
  • IPv6 не будет поддерживаться сервером во время тестирования.
  • Рекомендуется использовать UDP протокол.
  • Работы будут тестироваться на серверах с Debian GNU/Linux 10.1 (buster), x86-64. Обязательно проверьте корректность работы библиотеки на чистой системе перед отправкой работы.
  • Тестирование звонков будет производиться только между двумя клиентами, использующими одну и ту же конкурсную работу. Совместимость с текущей реализацией не является обязательной, но положительно повлияет на оценку жюри.
  • Клиенты одного звонка могут быть запущены на разных физических серверах.
  • На выходе требуется ZIP-файл (максимальный размер - 200MB) со следующей структурой:

    submission.zip
      -> libtgvoip.so - подключаемая библиотека
      -> README - инструкция по сборке, описание проделанной работы
      -> src - директория с исходным кодом
      -> deb-packages.txt - текстовый файл с названиями пакетов внешних зависимостей для сборки, разделенных переводом строки

Возможные подходы

Ниже перечислены возможные подходы при участии в конкурсе, по возрастанию степени их радикальности. Каждый из них имеет свои плюсы и будет иметь шансы на приз и победу при должном объёме и качестве проделанной работы.

  • Находить и исправлять конкретные проблемы в текущей реализации библиотеки. Например, исправлять потенциальные deadlock'и или находить сетевые условия, в которых качество голоса/задержка хуже, чем могло бы быть. Для всех подобных проблем необходимо подробно описать условия для воспроизведения и предпринятые меры.
  • Переписать библиотеку, сохранив совместимость с текущими клиентами (оставив сетевые протоколы без изменения).
  • Использовать сторонние библиотеки/протоколы, теряя совместимость. Опционально использовать свой Relay-сервер.

Критерии оценки

  • Соблюдение всех условий
  • Объем кода, количество внешних зависимостей

Все работы будут протестированы с одинаковыми наборами входных данных (аудиосемпл + сетевые условия). Выходные файлы будут оценены с помощью tgvoiprate, полученная метрика будет учитываться, но не будет являться основной при оценке работ.

Test Suite

Для тестирования в процессе разработки предоставляется набор утилит и звуковые файлы. Скачать на GitHub ».

Набор утилит позволяет:

  • Совершать псевдо-звонок с использованием бинарного so-файла с библиотекой. Вместо реального входного сигнала с микрофона используются звуковые семплы с речью, либо тишиной для каждой из сторон. Выходной сигнал у получателя записывается в аналогичный звуковой файл.
  • Программно задавать условия сети для одного из участников: потери пакетов, повышенная latency, пропускная способность канала, а также программно изменять их в процессе звонка.
  • Получать числовую оценку качества полученного на выходе звукового файла у получателя по сравнению со входным файлом и preprocessed файлом (который реально уходит по сети) у отправителя.
  • Записывать имена входных и выходных файлов, а также рейтинги в CSV файл, для дальнейшего анализа.
  • Управлять всем вышеперечисленным с помощью PHP-скрипта.
  • Агрегировать рейтинги по версиям библиотеки.

Ниже приведена инструкция для Debian GNU/Linux 10.1 (buster), x86-64.

Подготовка системы

1. Необходимо установить deb-пакеты:

$ sudo apt-get install php

2. Для эмулирования разных сетевых условий используется netem, а также ip-netns для наложения сетевых ограничений только на один из процессов (у отправителя). Перед началом работы необходимо однократно запустить скрипт

$ sudo bash ./tests/setup-netns.sh
$ sudo tc qdisc list

Он настроит network namespace client1 с виртуальным интерфейсом v-peer1 для дальнейшей работы утилиты звонков, больше при нормальной работе вызывать его не потребуется. Если какая-то из команд выведет ошибки, которые не пропадают при повторном её запуске, то возможно на вашей системе необходимо установить/включить netem или ip-netns.

3. Поскольку мы будем часто менять параметры netem для изменения сетевых условий, и это требует root/sudo, необходимо отключить интерактивный запрос пароля при вызове таких команд. Для этого запустим:

$ whoami
  user
$ sudo visudo

В самый конец файла добавляем строку

user ALL=(ALL) NOPASSWD: /usr/bin/ip netns exec client1 *

заменив user на вывод команды whoami. Сохраняем файл (в случае редактора Vim, необходимо нажать Esc, затем набрать :wq, нажать Enter).

4. После этого необходимо указать свой token для работы с VoIP Contest API. Для этого необходимо заменить значение по умолчанию 111222333444:AAABBBCCCDDD в файле tests/token.php на то значение, которое Вы получили от @jobs_bot во время регистрации на этот этап конкурса (или в рассылке).

Обратите внимание, что если Вы участвовали в первом этапе конкурса VoIP, Вам необходимо получить у бота новый токен для второго этапа.

Call + Rate

Основной файл с описанием сценария тестирования - tests/call.php. В нём задается список so-файлов библиотек для тестирования, количество итераций звонков, а также наборы сетевых условий. Для примера файл заполнен демонстрационным содержимым, рекомендуется изменить его под свои нужды.

Запуск с помощью:

$ php tests/call.php

Будет выполнен весь описанный сценарий тестирования. Это может занять длительное время, каждая итерация займёт порядка 10-20 секунд в зависимости от длительности выбранного аудиосемпла. В папках preprocessed и out появятся файлы с аудиоданными, отправляемыми по сети и полученные получателем, соответственно. Каждый звонок также будет сразу оценен, а результаты оценки записаны в CSV-файл. Если доступ к серверу осуществляется через SSH, рекомендуется использовать nohup/screen для длительных запусков, чтобы вызов не прерывался потерей соединения.
В конце выполнения скрипт также выведет средние значения оценок для каждой из протестированных версий, например:

Version stable (3234 ratings)
=============================================
ScoreCombined:      mean 3.063, stddev: 0.924
ScorePreprocess:    mean 4.257, stddev: 0.408
ScoreOutput:        mean 3.39, stddev: 0.942

....

Здесь ScorePreprocess характеризует, насколько деградирует качество звука в preprocessed файле по сравнению с входным. 1.0-5.0, где 1.0 - полностью испортилось, 5.0 - осталось неизменным.
Величина ScoreOutput характеризует, насколько деградирует качество звука у получателя по сравнению с preprocessed у отправителя. 1.0-5.0, где 1.0 - полностью испортилось, 5.0 - осталось неизменным.
Величина ScoreCombined характеризует, насколько деградирует качество звука у получателя по сравнению с исходным аудио отправителя, то есть некоторая аггрегация ScorePreprocess и ScoreOutput. 1.0-5.0, где 1.0 - полностью испортилось, 5.0 - осталось неизменным.

Эту статистику всегда можно получить позднее из CSV-файла, запустив

$ php tests/mean.php

Очистить все накопленные preprocessed, out файлы и CSV файл можно с помощью:

$ sh tests/clean.sh

Предполагаемое использование

Один из вариантов организации процесса разработки библиотеки может быть следующим:

  1. Вести разработку библиотеки в отдельной директории. На время разработки писать подробные логи внутри библиотеки в stdout/stderr.
  2. После каждого значимого изменения, выполнять сборку, совершать git commit, копировать выходной .so файл библиотеки в директорию lib Test Suite с уникальным именем, например libtgvoip.COMMIT.so и добавлять в список тестируемых библиотек libraries в tests/call.php.
  3. Запускать в фоне тестирование изменений, продолжать вести разработку (поскольку процесс тестирования длительный).
  4. Изучать выходные логи своей библиотеки (пишутся в .log файлы в папке out), а также прослушивать аудиофайлы, если это требуется, для примеров с наиболее низкими рейтингами.
  5. Находить и исправлять проблемы. Возращаться к п. 2.

Когда качество достигнет допустимого уровня, можно сфокусироваться на поиске новых сетевых условий, в которых результат работы библиотеки значительно портится, например перепады в скорости соединения, процентах потерь и исправлять там, где это возможно.