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.
— Добавлена возможность совершения звонков между двумя разными серверами.
— Обновлен скрипт настройки netnstests/setup-netns.sh
(обязательно запустите второй раз перед началом тестирования)
— Изменен вывод call.php и mean.php, теперь выводятся 2 таблицы оценок: по версиям библиотек/оценщикам и по версиям библиотек/сетевым условиям.
Входные данные
- Библиотека libtgvoip. В конкурсе будет использоваться исходный код по состоянию на коммит 6d21427.
- Публичный интерфейс звонков между двумя пользователями в заголовочном файле TgVoip.h. Через этот интерфейс библиотека подключена в тестирующем консольном клиенте tgvoipcall, он же в ближайшем времени будет использован и в мобильных клиентах.
- Набор утилит и звуковых файлов для тестирования и оценки качества звонков.
- Telegram API не требуется.
Задание
- Улучшить реализацию звонков одним из возможных путей.
- Сохранить публичный интерфейс звонков TgVoip.h.
Условия
- Использовать только 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
Предполагаемое использование
Один из вариантов организации процесса разработки библиотеки может быть следующим:
- Вести разработку библиотеки в отдельной директории. На время разработки писать подробные логи внутри библиотеки в stdout/stderr.
- После каждого значимого изменения, выполнять сборку, совершать
git commit
, копировать выходной .so файл библиотеки в директориюlib
Test Suite с уникальным именем, например libtgvoip.COMMIT.so и добавлять в список тестируемых библиотек libraries в tests/call.php. - Запускать в фоне тестирование изменений, продолжать вести разработку (поскольку процесс тестирования длительный).
- Изучать выходные логи своей библиотеки (пишутся в .log файлы в папке out), а также прослушивать аудиофайлы, если это требуется, для примеров с наиболее низкими рейтингами.
- Находить и исправлять проблемы. Возращаться к п. 2.
Когда качество достигнет допустимого уровня, можно сфокусироваться на поиске новых сетевых условий, в которых результат работы библиотеки значительно ухудшается, например перепады в скорости соединения, процентах потерь и т.д. – и улучшать его там, где это возможно.