Привет! Меня зовут Роман. Я back-end разработчик в digital-агентстве MACHAON. Мы занимаемся разработкой и развитием цифровых решений для b2b и EdTech.
В июне мы запустили онлайн-школу Programica для подготовки к ЕГЭ с возможностью создания неограниченного количества курсов по разным предметам, с видеотрансляциями, чатом, автоматизированными тренировками, дашбордами с прогрессом обучения и многим другим.
В рамках этого проекта для нашей компании была поставлена задача организовать видеотрансляции без привлечения сторонних сервисов-посредников, что актуально в условиях санкций и других ограничений. И необходимо было учесть следующие требования:
- Видеосвязь c возможностью демонстрации экрана.
- Возможность общения в чате в рамках онлайн-урока.
- Автоматическая запись и хранение записей уроков.
- Установка таймкодов на запись урока.
- Параллельный запуск онлайн-уроков без ограничений.
Для реализации видеотрансляций мы использовали open-source решение Jitsi Meet с автоматической записью уроков на стороне сервера c помощью Jibri.
В этой статье я дам подробную инструкцию по созданию решения для видеотрансляций с помощью Jitsi Meet.
Что такое Jitsi?
Jitsi — это набор проектов с открытым исходным кодом, которые позволяют использовать их в роли self-hosted сервер видеоконференций и быстро, и безопасно интегрировать функционал видеоконференций в веб- и мобильные приложения.
Архитектура
Jitsi состоит из нескольких проектов. Они устанавливаются вместе с пакетом jitsi-meet
. Часть из них обязательные для использования и настройки, и необходимы для работы видеоконференций, другие же опциональные, т.к. реализуют функционал, который может потребоваться не всем. Перечислим их:
Jitsi Meet — JavaScript-приложение, построенное на базе протокола WebRTC, которое подключается к Jitsi Videobridge.
Jitsi Videobridge (JVB) — совместимый с WebRTC сервер, предназначенный для маршрутизации видеопотоков между участниками конференции.
Jitsi Conference Focus (jicofo) — компонент фокуса на стороне сервера, который управляет сеансами мультимедиа и действует как балансировщик нагрузки между каждым из участников и видеомостом.
Jitsi Gateway to SIP (jigasi) — серверное приложение, позволяющее обычным SIP-клиентам присоединяться к конференциям Jitsi Meet.
Jitsi Broadcasting Infrastructure (jibri) — набор инструментов для записи и/или потоковой передачи конференции Jitsi Meet, который работает путем запуска экземпляра Chrome в framebuffer и захвата, и кодирования вывода с помощью ffmpeg.
Также Jitsi использует внешнее программное обеспечение:
Prosody — сервер XMPP, служит для объединения компонентов и функционала авторизации.
Внешние соединения можно разделить на две основные группы. Во-первых, соединения между клиентами, которые запрашивают видео- или аудиосоединение, осуществляются через удаленные запросы и потоки данных. Вторая категория внешних подключений — это подключения к внешним службам, которые помогают хранить записи, потоковые записи, потоковое видео или помогают создавать встречи.
Опыт интеграции Jitsi в web-приложение
Задача состояла в том, чтобы настроить видеоконференцию внутри web-приложения и управлять ей изнутри, разделяя права на доступ к некоторым функциям видеоконференции. Так, например, для простых участников должна отображаться просто трансляция без возможности производить действия по настройке. Для них требовалось спрятать кнопки управления трансляцией. А для модераторов, наоборот, предоставить полный доступ, но так же ограничить ряд функций. Еще одной из задач была реализовать запись видеоконференции и сохранение записей в web-приложении. О чем уже упоминал выше.
Для этого потребовалось задействовать следующие решения:
- Jitsi Meet Server — сервер, который является ядром, управляющим видеоконференцией.
- Jitsi IframeAPI — библиотека, предоставляемая jitsi, дающая возможность поместить конференцию Jitsi в Iframe и управлять трансляцией с помощью JS.
- JWT Tokens — авторизацию в проекте было решено реализовать через JWT (JSON Web Token).
- Jitsi Token Moderation Plugin — плагин, который добавляет в jitsi возможность указывать в JWT токене роль пользователя (moderator).
- Jibri — JItsi BRoadcasting Infrastructure, позволяющая вести запись видеоконференции.
Далее более подробно будет рассказано про каждую часть, ее установку и настройку.
Установка и настройка Jitsi
Для корректной работы, а также с целью распределения ресурсов Jitsi требуется устанавливать на отдельный сервер с возможностью доступа по домену и отдельным ip-адресом, который будет доступен вашему приложению.
Требования
Вам понадобятся следующие пакеты:
gnupg2
nginx
sudo
# требуется, только если вы авторизованы не под пользователемroot
curl
# или wget для добавления репозиториев Jitsi ниже
Далее будут использованы команды без `sudo`, подразумевая, что сервер настроен и используется под пользователем `root`. Если это не так, то следует добавить `sudo`, когда того требует команда.
Убедитесь, что система обновлена и установлены необходимые пакеты:
apt update
apt install apt-transport-https
Установка Jitsi
Домен и DNS
Решите, какой домен будет использовать ваш сервер. Например, meet.example.org
.
Установите запись DNS A для этого домена, используя публичный IP-адрес вашего сервера, если у него есть собственный публичный IP-адрес, или же общедоступный IP-адрес вашего маршрутизатора, если ваш сервер имеет частный (RFC1918) IP-адрес (например, 192.168.1.2) и подключается через ваш маршрутизатор через преобразование сетевых адресов (NAT).
Репозиторий пакетов Prosody
Добавьте официальный репозиторий Prosody, чтобы установить последнюю версию Prosody, которая необходима для работы Jitsi, в частности, функционала лобби.
echo deb http://packages.prosody.im/debian $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list
wget https://prosody.im/files/prosody-debian-packages.key -O- | sudo apt-key add -
Репозиторий пакетов Jitsi
Добавьте официальный репозиторий jitsi в систему, чтобы сделать пакеты Jitsi Meet доступными.
curl https://download.jitsi.org/jitsi-key.gpg.key | sudo sh -c 'gpg --dearmor > /usr/share/keyrings/jitsi-keyring.gpg'
echo 'deb [signed-by=/usr/share/keyrings/jitsi-keyring.gpg] https://download.jitsi.org stable/' | sudo tee /etc/apt/sources.list.d/jitsi-stable.list > /dev/null
#После добавления репозиториев обновите все пакеты
apt update
Настройка брандмауэра
Следующие порты должны быть открыты в брандмауэре, чтобы разрешить трафик на сервер Jitsi Meet:
- 80 TCP — для проверки/обновления сертификата SSL с помощью Let’s Encrypt;
- 443 TCP — для общего доступа к Jitsi Meet;
- 10000 UDP — для общей сетевой видео/аудиосвязи;
- 22 TCP — если доступ к серверу с помощью SSH (соответственно измените порт, если он не 22);
- 3478 UDP — для запроса stun-сервера (coturn, необязательно, для его включения требуется изменение config.js);
- 5349 TCP — для резервной сетевой видео/аудио связи по TCP (например, когда UDP заблокирован), обслуживается coturn.
Если используется ufw
:
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 10000/udp
ufw allow 22/tcp
ufw allow 3478/udp
ufw allow 5349/tcp
ufw enable
#Проверить состояние брандмауэра можно с помощью
ufw status verbose
TLS Сертификат
Для корректной работы Jitsi требуется TLS сертификат. Его можно сгенерировать самостоятельно, выбрав любой удобный способ. Или позже создайте сертификат Lets-Encrypt (см. ниже).
Установка jitsi-meet
apt install jitsi-meet
Будет предложено ввести имя хоста экземпляра Jitsi Meet. Если есть домен, нужно использовать конкретное доменное имя, например: meet.example.org
. В качестве альтернативы можно ввести IP-адрес машины (если он статичен или не меняется). Это имя хоста будет использоваться для конфигурации виртуального хоста внутри Jitsi Meet, также корреспонденты будут использовать его для доступа к веб-конференциям.
Также будет задан вопрос: требуется ли сгенерировать новый самоподписанный сертификат. Необходимо поступить на свое усмотрение, исходя из того, каким способом вы добавили или добавите сертификат. Рекомендуемый вариант — выбрать «Generate a new self-signed certificate», а далее его заменить.
Установщик проверит наличие Nginx или Apache (именно в таком порядке) и настроит виртуальный хост на найденном веб-сервере для обслуживания Jitsi Meet.
Если уже используется Nginx на порту 443 на той же машине, конфигурация TurnServer будет пропущена, так как она будет конфликтовать с вашим текущим портом 443.
Создайте сертификат Let’s Encrypt
Данный шаг не является обязательным, если вы ранее уже создали сертификат.
Лучший способ — создать сертификат, подписанный центром сертификации. Так не появится проблем с самоподписанным сертификатом. Самый простой способ — использовать Let’s Encrypt. Просто запустите в своей оболочке следующее:
/usr/share/jitsi-meet/scripts/install-letsencrypt-cert.sh
Обратите внимание, что этот сценарий использует тип подтверждения владением HTTP-01, поэтому сервер должен быть доступен из общедоступного Интернета через порты 80 и 443. Если хотите использовать другой тип подтверждения, не используйте этот сценарий, а вместо этого выберите «I want to use my own certificate» во время установки jitsi-meet.
Проверка
После успешной установки jitsi перейдите на домен или ip-адрес с портом 443, который вы указали при установке jitsi-meet
и запустите конференцию.
Отладка проблем
- Веб-браузер: можно попробовать использовать другой веб-браузер. Известно, что некоторые версии некоторых браузеров имеют проблемы с Jitsi Meet. WebRTC, веб-камера и микрофон: или посетите https://webrtc.github.io/samples/src/content/getusermedia/gum, чтобы протестировать поддержку WebRTC в вашем браузере.
- Брандмауэр: если участники не видят и не слышат друг друга, дважды проверьте правила брандмауэра/NAT.
- Nginx/Apache: поскольку мы предпочитаем использовать Nginx в качестве веб-сервера, установщик сначала проверяет наличие Nginx, а затем Apache. Если вам крайне необходимо принудительно использовать apache, попробуйте предварительно установить переменную jitsi-meet/enforce_apache для пакета jitsi-meet-web-config в debconf.
- Файлы журналов: взгляните на различные файлы журналов:
/var/log/jitsi/jvb.log
/var/log/jitsi/jicofo.log
/var/log/prosody/prosody.log
Jitsi IframeAPI
Чтобы использовать API, подключите библиотеку с помощью:
<script src='https://<your-domain>/external_api.js'></script>
или
<script src='https://meet.jit.si/external_api.js'></script>
Чтобы встроить Iframe на страницу, воспользуйтесь следующим:
const domain = '<your-domain>';
const options = {
roomName: '<your-room-name>',
width: 700,
height: 700,
parentNode: document.querySelector('#meet'),
lang: 'ru'
};
const api = new JitsiMeetExternalAPI(domain, options);
Чтобы более гибко настроить iframe, можно воспользоваться опциями:
const options = {
...
configOverwrite: {},
interfaceConfigOverwrite: {},
...
};
Внутри данных опций можно переопределить значения некоторых свойств, которые можно найти в файлах config.js и interface_config.js соответственно.
Чтобы передать токен JWT в Jitsi Meet, используйте следующий формат:
const options = {
...
jwt: '<jwt-token>',
...
};
или используйте userInfo
, чтобы передать параметры пользователя:
var options = {
...
userInfo: {
email: '<user-email>',
displayName: '<user-name>'
}
...
}
Далее будет использован способ авторизации с помощью JWT токена, так что если требуется использовать их, выбирайте `jwt` вместо `userInfo`. Или наоборот, если того требует ситуация.
Другие свойства и возможности IframeAPI можно найти на странице с официальной документацией.
JWT-токены
Все настройки авторизации через JWT производятся на стороне сервера Jitsi.
Что такое JWT
JSON Web Token (JWT) — это открытый стандарт (RFC 7519), определяющий компактный и автономный метод, который можно использовать для безопасного обмена информацией между двумя сторонами путем аутентификации доступа пользователя.
Как только пользователь войдет в систему, каждый будущий запрос будет содержать JWT, что позволит пользователю получить доступ к службам и ресурсам, доступным с помощью этого токена.
JWT и Jitsi встречаются
Аутентификация на основе JWT с Jitsi Meet требует, чтобы приложение генерировало веб-токен JSON, когда планируется конференция, которое можно отправить (с прикрепленным URL-адресом конференции и сгенерированным токеном) пользователю для обеспечения безопасного общения. Пользователи смогут просто щелкнуть ссылку и присоединиться к совещанию, не дожидаясь авторизации Модератором в лобби, без ввода имени пользователя или пароля вручную. Пользователи, не использующие JWT, также могут присоединиться, даже если они будут знать URL-адрес собрания, поскольку есть имя пользователя и пароль, индивидуально защищающие ваши собрания.
Установка и настройка
1. Установите Lua зависимости:
- Lus5.2
- Liblua5.2-0
- Liblua5.2-dev
- Luaroks
- Libss11.0-dev
2. Установите luacrypt lua-cjson:
luarocks install luacrypt
mkdir -p /tmp/src)
cd /tmp/src
git clone https://github.com/mpx/lua-cjson.git
cd lua-cjson
sed -i 's/lua_objlen/lua_rawlen/g' lua_cjson.c
sed -i 's|$(PREFIX)/include|/usr/include/lua5.2|g' Makefile
luarocks make
3. Установите luajwtjitsi:
luarocks install luajwtjitsi 2.0-0
Версия 2.0-0 должна быть обязательно указана, так как текущая версия jitsi не поддерживает другую и в противном случае это не заработает.
4. Установите basexx:
luarocks install basexx
5. Установите token-plugin:
apt-get install jitsi-meet-tokens
6. Проверьте и настройте конфигурацию prosody.
Найти файл настройки prosody можно по пути /etc/prosody/conf.avail/.cfg.lua
...
VirtualHost "<your-domain>"
authentication = "token"
app_id="<app-id>"
app_secret="<app-secret>"
...
modules_enabled = {
...
"presence_identity";
...
}
...
Component "conference.<your-domain>" "muc"
...
modules_enabled = {
...
"token_verification";
...
}
...
...
`app-id` и `app-secret` задаются произвольно, но обычно `app-id` представляет из себя строку, например ‘MyJitsiApp’. А `app-secret` — это строка, состоящая из 20 различных символов, которая шифрует токен и подтверждает, что он подлинный. Данные параметры используются при генерации JWT токена.
После всех настроек перезагрузите prosody
, чтобы применить настройку prosody
.
sudo systemctl restart prosody
Генерация JWT
Чтобы попробовать сгенерировать JWT токен, можно использовать сервис https://jwt.io/.
Программно это можно сделать с помощью библиотек, которые уже существуют для разных языков программирования. Например, чтобы сгенерировать токен в php лучше всего использовать PHP-JWT от FireBase.
Структура JWT должна представлять из себя:
header
{
"alg": "HS256",
"typ": "JWT"
}
payload
{
"context": {
"user": {
"avatar": "<your-avatar-link>", #ссылка на аватар
"name": "<user-name>", #имя пользователя
"email": "<user-email>" #email пользователя
}
},
"aud": "jitsi",
"iss": "<app-id>",
"sub": "<your-domain>",
"room": "*", #имя комнаты или * - любая комната
"iat" => 1643498815, #время в timestamps до которого будет действителен токен
"nbf" => 1643498815, #время в timestamps от которого будет действителен токен
}
Также библиотека для генерации должна использовать ключ
Jitsi Token Moderation Plugin
В Jitsi нет встроенного механизма определения ролей пользователя на основе JWT токена. Эту проблему можно решить, поставив плагин https://github.com/nvonahsen/jitsi-token-moderation-plugin.
Его установка очень простая и описана в репозитории, но я продублирую ее в этой инструкции.
Установка
- Скачайте и поместите
mod_token_moderation.lua
файл на свой сервер. - Откройте файл конфигурации prosody
/etc/prosody/conf.avail/.cfg.lua
- Добавьте в самое начало:
plugin_paths = { "/usr/share/jitsi-meet/prosody-plugins/", "/usr/share/jitsi-meet/prosody-plugins-custom/"
4. Файл mod_token_moderation.lua
поместите в дирректорию /usr/share/jitsi-meet/prosody-plugins-custom/
5. В файле конфигурации prosody
добавьте:
Component "conference.meet.example.com" "muc"
...
modules_enabled = {
...
"token_moderation"; # <- требуется добавить вот эту строчку
...
}
...
6. Перезагрузите Jitsi.
sudo systemctl restart prosody && sudo systemctl restart jicofo && sudo systemctl restart jitsi-videobridge2
Применение
После установки в JWT можно добавить параметр moderator
{
...
moderator: true
...
}
И тогда, у кого будет этот параметр равен true
, будет являться модератором видеоконференции. И наоборот, если `false`, то обычным пользователем.
На этом все, чем я хотел поделиться про установку и настройку Jitsi. Надеюсь, что статья была полезной.
Жду в комментариях с вопросами и обратной связью.
В следующей статье расскажу про Jibri.