Популярность онлайн-образования увеличивается с каждым месяцем. А где увеличение популярности, там и возрастание конкуренции и улучшение качества: многие авторы онлайн-школ поняли, что уже мало снимать какую-то кашу из пикселей на фронталку четвертого айфона - нужно работать над качеством картинки, звука, подачей материала и т.д. Мало того, что пандемия доказала, что онлайн можно преподавать хоть сальсу, хоть вязание крючком, так это еще и дало очень большой толчок к улучшению преподаваемых материалов + разнообразие на рынке труда. Мамочки в декрете могут ликовать - теперь действительно можно зарабатывать сто тысяч миллионов в секунду, сидя дома. В прошлой статье мы говорили о новых профессиях, порожденных карантином и инструментах для их работы, а еще, с помощью всего лишь 70 строчек кода, накидали скелет многоточечной конференции с записью и скриншарингом.  Скриншаринг вообще очень востребованная штука, особенно в современных реалиях, когда на пике моды разные курсы саморазвития. Хочешь похудеть, потолстеть, заработать миллионы, сменить профессию, правильно воспитывать детей, достичь просветления, затемнения или убираться по Фен-Шую? В сети есть нужный тебе наставник и даже не один. Главный инструмент таких тренеров - проведение вебинаров, чаще всего платных.  И если браться разрабатывать свою систему вебинаров, то сразу появляется несколько вопросов:  Где разместить? Как реализовать? Как ограничить доступ?  Мы решили собрать все ответы воедино, так получилась эта статья.   Для запуска стриминга в эксплуатацию нужно оценить масштабы системы.  число пользователей стримеров; число входящих стримов; число пользователей подписчиков; число исходящих стримов; параметры видео стримов; временные периоды; география размещения серверов и подписчиков.  И на основе этих данных выбрать подходящую конфигурацию физического сервера или виртуального инстанса.  Примерные требования по характеристикам сервера для типовых задач указаны ниже:  Количество подписчиков CPUs RAM, GB Трафик, TB Пример использования до 200 4 8 5 Система видеонаблюдения до 500 8 16 6 Вебинары до 1000 16 64 9 Видеочат до 2000 20 96 10 Стриминг HD видео Если в вашем проекте планируется большее число подписчиков, не имеет смысла увеличивать технические характеристики одного сервера т.к. это приведет к появлению единой точки отказа.  В этом случае можно использовать технологии CDN из расчета 1 Edge сервер на 2000 подписчиков. Благодаря масштабированию, географическому и логическому разделению (с выделением функций транскодинга и доставки контента) можно гибко определить необходимый уровень производительности для каждого из серверов. Нагрузка на системные ресурсы сервера не должна превышать 80%. В этом случае, все подписчики получат видеопотоки с приемлемым качеством.   Достаточно часто CDN разворачивают и при небольшом числе пользователей, если планируется значительное количество трафика. Арифметика простая: 1 стрим это примерно 1 Mbps трафика, соответственно 1000 стримов - 1000 Mbps. Не всегда есть техническая и финансовая возможность подключить к серверу канал 10Gbps. Большая часть интернет провайдеров не могут предоставить канал более 400 Mbps, поэтому, чтобы транслировать потоки со скоростью 1000 Mbps понадобится три сервера.  Рассмотрим некоторые настройки WCS, от которых напрямую зависит конечное число зрителей и качество трансляции. По умолчанию, для WebRTC подключений доступно только 499 портов. Это ограничение задается в файле flashphoner.properties. При необходимости можно увеличить диапазон портов в строках  Внимательный читатель, конечно, возразит, что в указанном диапазоне 999 портов. Да, так и есть, но для передачи медиатрафика используются только четные порты. Поэтому по умолчанию доступно всего 499 соединений по WebRTC.  При расширении диапазона медиапортов, проверьте, что диапазон не пересекается с другими портами, используемыми в работе сервера и диапазоном динамических портов Linux (при необходимости можно его изменить)  Так же обратите внимание, что медиапорты используются только для WebRTC соединений. Поэтому, если вы отдаете поток по WebRTC, а зрители смотрят его по HLS на своих айфонах, проблема свободных портов становится не актуальна.  При стриминге в памяти создается и уничтожается много объектов с данными.  Эти объекты хранятся в Java heap, если не рассматривать случай транскодинга, при котором картинки хранятся в физической памяти сервера.  Heap (куча) – основной сегмент памяти, где Java VM хранит все ваши объекты. Когда вы хотите создать новый объект, но места в heap уже нет, JVM проводит garbage collection (сборку мусора), что значит, что JVM ищет в памяти все объекты, которые более не нужны, и избавляется от них. В момент работы garbage collection работа остальных процессов в JVM приостанавливается. Поэтому, для задач стриминга, крайне важно, чтобы эта пауза занимала как можно меньше времени.  Для этого в Java был разработан новый сборщик мусора — "Z Garbage Collector" (ZGC), позволяющий обеспечить низкую задержку при сборке мусора, не останавливая выполнения потоков приложения более чем на 10 миллисекунд, даже при работе с очень большой memory heap. Рекомендуется выделять под Java memory heap не менее, чем 1/2 физической памяти сервера. Например, если объем оперативной памяти сервера составляет 32 Гб, рекомендуется выделить 16 Гб.  Размер Java memory heap указывается в файле wcs-core.properties в строчках Значение по умолчанию - 1024 Мб. Что бы выделить под Java memory heap 16 ГБ укажите  Установим Z Garbage Collector в составе OpenJDK 12. 1.Скачиваем последнюю сборку OpenJDK 12 со страницы http://jdk.java.net/12/:  2.Распаковываемый полученный файл и перемещаем его содержимое в рабочую директорию: 3.Создаем символические ссылки на OpenJDK 12: 4.Если WCS был установлен ранее, комментируем или удаляем следующие строки в файле wcs-core.properties: и заменяем строку  на  5.Добавляем настройки для ZGC и логирования: Обычно этих настроек хватает для улучшения производительности сервера и подключения большого количества зрителей.  Итак, мы определились с выбором сервера или виртуального инстанса для WCS. Теперь переходим непосредственно к написанию кода функции скриншаринга для последующего добавления на сайт.  Архитектура решения для этой статьи: Фронтенд Web сервер  - организует интерфейс со стримером и зрителями.  WCS - обрабатывает входящий видеопоток от стримера и отдает его для воспроизведения зрителям.  Начнем развертывание с установки WCS. Следуем указаниям инструкции или запускаем виртуальный инстанс на Amazon, Google Cloud или DigitalOcean.  WCS так же можно запустить как контейнер в Docker. Выполняем настройку сервера согласно предыдущей главе и рекомендациям инструкции по подготовке к промышленной эксплуатации.   Теперь запускаем web сервер. В этой статье мы используем Nginx на CentOS 7. На Apache все будет конфигурироваться сходным образом. Если у вас уже есть сайт, к которому планируется добавить функционал скриншаринга, тогда готовить web сервер отдельно не нужно. Или можно развернуть web сервер на той же машине, что и WCS.   На web сервере создаем два файла: страницу будущего интерфейса скриншаринга и скрипт, который будет реализовывать работу. У нас это файлы — "screen-sharing-min.html" и "screen-sharing-min.js". Рядом с этими файлами нужно разместить скрипт основного API - "flashphoner.js", который можно скачать здесь. Или укажите путь до этого файла, если работы проводятся на той же машине, где установлен WCS.  Начнем с подготовки HTML страницы со всеми нужными элементами.  Подключаем скрипты:  На загрузку тела страницы навешиваем функцию запуска API:  И добавляем div-элемент для превью потока скриншаринга  и кнопку для запуска: Кода HTML страницы совсем немного: Теперь переходим к созданию JS скрипта для работы скриншаринга. Функция "init_api()" которая вызывается при загрузке HTML страницы инициализирует основной API   При нажатии на кнопку "Share Screen" будут последовательно выполняться две функции нашего скрипта  — функция  "connect()", которая будет устанавливать подключение к WCS по WebSocket  и функция  "startStreaming()", которая формирует и публикует поток скриншаринга на WCS Важное отличие от обычного стриминга  с веб камеры – чтобы захватить экран, а не камеру, в constraints нужно явно указать два параметра: Файл скрипта тоже достаточно компактный.  Всего 34 строчки с комментариями.  Сохраняем, запускаем и проверяем работу. Нажимаем на кнопку «Share Screen» и сообщаем браузеру, что именно будем шарить: весь экран, приложение или определенную вкладку браузера. Превью потока скриншаринга будет отображаться в div-элементе на HTML странице.  В коде скрипта мы жестко задали имя публикуемого потока - "mystream" Этот поток в дальнейшем может быть может быть записан, воспроизведен, транскодирован или ретранслирован по любой из технологий, поддерживаемых WCS Итак, все отлично работает. Теперь предлагаю рассмотреть, как можно реализовать простую меру защиты вашего контента — доступ к стриму с использованием Basic Auth. Настраиваем web сервер на использование Basic Auth.  Создаем файл .htpasswd: Первая команда уставит в системе утилиту для генерации файла .htpasswd. Вторая команда создаст файл по указанному пути и запросит пароль для пользователя "admin".  Ключ "-c" нужен только при первичной генерации файла. Для записи в файл  .htpasswd других учетных записей он не нужен.   Далее переходим к конфигам Nginx. Мы не выделяли настройки сайта в отдельный конфиг, поэтому делаем настройки в основном конфигурационном файле /etc/nginx/nginx.conf В секции http добавляем следующие строчки: Первая строка – строка приветствия, вторая путь к файлу .htpasswd На этом этапе можно перезапустить Nginx и посмотреть, заработал ли запрос пароля при открытии web интерфейса.  Далее настраиваем web server на работу по протоколу HTTPS. Дописываем следующие строчки в секцию "Server" в файле nginx.conf   Настраиваем реверсивное проксирование на WebSocket порт WCS  Еще раз перезапустите Nginx.  Теперь немного модифицируем код, который мы написали и протестировали в предыдущей главе, чтобы передавать логин и пароль. В параметре "urlServer" функции "Connect"  указываем обращение к серверу в виде "wss://login:password@wcs.yourdomain.com:443/wss" Теперь при обращении к HTML странице "screen-sharing-min.html" браузер будет запрашивать логин и пароль. И дальнейший доступ по WebSocket протоколу к WCS серверу также будет использовать логин и пароль, который мы задали в коде.  Таким образом мы развернули и протестировали пример скриншаринга и прикрутили к нему минимальную авторизацию по технологии Basic Auth. Для чего в 2021 году не нужно создавать и регистрировать свое расширение для Google Chrome и утруждать конечных пользователей установкой каких-то дополнительных компонентов — все работает "из коробки".  Удачного скриншаринга!  Наш демо сервер WCS на Amazon EC2 - Быстрое развертывание WCS на базе Amazon WCS на DigitalOcean - Быстрое развертывание WCS на базе DigitalOcean WCS в Docker - Запуск WCS как Docker контейнера  Трансляция экрана по WebRTC - Функция демонстрации и трансляции экрана из браузеров Описание файла настроек flashphoner.properties Описание файла настроек wcs-core.properties Документация по управлению памятью в Java Рекомендации по тонкой настройке сервера Документация по подготовке к промышленной эксплуатации WCS Screen Sharing в браузере по WebRTC Документация по Screen Sharing Web SDK Streaming video engineer