О том, что самоизоляция — это не только «тук-тук-тук» в крышку гроба экономики, но и новые «горизонты возможностей», уже написано немало статей. Правда, многие из них вызывают в памяти басню Крылова про лису и виноград. Но всё же в одном карантинные коучи правы: вся эта ситуация заставляет изобретать — не обязательно какие-то глобальные штуки, которые изменят новый мировой порядок. Иногда — просто небольшие продукты, которые помогли сделать самоизоляцию чуть более выносимой. Об одном из них, плеере ITSkino, мы уже вкратце писали. А сейчас хотим рассказать, как и что мы делали, чтобы наделить VLC функцией синхронного просмотра потокового или локального видео у неограниченного количества человек одновременно.

У нас сейчас есть две сборки — под Windows и под MacOS. Исходные коды можно найти по этой ссылке. Два наших разработчика рассказывают о нюансах, с которыми столкнулись в процессе создания сборок.

Windows


Сборка как самого приложения, так и окружения описана здесь. Мы использовали метод сборки MinGW on Linux (ОС – Ubuntu 16.04.6 LTS).

Во время сборки могут приключиться разного рода сложности. Что-то можно нагуглить сходу, что-то не сразу, что-то можно найти у наших китайских братьев по ссылкам, например, www.cnblogs.com/johnsen/p/11721632.html или blog.csdn.net/DANFBAORE/article/details/95188935. В конечном итоге, всё получится!

Идеологически правильно было бы сделать отдельный модуль, но хотелось побыстрее собрать mvp, посмотреть и «пощупать», что получится. Поэтому решили немного допилить уже имеющийся модуль интерфейса (/modules/gui/qt). Версия qt, которая собирается «из коробки», не имела на борту поддержки сети (QNetwork), https (openSSL), а также был выключен плагин поддержки gif. Чтобы добавить необходимую функциональность, нужно было:

  • Собрать openSSL

git clone https://github.com/openssl/openssl.git
cd openssl? 
git checkout OpenSSL_1_0_2-stable?? 
./Configure --cross-compile-prefix=x86_64-w64-mingw32- mingw64 ? 
make? 
sudo make install

  • Добавить поддержку необходимых сетевых подсистем и плагинов, изменив файлы configure.ac и contrib/src/qt/rules.mak.

  • Собрать (пересобрать) qt.

«Центр» всей системы — ShareService — синглтон, который инициализируется вместе с модулем интерфейса.

Его основная функциональность:

  • «перехват» и обработка элементов списка воспроизведения, использующих в качестве источника адреса, начинающиеся с itsshare://
  • обработка изменения состояния элементов списка воспроизведения (play/pause/stop);
  • обработка события «поделиться»;
  • регистрация плейера как обработчика протокола itsshare.

Второстепенные функции:

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

API вызовы:

  1. Создание сеанса — api/stream/create
  2. Получить источник сеанса по хэшу — api/session/get
  3. Play — api/stream/play
  4. Pause — api/session/pause
  5. Stop — api/session/stop

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

Если во время воспроизведения видео, которое не участвует в сеансе совместного просмотра, пользователь нажал на кнопку «поделиться» (выбрал соответствующий пункт в меню ITSKino), то на эндпойнт api/stream/create отправляется запрос, содержащий источник (имя локального файла или ссылка на потоковое видео) и текущее время воспроизведения. В ответ мы получаем хэш созданного сеанса и ссылку на него, которая автоматически копируется в буфер обмена. Данный хэш сеанса, ассоциированный с источником, мы храним для последующего использования при взаимодействии с API.

При открытии в браузере ссылки
https://itskino.ru/join?stream=<hash>
происходит редирект на
itsshare://<hash>
Далее открывается плеер VLC (так как он является обработчиком данного протокола), в который передается соответствующий URL. ShareService перехватывает данный URL, извлекает хэш сессии и обращается с ним на эндпойнт api/session/get для получения источника воспроизведения. Источник связывается с хэшем сеанса для последующего использования при взаимодействии с API.

При изменении статуса элемента списка воспроизведения (play/pause/stop) идёт проверка, имеется ли связанный с ним хэш сеанса — и если есть, то он отсылается на соответствующий событию эндпойнт — api/stream/play, api/session/pause, api/session/stop. Запрос на api/stream/play возвращает текущее время воспроизведения сеанса совместного просмотра.

Если все участники сеанса отослали запрос api/session/pause, то сеанс приостанавливается и возобновляется только при первом запросе api/stream/play. При переключении элементов списка воспроизведения, источники которых связаны с хэшем сеанса, происходит обращение на api/session/stop. Сеанс перестает существовать, если все участники процесса отослали api/session/stop.

Публичный репозиторий

macOS


Билд:

Обнаружилась проблема с libiconv: если есть libiconv в /usr/local/ lib, надо временно переименовать папку lib, чтобы подсосался дефолтный libiconv из usr/lib.

Юнит:

  1. Сделан класс ItsUnit (фактически, аналог ShareService в виндовой сборке) и добавлен в мейк modules/gui/macosx/Makefile.am: юнит обрабатывает 5 эндпойнтов API (play, pause, stop, create, connect) и дополнительные методы (реакция на изменение элемента в плейлисте, проигрывание видеоинструкции, добавление, выбор папки синхронизации и т.д.)
  2. Чтобы приложение в macOS открывалось по кастомному протоколу, нужно следовать инструкции.
  3. Методы класса интегрированы в нужных местах модуля macOS GUI (в основном — modules/gui/macosx/playlist/VLCPlayerController, а также modules/gui/macosx/os-integration/applescript.m, modules/gui/macosx/library/VLCLibraryWindow.m и modules/gui/macosx/menus/VLCMainMenu.m/
  4. Инициализирован юнит в классе modules/gui/macosx/main/VLCMain.m

Публичный репозиторий — github.com/itsumma/itskino_mac

Вместо вывода


Тут, в общем, и нет никакого вывода: +\- какие-то похожие решения существовали и раньше. Просто мы сильно скучали по офису и друг другу. И решили, что раз мы айтишники, то можем себе позволить потратить немного времени, чтобы сделать штуку, которая объединит классные функции других решений и будет при этом open source, как мы любим. Ребята, которые писали выше про сборки, чуток поскромничали: не всё элементарно (и упорядочено) в исходниках VLC, и поразбираться всё-таки пришлось. Но на выходе получилось и красиво, и полезно — потому что самоизоляция закончится (ну, рано или поздно), а наше решение пригодится и дальше. И не только тем, кто хочет посмотреть вместе кино, но и, например, в дистанционном обучении.

Ну, а пока — вы знаете, чем занять себя вечером этой пятницы :-)