VoIP Contest: Stage 3

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

Задача этапа

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

К участию приглашаются все желающие. Вы можете прислать свою работу даже если не принимали участия в первом или втором этапах. Этап продлится три недели, до 20:59:00 UTC 30 марта 2020.

Отличия от второго этапа

Если вы принимали участие во втором этапе, обратите внимание на следующие изменения:

  • Изменилась базовая версия (коммит 6d21427) библиотеки libtgvoip. В частности в неё вошли некоторые улучшения, предложенные участниками второго этапа, а также незначительно был изменён публичный интерфейс TgVoip.h, для дальнейшего встраивания в мобильные клиенты и tgvoipcall.
  • Обновился tgvoip-test-suite. Скачать новую версию на GitHub ».
    — Добавлены дополнительные утилиты для оценки звонков (использованы работы победителей первого этапа)
    — Добавлен замер задержек во время совершения звонка. Пример анализа доступен в Jupyter Notebook с подведением итогов второго этапа: VoIP-Stage2-Dataset.tar.gz.
    — Добавлена возможность совершения звонков между двумя разными серверами.
    — Обновлен скрипт настройки netns tests/setup-netns.sh (обязательно запустите второй раз перед началом тестирования)
    — Изменен вывод call.php и mean.php, теперь выводятся 2 таблицы оценок: по версиям библиотек/оценщикам и по версиям библиотек/сетевым условиям.

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

  1. Библиотека libtgvoip. В конкурсе будет использоваться исходный код по состоянию на коммит 6d21427.
  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.
  • Необходимо уделить особое внимание потокобезопасности кода, стараться избегать дедлоков.
  • Участникам предыдущего этапа конкурса рекомендуется сфокусироваться на направлениях, предложенных в комментариях жюри к их работам на contest.com. Новые участники могут выбрать любой из подходов.

Примечания

  • 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 libssl-dev libopus-dev libavcodec-dev libavutil-dev libavformat-dev libavresample-dev libasound-dev python3 python-pip opus-tools libopusfile-dev pocketsphinx build-essential automake libtool libsphinxbase-dev libpocketsphinx-dev pkg-config sphinxbase-utils sphinxtrain libopusfile0 ffmpeg

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 и сохраняем файл.

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

Call + Rate

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

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

$ php tests/call.php

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

Version newunstable (12 ratings)
=============================================
ScoreFinal:         mean 3.58, stddev: 1.136
ScoreCombined:      mean 3.522, stddev: 1.265
ScoreOutput:        mean 3.713, stddev: 1.315
Score1010:          mean 3.615, stddev: 1.189
Score1012:          mean 3.298, stddev: 1.621
Score1002:          mean 2.413, stddev: 1.009
Score997:           mean 3.807, stddev: 0.923

....

Scores by network

Network             |   stable   |  unstable  |newunstable 
===========================================================
WiFi                |   4.604    |   4.798    |   4.794    
3G1                 |   4.874    |   4.636    |   4.727    
3G2                 |    4.48    |   3.722    |   4.242    
3G3                 |   4.822    |   4.023    |   4.209    
3G4                 |   4.369    |   3.696    |   4.274    
3GDelay             |     4      |   3.987    |   3.792    
3GOutage            |    3.97    |   3.877    |   4.029    
EDGE1               |   3.355    |   3.871    |   4.183    
EDGE2               |   2.859    |   2.366    |   2.564    
GPRS1               |   2.316    |   3.088    |   2.982    
GPRS2               |   1.752    |   1.651    |   1.785    
GPRS3               |   1.367    |   1.154    |   1.374    
-----------------------------------------------------------
Overall             |   3.564    |   3.406    |    3.58 

....

Здесь 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 - осталось неизменным.
Величины Score1010, Score1012, Score1002 и т д. являются аналогами ScoreCombined, в других реализациях.
Величина ScoreFinal является взвешенной суммой вышеописанных величин, на которую следует опираться в первую очередь при сравнении качества.

Эту статистику всегда можно получить позднее из 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.

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