Марков цепи пропил
Максимально проклято
С огромной долей вероятности оно все сведется к +/- этому
iCTS: Iterative and Hierarchical Clock Tree Synthesis With Skew-Latency-Load Tree [ссылка]
Прикольная статья, в которой китайцы предлагают интересный метод оптимизации тактового дерева.
Если кратко, то синхронная цифровая схема держится на одном допущении: каждый триггер видит фронт тактового сигнала одновременно (иначе данные защёлкнутся раньше, чем вычисление закончилось, и триггер захватит некорректный результат).
Но "одновременно" физически невозможно. Сигнал идёт от одного источника до тысяч триггеров по металлическим проводам с сопротивлением и емкостью, разные триггеры находятся на разном расстоянии, и сигнал приходит в разное время (эта разница называется skew).
Решение - буферы. Они восстанавливают деградировавший фронт и добавляют контролируемую задержку, и если вставить буферы в нужных точках сети, суммарная задержка по всем путям выравнивается и каждый триггер получает фронт в +/- одно и то же время. Собственно, автоматическое построение такого дерева буферов и называется Clock Tree Synthesis.
Звучит как инженерная задача с однозначным решением, но внутри три цели, которые конфликтуют между собой: минимальный skew, минимальная длина проводов и минимальная latency. Получить всё три одновременно - NP-hard.
Стандартный CTS flow разбит на два независимых шага без обратной связи: сначала DME (алгоритм балансировки топологии тактового дерева) фиксирует структуру дерева: где провода соединяются и как ветвятся. Потом отдельный алгоритм (как правило, ван Гинекен) вставляет буферы уже в готовую структуру: обходит дерево снизу вверх, в каждом узле оценивает варианты буферов с учётом ёмкостной нагрузки downstream и выбирает лучший. Топологию изменить уже нельзя, поэтому алгоритм подстраивается под то, что есть.
Чтобы выровнять задержки на коротких ветках, DME добавляет wire elongations - буквально удлиняет провода змейкой, из-за чего растёт ёмкость и мощность. Буферы потом сайзятся под худший случай нагрузки, часто избыточно.
И это бьёт не только по мощности. Буферы занимают площадь кристалла, тактовые провода съедают ресурсы роутинга, рядом с кластерами буферов нужны decap-ячейки. Место, которое могло быть вычислениями, занято инфраструктурой доставки сигнала.
Тактовое дерево переключается каждый такт, независимо от того что делает логика. На высокопроизводительных процессорах это может отъедать до 50% от TDP, то есть если чип греется на 100 Вт, то до 50 Вт уходит только на доставку тактового сигнала, а не на вычисления (пара статей про это - [тык], [тык], [тык])
Исследователи из CUHK и Pengcheng Lab предложили строить топологию и буферизацию одновременно с явным trade-off между skew, latency и wirelength. В классическом DME точка слияния двух поддеревьев единственная, где задержки выравниваются, и никакого выбора нет. iCTS расширяет это до отрезка допустимых точек слияния, где любая точка даёт skew в пределах заданной границы, и на этом отрезке алгоритм выбирает точку, минимизирующую сумму с явными весами для latency и wirelength.
Поверх этого иерархическая кластеризация группирует синки не по геометрической близости, а по ёмкостной нагрузке, потому что физически близкие синки могут нагружать дерево по-разному и ломать балансировку. Результат кластеризации дополнительно оптимизируется отжигом. Буферы оцениваются до вставки, что позволяет отсекать плохие варианты раньше. После буферизации ISCA итеративно перезапускает BST-DME на зафиксированной топологии, каждый раз уточняя оценки задержек, пока skew не достигает целевого значения.
На бенчмарках ISCAS'89, OpenLane, OpenCores и ysyx (от 1248 до 22810 flip-flop) при 28nm результат такой: коммерческий P&R инструмент проигрывает iCTS на 39.5% по skew, 13.0% по latency и 18.5% по capacitance, OpenROAD - на 101.6%, 50.7% и 25.5% соответственно. По clock power коммерческий инструмент потребляет в среднем на 32% больше, OpenROAD - на 81% больше.
Хоть в максимальном бенчмарке всего ~23к триггеров, иерархическая архитектура iCTS должна масштабироваться. Не знаю, применит ли это кто-нибудь в продакшене, но звучит многообещающе
Прикольная статья, в которой китайцы предлагают интересный метод оптимизации тактового дерева.
Если кратко, то синхронная цифровая схема держится на одном допущении: каждый триггер видит фронт тактового сигнала одновременно (иначе данные защёлкнутся раньше, чем вычисление закончилось, и триггер захватит некорректный результат).
Но "одновременно" физически невозможно. Сигнал идёт от одного источника до тысяч триггеров по металлическим проводам с сопротивлением и емкостью, разные триггеры находятся на разном расстоянии, и сигнал приходит в разное время (эта разница называется skew).
Решение - буферы. Они восстанавливают деградировавший фронт и добавляют контролируемую задержку, и если вставить буферы в нужных точках сети, суммарная задержка по всем путям выравнивается и каждый триггер получает фронт в +/- одно и то же время. Собственно, автоматическое построение такого дерева буферов и называется Clock Tree Synthesis.
Звучит как инженерная задача с однозначным решением, но внутри три цели, которые конфликтуют между собой: минимальный skew, минимальная длина проводов и минимальная latency. Получить всё три одновременно - NP-hard.
Стандартный CTS flow разбит на два независимых шага без обратной связи: сначала DME (алгоритм балансировки топологии тактового дерева) фиксирует структуру дерева: где провода соединяются и как ветвятся. Потом отдельный алгоритм (как правило, ван Гинекен) вставляет буферы уже в готовую структуру: обходит дерево снизу вверх, в каждом узле оценивает варианты буферов с учётом ёмкостной нагрузки downstream и выбирает лучший. Топологию изменить уже нельзя, поэтому алгоритм подстраивается под то, что есть.
Чтобы выровнять задержки на коротких ветках, DME добавляет wire elongations - буквально удлиняет провода змейкой, из-за чего растёт ёмкость и мощность. Буферы потом сайзятся под худший случай нагрузки, часто избыточно.
И это бьёт не только по мощности. Буферы занимают площадь кристалла, тактовые провода съедают ресурсы роутинга, рядом с кластерами буферов нужны decap-ячейки. Место, которое могло быть вычислениями, занято инфраструктурой доставки сигнала.
Тактовое дерево переключается каждый такт, независимо от того что делает логика. На высокопроизводительных процессорах это может отъедать до 50% от TDP, то есть если чип греется на 100 Вт, то до 50 Вт уходит только на доставку тактового сигнала, а не на вычисления (пара статей про это - [тык], [тык], [тык])
Исследователи из CUHK и Pengcheng Lab предложили строить топологию и буферизацию одновременно с явным trade-off между skew, latency и wirelength. В классическом DME точка слияния двух поддеревьев единственная, где задержки выравниваются, и никакого выбора нет. iCTS расширяет это до отрезка допустимых точек слияния, где любая точка даёт skew в пределах заданной границы, и на этом отрезке алгоритм выбирает точку, минимизирующую сумму с явными весами для latency и wirelength.
Поверх этого иерархическая кластеризация группирует синки не по геометрической близости, а по ёмкостной нагрузке, потому что физически близкие синки могут нагружать дерево по-разному и ломать балансировку. Результат кластеризации дополнительно оптимизируется отжигом. Буферы оцениваются до вставки, что позволяет отсекать плохие варианты раньше. После буферизации ISCA итеративно перезапускает BST-DME на зафиксированной топологии, каждый раз уточняя оценки задержек, пока skew не достигает целевого значения.
На бенчмарках ISCAS'89, OpenLane, OpenCores и ysyx (от 1248 до 22810 flip-flop) при 28nm результат такой: коммерческий P&R инструмент проигрывает iCTS на 39.5% по skew, 13.0% по latency и 18.5% по capacitance, OpenROAD - на 101.6%, 50.7% и 25.5% соответственно. По clock power коммерческий инструмент потребляет в среднем на 32% больше, OpenROAD - на 81% больше.
Хоть в максимальном бенчмарке всего ~23к триггеров, иерархическая архитектура iCTS должна масштабироваться. Не знаю, применит ли это кто-нибудь в продакшене, но звучит многообещающе
🔥10 6👌1👻1
Forwarded from Канал респекта и уважухи 2.0
разработчик мессенджера Max может добиться эрекции только когда его жена грязно шепчет ему на ухо, что выбрала его, только потому что все другие мужики, которые её реально возбуждали, оказались недоступны, а не потому что она типа его реально любит и хочет
😁48🤡4🙏3👻2 1 1
Simple Recipe Works: Vision-Language-Action Models are Natural Continual Learners with Reinforcement Learning [ссылка]
Tldr: челы решили проверить, есть ли смысл в существующих методах Continual RL для обучения роботов, или можно обойтись простым Sequential Fine-Tuning с LoRA и on-policy RL.
Большие VLA-модели вроде OpenVLA или Pi-0 хорошо обобщаются, но ломаются при деплое в меняющейся среде. Чтобы агент мог адаптироваться к новым задачам через взаимодействие со средой, его нужно дообучать с RL постепенно, не имея доступа к данным предыдущих задач. Но есть проблема: Sequential Fine-Tuning в такой постановке ведёт к катастрофическому забыванию, модель переобучается на текущей задаче и теряет навыки предыдущих.
Существующие методы Continual RL решают это тремя способами: регуляризацией весов (EWC штрафует обновления параметров, важных для прошлых задач), воспроизведением прошлого опыта (Expert Replay и Dark Experience Replay хранят демонстрации или логиты и перемешивают их с текущим обучением) и изоляцией параметров (Dynamic Weight Expansion выделяет отдельный LoRA-адаптер на каждую задачу). Для больших моделей есть и более свежие подходы: SLCA применяет разные learning rate для разных слоёв, RETAIN после каждой задачи вмёрживает веса обратно в базовую модель с коэффициентом дисконтирования.
Авторы берут простейший Seq. FT с LoRA и GRPO и гоняют его вместе со всеми перечисленными методами на трёх VLA-моделях (OpenVLA-OFT, OpenVLA, Pi-0) и пяти бенчмарках (LIBERO-Object, LIBERO-Spatial, LIBERO-Long, RoboCasa, ManiSkill). И в результате Seq. FT с LoRA и GRPO выигрывает или не уступает во всех сетапах, при этом падение успешности на прошлых задачах меньше 2%, нередко уходя в минус, то есть обучение на новых задачах ещё и улучшает старые. EWC, SLCA и RETAIN хуже учатся новым задачам - ограничения на обновления параметров мешают не только забывать старое, но и усваивать новое, поэтому итоговый avg ниже. DWE вообще не получает transfer между задачами. Replay требует хранить демонстрации и при этом ничего не выигрывает. Zero-shot на незнакомых задачах у Seq. FT в большинстве сетапов не уступает модели, обученной сразу на всех задачах одновременно, то есть верхней границе качества. А там, где Seq. FT всё же отстаёт, хватает просто подольше потренировать слабые задачи.
Авторы объясняют это синергией трёх вещей. On-policy RL неявно удерживает политику близко к базовой, потому что обновления не могут сдвинуть вероятностную массу туда, где базовая политика почти не имеет поддержки. Большой размер модели помогает потому, что в пространстве миллиардов параметров обновление по новой задаче почти не затрагивает направления, важные для предыдущих. LoRA не даёт отдельным слоям переписываться полностью, при этом пластичность не страдает: on-policy обучение при разреженном вознаграждении информационно дёшево, и ёмкости адаптера хватает.
Пока все эксперименты проводились в симуляции. Решат ли авторы главную проблему RL -он не работает плохую масштабируемость в реальных средах, пока неизвестно. Но понаблюдать за развитием можно здесь [тык]
Tldr: челы решили проверить, есть ли смысл в существующих методах Continual RL для обучения роботов, или можно обойтись простым Sequential Fine-Tuning с LoRA и on-policy RL.
Большие VLA-модели вроде OpenVLA или Pi-0 хорошо обобщаются, но ломаются при деплое в меняющейся среде. Чтобы агент мог адаптироваться к новым задачам через взаимодействие со средой, его нужно дообучать с RL постепенно, не имея доступа к данным предыдущих задач. Но есть проблема: Sequential Fine-Tuning в такой постановке ведёт к катастрофическому забыванию, модель переобучается на текущей задаче и теряет навыки предыдущих.
Существующие методы Continual RL решают это тремя способами: регуляризацией весов (EWC штрафует обновления параметров, важных для прошлых задач), воспроизведением прошлого опыта (Expert Replay и Dark Experience Replay хранят демонстрации или логиты и перемешивают их с текущим обучением) и изоляцией параметров (Dynamic Weight Expansion выделяет отдельный LoRA-адаптер на каждую задачу). Для больших моделей есть и более свежие подходы: SLCA применяет разные learning rate для разных слоёв, RETAIN после каждой задачи вмёрживает веса обратно в базовую модель с коэффициентом дисконтирования.
Авторы берут простейший Seq. FT с LoRA и GRPO и гоняют его вместе со всеми перечисленными методами на трёх VLA-моделях (OpenVLA-OFT, OpenVLA, Pi-0) и пяти бенчмарках (LIBERO-Object, LIBERO-Spatial, LIBERO-Long, RoboCasa, ManiSkill). И в результате Seq. FT с LoRA и GRPO выигрывает или не уступает во всех сетапах, при этом падение успешности на прошлых задачах меньше 2%, нередко уходя в минус, то есть обучение на новых задачах ещё и улучшает старые. EWC, SLCA и RETAIN хуже учатся новым задачам - ограничения на обновления параметров мешают не только забывать старое, но и усваивать новое, поэтому итоговый avg ниже. DWE вообще не получает transfer между задачами. Replay требует хранить демонстрации и при этом ничего не выигрывает. Zero-shot на незнакомых задачах у Seq. FT в большинстве сетапов не уступает модели, обученной сразу на всех задачах одновременно, то есть верхней границе качества. А там, где Seq. FT всё же отстаёт, хватает просто подольше потренировать слабые задачи.
Авторы объясняют это синергией трёх вещей. On-policy RL неявно удерживает политику близко к базовой, потому что обновления не могут сдвинуть вероятностную массу туда, где базовая политика почти не имеет поддержки. Большой размер модели помогает потому, что в пространстве миллиардов параметров обновление по новой задаче почти не затрагивает направления, важные для предыдущих. LoRA не даёт отдельным слоям переписываться полностью, при этом пластичность не страдает: on-policy обучение при разреженном вознаграждении информационно дёшево, и ёмкости адаптера хватает.
Пока все эксперименты проводились в симуляции. Решат ли авторы главную проблему RL -
Dial-up 2.0, или гоним трафик в обход белых списков через звонки в ВК
Пока железки в пути, решил заняться насущным вопросом, который в последнее время что-то обострился.
VK-звонки работают через WebRTC с Selective Forwarding Unit, который пробрасывает SCTP DataChannel между участниками, не заглядывая внутрь. Помимо своего animoji-канала (id:1) VK туда ничего больше не кладёт, поэтому можно создать рядом свой DataChannel (id:2) и использовать его как двунаправленный пайп для произвольных данных. Весь трафик при этом идёт через TURN-серверы VK, которые находятся в белых списках - для DPI это выглядит как обычный звонок.
На стороне Creator'а (тот, у кого есть доступ в интернет) запускается Go relay и hook.js сниппет в браузере. Сниппет хукает RTCPeerConnection, перехватывает ICE-конфигурацию прямо из конструктора, после чего создаётся туннельный DataChannel и бриджится с локальным WebSocket'ом, через который relay раздаёт трафик наружу.
На стороне Joiner'а (тот, кто в зоне белых списков) всё чуть интереснее. Приложение открывает VK-звонок в WebView, поднимает VpnService, который перехватывает весь IP-трафик устройства, прогоняет его через tun2socks, дальше в SOCKS5 прокси на Go, и уже оттуда через WebSocket в тот же DataChannel. Go-часть собирается через gomobile в .aar и линкуется прямо в APK, поэтому можно обойтись без рута/termux.
На speed test получилось добиться 9.57 Мбит/с на скачивание, 4.15 Мбит/с на загрузку с задержкой 14 мс до Брюсселя с мобильной сети.
Есть моменты, которые можно улучшить и автоматизировать, но в целом пока пойдет.
Код/билды здесь [тык]
Пока железки в пути, решил заняться насущным вопросом, который в последнее время что-то обострился.
VK-звонки работают через WebRTC с Selective Forwarding Unit, который пробрасывает SCTP DataChannel между участниками, не заглядывая внутрь. Помимо своего animoji-канала (id:1) VK туда ничего больше не кладёт, поэтому можно создать рядом свой DataChannel (id:2) и использовать его как двунаправленный пайп для произвольных данных. Весь трафик при этом идёт через TURN-серверы VK, которые находятся в белых списках - для DPI это выглядит как обычный звонок.
На стороне Creator'а (тот, у кого есть доступ в интернет) запускается Go relay и hook.js сниппет в браузере. Сниппет хукает RTCPeerConnection, перехватывает ICE-конфигурацию прямо из конструктора, после чего создаётся туннельный DataChannel и бриджится с локальным WebSocket'ом, через который relay раздаёт трафик наружу.
На стороне Joiner'а (тот, кто в зоне белых списков) всё чуть интереснее. Приложение открывает VK-звонок в WebView, поднимает VpnService, который перехватывает весь IP-трафик устройства, прогоняет его через tun2socks, дальше в SOCKS5 прокси на Go, и уже оттуда через WebSocket в тот же DataChannel. Go-часть собирается через gomobile в .aar и линкуется прямо в APK, поэтому можно обойтись без рута/termux.
На speed test получилось добиться 9.57 Мбит/с на скачивание, 4.15 Мбит/с на загрузку с задержкой 14 мс до Брюсселя с мобильной сети.
Есть моменты, которые можно улучшить и автоматизировать, но в целом пока пойдет.
Код/билды здесь [тык]
419🔥140 26😁9👻3🦄1
Major update v0.1.0
Добавил поддержку телемоста. Это было то еще приключение, но в итоге работает. Главное - не загружать большие файлы с joiner’а, а то SFU, видимо, захлебывается и умирает. Также наформошлепил на электроне десктопные версии, чтобы не запускать снипет каждый раз из браузера + туда зашиты бинарники на go, чтобы не поднимать relay руками. Пока думаю над тем, как пересылать данные в видеопотоке минуя vpx (на случай, если дата-каналы прикроют), так как если просто слать фейковое видео, то из-за компрессии мы будем терять данные, и, кажется, даже автокоррекция ошибок здесь не поможет. В целом работы предстоит много: нужно искать какие сервисы еще могут помочь в обходе, автоматизировать создание/присоединение к звонкам, искать/править баги, улучшать пайплайны, и в целом подумать, как можно улучшить пользовательский опыт. Боюсь, что в соло у меня рук не хватит, поэтому если есть желание поучаствовать - welcome
Все билды/исходнки, по-классике здесь [тык, тык]
Добавил поддержку телемоста. Это было то еще приключение, но в итоге работает. Главное - не загружать большие файлы с joiner’а, а то SFU, видимо, захлебывается и умирает. Также наформошлепил на электроне десктопные версии, чтобы не запускать снипет каждый раз из браузера + туда зашиты бинарники на go, чтобы не поднимать relay руками. Пока думаю над тем, как пересылать данные в видеопотоке минуя vpx (на случай, если дата-каналы прикроют), так как если просто слать фейковое видео, то из-за компрессии мы будем терять данные, и, кажется, даже автокоррекция ошибок здесь не поможет. В целом работы предстоит много: нужно искать какие сервисы еще могут помочь в обходе, автоматизировать создание/присоединение к звонкам, искать/править баги, улучшать пайплайны, и в целом подумать, как можно улучшить пользовательский опыт. Боюсь, что в соло у меня рук не хватит, поэтому если есть желание поучаствовать - welcome
Все билды/исходнки, по-классике здесь [тык, тык]
11🔥59👻3 3
Блин, эмодзи с аниме из реакций пропали. Подайте админу бустов, пожалуйста
https://xn--r1a.website/boost/markovdrankthechains
UPD: Всем спасибо
https://xn--r1a.website/boost/markovdrankthechains
UPD: Всем спасибо
54 27🎉17 5🙏2💅1 1
Засылать данные по видеоканалу WebRTC - довольно интересная с инженерной точки зрения задача. На ум сразу приходит решение в виде стеганографии: внедрять в картинку последовательность пикселей определенных цветов на одной стороне, и расшифровывать на другой. Но, к сожалению, энкодер просто съест нужную информацию и на выходе мы получим мусор. Поэтому в голову пришла мысль: что, если мы встроимся в часть пайплайна аккурат до VP8? Для этого пришлось спустится на уровень ниже. Туннель работает поверх TrackLocalStaticSample - в нем pion отправляет VP8 фреймы как видеосемплы. Поэтому мы посылаем фреймы двух типов:
Keepalive - настоящие VP8 фреймы (interframe 17 байт, keyframe 30 байт каждый 60-й фрейм). Отправляются с частотой 25fps по таймеру когда нет данных. Нужны чтобы SFU/TURN считал видеопоток живым и не отключал
Data - фрейм данных: [0xFF][4 байта длина][payload]. Маркер 0xFF отличает от VP8 (у keyframe bit0=0, у interframe bit0=1, поэтому первый байт никогда не 0xFF)
Таким образом удается построить bidirectional канал связи, и отсылать данные как для download, так и для upload. Единственное ограничение - ширина канала за счет специфики, из-за чего скорость ограничена в среднем 1.2 (+/- 0.2) мб/с. Тем не менее такой поток довольно сложно заметить/перехватить (в случае, если начнут обрубать по сигнатурам/VP8 фреймам - их всегда можно обновить/зашифровать). Я бы, наверное, советовал пользоваться именно этим каналом, так как он еще и меньше нагружает инфраструктуру, и его обычно достаточно для базового взаимодействия в интернете.
Оно реализовано в обновленном релизе v0.1.5 - [Исходники], [Билды]
Сейчас там по умолчанию установлен DataChannel, для видео нужно переключиться в выпадающем списке. Для того, чтобы оно работало, необходимо, чтобы и у creator’a и у joiner’а совпадали каналы передачи данных (video - video, data channel - data channel). Так же необходимо, чтобы при заходе в звонок через video channel в интерфейсе была включена камера (реальную камеру оно не включает - можно не давать разрешения, так как поток все равно фейковый), потому что иначе нужный канал данных просто не откроется, и подключение провалится
Keepalive - настоящие VP8 фреймы (interframe 17 байт, keyframe 30 байт каждый 60-й фрейм). Отправляются с частотой 25fps по таймеру когда нет данных. Нужны чтобы SFU/TURN считал видеопоток живым и не отключал
Data - фрейм данных: [0xFF][4 байта длина][payload]. Маркер 0xFF отличает от VP8 (у keyframe bit0=0, у interframe bit0=1, поэтому первый байт никогда не 0xFF)
Таким образом удается построить bidirectional канал связи, и отсылать данные как для download, так и для upload. Единственное ограничение - ширина канала за счет специфики, из-за чего скорость ограничена в среднем 1.2 (+/- 0.2) мб/с. Тем не менее такой поток довольно сложно заметить/перехватить (в случае, если начнут обрубать по сигнатурам/VP8 фреймам - их всегда можно обновить/зашифровать). Я бы, наверное, советовал пользоваться именно этим каналом, так как он еще и меньше нагружает инфраструктуру, и его обычно достаточно для базового взаимодействия в интернете.
Оно реализовано в обновленном релизе v0.1.5 - [Исходники], [Билды]
Сейчас там по умолчанию установлен DataChannel, для видео нужно переключиться в выпадающем списке. Для того, чтобы оно работало, необходимо, чтобы и у creator’a и у joiner’а совпадали каналы передачи данных (video - video, data channel - data channel). Так же необходимо, чтобы при заходе в звонок через video channel в интерфейсе была включена камера (реальную камеру оно не включает - можно не давать разрешения, так как поток все равно фейковый), потому что иначе нужный канал данных просто не откроется, и подключение провалится
1🔥51 7 4 2🙏1
В v0.1.7 внес ряд UX улучшений + исправлений:
В режиме creator’а появилась мультиоконность - можно создавать кучу звонков в телемосте на разных каналах данных. Например, опять же, можно открыть DataChannel если нужно загрузить что-то объемное, и в другой вкладке - video channel, если, например, нужно будет закинуть кому-то файлы.
Так же в телемосте на десктопе автоматизировано добавление пользователя - больше не нужно нажимать "Добавить" при попытке подключиться. В целом удалось повысить стабильность, и теперь можно просто насоздавать ссылок в начале дня, и подключаться по мере необходимости чтобы не сажать батарейку + поправлены разные баги и реализованы предложения из github issues.
Актуальные сборки, как водится, [здесь]
В режиме creator’а появилась мультиоконность - можно создавать кучу звонков в телемосте на разных каналах данных. Например, опять же, можно открыть DataChannel если нужно загрузить что-то объемное, и в другой вкладке - video channel, если, например, нужно будет закинуть кому-то файлы.
Так же в телемосте на десктопе автоматизировано добавление пользователя - больше не нужно нажимать "Добавить" при попытке подключиться. В целом удалось повысить стабильность, и теперь можно просто насоздавать ссылок в начале дня, и подключаться по мере необходимости чтобы не сажать батарейку + поправлены разные баги и реализованы предложения из github issues.
Актуальные сборки, как водится, [здесь]
1.07K🔥28🎉4 2🙏1👻1