Размещение картинок потоков в микшере при помощи языка разметки¶
Описание¶
В сборке 5.2.1009 добавлена возможность описания собственных вариантов размещения картинок в микшере при помощи языка разметки на основе XML. Разработка собственного Java класса при этом не требуется.
Вариант размещения картинок представляет собой набор XML-файлов с расширением .mix
, расположенных в одном каталоге. Каждый файл должен описывать размещение картинок для определенного количества участников: 1, 2, 3, 4 и т.д. Имя файла должно начинаться с количества участников и следующего за ним символа подчеркивания, остальная часть имени файла должна содержать произвольный набор алфавитно-цифровых символов, например
1_test-mixer-layout-1-participant.mix
2_test-mixer-layout-2-participants.mix
3_test-mixer-layout-3-participants.mix
4_test-mixer-layout-4-participants.mix
...
Файлы, описывающие один вариант размещения картинок, должны располагаться в одном каталоге. Одному количеству участников должен соответствовать один и только один файл. Таким образом, смешивать в одном и том же каталоге два различных варианта не допускается.
Путь к этому каталогу может быть указан в настройке в файле flashphoner.properties
В этом случае данный вариант размещения картинок будет применяться по умолчанию ко всем микшерам на сервере
Также путь к каталогу можно указать в REST API запросе /mixer/startup
:
POST /rest-api/mixer/startup HTTP/1.1
HOST: 192.168.1.101:8081
Content-type: application/json
{
"uri": "mixer://mixer1",
"localStreamName": "mixer1_stream",
"hasVideo": true,
"hasAudio": false,
"mixerLayoutDir": "/opt/mixer1-layout"
}
Применение варианта размещения картинок к активному микшеру¶
Начиная со сборки 5.2.1480, вариант размещения картинок можно применить к активному микшеру
POST /rest-api/mixer/set_parameter HTTP/1.1
HOST: 192.168.1.101:8081
Content-type: application/json
{
"uri": "mixer://mixer1",
"mixerLayoutDir": "/opt/mixer1-layout"
}
Вернуться к размещению картинок по умолчанию можно, указав пустое значение параметра mixerLayoutDir
POST /rest-api/mixer/set_parameter HTTP/1.1
HOST: 192.168.1.101:8081
Content-type: application/json
{
"uri": "mixer://mixer1",
"mixerLayoutDir": ""
}
При этом будет применен класс размещения картинок, указанный в параметре микшера mixerLayoutClass
.
Формат файла описания картинок¶
XML-файл описания картинок должен соответствовать следующей схеме
Mixer layout XSD
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="body" type="bodyType"/>
<xs:complexType name="videoType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="value" type="xs:string"/>
<xs:attribute type="xs:int" name="x" default="0"/>
<xs:attribute type="xs:int" name="y" default="0"/>
<xs:attribute type="xs:string" name="width" default="0"/>
<xs:attribute type="xs:string" name="height" default="0"/>
<xs:attribute type="xs:string" name="align" default="LEFT"/>
<xs:attribute type="xs:string" name="watermark"/>
<xs:attribute type="xs:int" name="padding-left" default="0"/>
<xs:attribute type="xs:int" name="padding-right" default="0"/>
<xs:attribute type="xs:int" name="padding-top" default="0"/>
<xs:attribute type="xs:int" name="padding-bottom" default="0"/>
<xs:attribute type="xs:boolean" name="crop" default="false"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="divType">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:choice>
<xs:element name="video" type="videoType"/>
<xs:element name="div" type="divType"/>
<xs:element name="row" type="rowType"/>
</xs:choice>
</xs:sequence>
<xs:attribute type="xs:int" name="x" default="0"/>
<xs:attribute type="xs:int" name="y" default="0"/>
<xs:attribute type="xs:string" name="width" default="0"/>
<xs:attribute type="xs:string" name="height" default="0"/>
<xs:attribute type="xs:string" name="align" default="LEFT"/>
<xs:attribute type="xs:int" name="padding-left" default="0"/>
<xs:attribute type="xs:int" name="padding-right" default="0"/>
<xs:attribute type="xs:int" name="padding-top" default="0"/>
<xs:attribute type="xs:int" name="padding-bottom" default="0"/>
</xs:complexType>
<xs:complexType name="rowType">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:choice>
<xs:element name="video" type="videoType"/>
<xs:element name="div" type="divType"/>
<xs:element name="row" type="rowType"/>
</xs:choice>
</xs:sequence>
<xs:attribute type="xs:int" name="x" default="0"/>
<xs:attribute type="xs:int" name="y" default="0"/>
<xs:attribute type="xs:string" name="width" default="0"/>
<xs:attribute type="xs:string" name="height" default="0"/>
<xs:attribute type="xs:string" name="align" default="LEFT"/>
<xs:attribute type="xs:int" name="padding-left" default="0"/>
<xs:attribute type="xs:int" name="padding-right" default="0"/>
<xs:attribute type="xs:int" name="padding-top" default="0"/>
<xs:attribute type="xs:int" name="padding-bottom" default="0"/>
</xs:complexType>
<xs:complexType name="bodyType">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:choice>
<xs:element name="video" type="videoType"/>
<xs:element name="div" type="divType"/>
<xs:element name="row" type="rowType"/>
</xs:choice>
</xs:sequence>
<xs:attribute type="xs:string" name="watermark"/>
</xs:complexType>
</xs:schema>
Описания картинок проверяются по данной схеме, если валидация для какого-то количества участников не проходит, то будет использовано стандартное размещение картинок.
Поддерживаются следующие элементы:
body
- контейнер верхнего уровня для описания размещения картинок, представляет холст микшера. Может использоваться только один раз в одном файлеdiv
- контейнер для одной картинки, набора картинок или другого контейнера. Может использоваться в любом количестве, также может быть вложеннымvideo
- описание картинки, представляет собой поток в микшере. Может использоваться в любом количестве.
Элемент body
¶
Является контейнером верхнего уровня. Поддерживает следующие атрибуты:
watermark
- имя файла картинки, которая будет применена как водяной знак ко всему микшеру (добавлен, начиная со сборки 5.2.1051)
Элемент div
¶
Является контейнером для других div
или video
элементов. Поддерживает следующие атрибуты:
x
,y
- координаты левого верхнего угла на холсте микшера, в пикселяхwidth
- ширина на холсте микшера в пикселях или процентах от ширины родительского элементаheight
- высота на холсте микшера в пикселях или процентах от ширины родительского элементаpadding-left
,padding-right
,padding-top
,padding-bottom
- дополнение контейнера с каждой стороны, в пикселяхalign
- выравнивание на холсте микшера или в родительском контейнере
Атрибут align
может принимать следующие значения
LEFT
- элемент выровнен по левому краюRIGHT
- элемент выровнен по правому краюTOP
- элемент выровнен по верхней границеBOTTOM
- элемент выровнен по нижней границеCENTER
- элемент выровнен по центруBOTTOM_CENTER
- элемент выровнен по центру и по нижней границеTOP_CENTER
- элемент выровнен по центру и по верхней границеINLINE_HORIZONTAL
- элемент выровнен по правому верхнему углу ближайшего элемента слеваINLINE_HORIZONTAL_CENTER
- то же, что и в предыдущем случае, с центрированием по вертикалиINLINE_VERTICAL
- элемент выровнен по левому нижнему углу ближайшего элемента сверхуINLINE_VERTICAL_CENTER
- то же, что и в предыдущем случае, с центрированием по горизонтали
Если координаты левого верхнего угла заданы явно, то параметр align
не применяется
Элемент row
¶
В сборке 5.2.1052 добавлена поддержка элемента row, представляющего строку из одной или нескольких картинок. Поддерживает те же атрибуты, что и div
.
Элемент video
¶
Представляет картинку потока в контейнере. Поддерживает те же атрибуты, что и div
, с дополнительными атрибутами
crop
- увеличивает картинку и обрезает вокруг центраid
- идентификатор позиции для размещения картинки потока (добавлен в сборке 5.2.1950)
Атрибут crop
может принимать значения true
или false
.
Атрибут id
может принимать любые значения, но должен быть уникальным в пределах XML файла описания размещения картинок
Ширина картинки потока¶
Начиная со сборки 5.2.1052, ширина картинки может задаваться как в пикселях или процентах от ширины родительского элемента, так и в колонках. Для этого родительским элементом должен быть элемент row
, например
<?xml version="1.0" encoding="utf-8"?>
<body>
<row height="80%" align="CENTER">
<video width="1col" align="INLINE_HORIZONTAL_CENTER"/>
<video width="1col" align="INLINE_HORIZONTAL_CENTER"/>
</row>
</body>
В этом случае, при разборе файла описания размер одной колонки вычисляется, как ширина строки, деленная на количество картинок одного уровня, затем для всех картинок в строке устанавливается размер в соответствии с указанным в атрибуте width количеством колонок.
Пример картинки микшера для вышеприведенного описания
Warning
Не допускается смешивать в элементах одного уровня ширину в колонках и в процентах!
Начиная со сборки 5.2.1094, ширина в колонках может быть указана также и для дочерних элементов div
<?xml version="1.0" encoding="utf-8"?>
<body>
<div height="80%" align="CENTER">
<video width="1col" align="INLINE_HORIZONTAL_CENTER"/>
<video width="1col" align="INLINE_HORIZONTAL_CENTER"/>
</row>
</body>
Высота картинки потока¶
Начиная со сборки 5.2.1094, высота картинки может задаваться как в пикселях или процентах от высоты родительского элемента, так и в строках
<?xml version="1.0" encoding="utf-8"?>
<body>
<row height="1row" align="INLINE_VERTICAL_CENTER">
<div width="1col" height="100%" align="INLINE_HORIZONTAL_CENTER"><video width="100%" height="100%" align="CENTER"/></div>
<div width="1col" height="100%" align="INLINE_HORIZONTAL_CENTER"><video width="100%" height="100%" align="CENTER"/></div>
</row>
<row height="1row" align="INLINE_VERTICAL_CENTER">
<div width="1col" height="100%" align="INLINE_HORIZONTAL_CENTER"/>
<div width="1col" height="100%" align="INLINE_HORIZONTAL_CENTER"><video width="100%" height="100%" align="CENTER"/></div>
<div width="1col" height="100%" align="INLINE_HORIZONTAL_CENTER"/>
</row>
<row height="1row" align="INLINE_VERTICAL_CENTER" />
</body>
В этом случае, при разборе файла описания размер одной строки вычисляется, как высота родительского элемента, деленная на количество элементов одного уровня, затем для всех элементов устанавливается размер в соответствии с указанным в атрибуте height
количеством строк.
Пример картинки микшера для вышеприведенного описания
Warning
Не допускается смешивать в элементах одного уровня высоту в строках и в процентах!
Шаблон имени потока¶
Элемент video
может задавать шаблон имени потока. Например
отобразит только поток с именем test
, к другим потокам этот элемент применяться не будет.
Шаблон может быть задан регулярным выражением, например
В этом случае данный элемент отобразит поток с именем test1
, test1#room1
, test11
и т.д.
Если имя потока не соответствует ни одному шаблону, и в файле есть элемент video
без шаблона, то для этого потока будет использован этот элемент. Например, рассмотрим описание картинки для одного участника
<?xml version="1.0" encoding="utf-8"?>
<body xsi:noNamespaceSchemaLocation="schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<div width="320" height="180" padding-left="0" padding-right="0" padding-bottom="0" align="TOP_CENTER">
<video>test1.*</video>
</div>
<div width="320" height="180" padding-left="0" padding-right="0" padding-bottom="0" align="BOTTOM_CENTER">
<video>test2.*</video>
</div>
<div width="160" height="90" padding-left="0" padding-right="0" padding-bottom="0" align="RIGHT">
<video>.*</video>
</div>
</body>
В этом случае поток test3
будет отображен в последнем video
элементе.
Размещение потока в определенной позиции¶
В сборке 5.2.1950 добавлена возможность поместить картинку потока в заданную позицию по ее идентификатору. Это удобно в том случае, если невозможно воспользоваться шаблоном имени потока. Например, есть описание размещения картинок на три участника
<?xml version="1.0" encoding="utf-8"?>
<body>
<row height="100%" align="CENTER">
<video width="100%" id="desktop" align="CENTER"></video>
<row height="20%" align="BOTTOM">
<div width="1col" height="100%" align="INLINE_HORIZONTAL"><video width="95%" height="95%" id="speaker" align="RIGHT"/></div>
<div width="1col" height="100%" align="INLINE_HORIZONTAL"><video width="95%" height="95%" id="participant" align="LEFT"/></div>
</row>
</row>
</body>
В этом случае можно переместить поток в позицию с идентификатором desktop
при помощи REST API запроса /mixer/set_position
:
POST /rest-api/mixer/set_position HTTP/1.1
Host: localhost:8081
Content-Type: application/json
{
"uri": "mixer://mixer1",
"remoteStreamName": "stream3",
"videoPositionId": "desktop"
}
Также поток можно поместить в заданную позицию при его добавлении в микшер:
POST /rest-api/mixer/add HTTP/1.1
Host: localhost:8081
Content-Type: application/json
{
"uri": "mixer://mixer1",
"remoteStreamName": "stream1",
"videoPositionId": "speaker"
}
Добавление водяного знака в поток микшера или в поток участника¶
В сборке 5.2.1051 добавлена возможность указать в описании количества участников картинку в формате PNG, которая будет применена в качестве водяного знака ко всему потоку микшера или к потоку отдельного участника.
Для применения водяного знака ко всему потоку микшера необходимо добавить атрибут watermark
с указанием имени PNG файла к элементу body
:
<body watermark="image.png">
<row height="80%" align="CENTER">
<video width="50%" align="INLINE_HORIZONTAL_CENTER"/>
<video width="50%" align="INLINE_HORIZONTAL_CENTER"/>
</row>
</body>
При этом PNG файл должен располагаться в каталоге описания размещения картинок:
[root@demo ~]# ls -l /opt/GridLayout
total 20
-rw-r--r-- 1 root root 106 Sep 30 13:10 1_participants.mix
-rw-r--r-- 1 root root 204 Oct 11 12:11 2_participants.mix
-rw-r--r-- 1 root root 409 Oct 8 13:18 3_participants.mix
-rw-r--r-- 1 root root 591 Oct 8 13:00 4_participants.mix
-rw-r--r-- 1 root root 3434 Oct 7 08:57 image.png
Пример выходного потока микшера с наложенным водяным знаком
Водяной знак может быть наложен и на поток отдельного участника. Для этого необходимо добавить атрибут watermark
с указанием имени PNG файла к элементу video
:
<body>
<row height="80%" align="CENTER">
<video watermark="image.png" width="50%" align="INLINE_HORIZONTAL_CENTER"/>
<video width="50%" align="INLINE_HORIZONTAL_CENTER"/>
</row>
</body>
Описание демонстрации экрана для определенного количества участников¶
В сборке 5.2.1091 добавлена возможность описать вариант размещения картинок с демонстрацией экрана для определенного количества участников. Файлы описаний для демонстрации экрана должны иметь расширение .desktopmix
и располагаться в том же каталоге варианта размещения картинок, что и файлы описаний без экрана:
1_participants.desktopmix
2_participants.desktopmix
3_participants.desktopmix
1_participants.mix
2_participants.mix
3_participants.mix
Поток экрана определяется по шаблону имени. Пример описания для двух участников и одного потока экрана
3_participants.desktopmix
<?xml version="1.0" encoding="utf-8"?>
<body>
<row height="80%" align="TOP">
<video width="100%" align="CENTER">.*_desktop.*</video>
</row>
<row height="20%" align="BOTTOM">
<div width="1col" height="100%" align="INLINE_HORIZONTAL_CENTER"><video width="90%" align="CENTER"/></div>
<div width="1col" height="100%" align="INLINE_HORIZONTAL_CENTER"><video width="90%" align="CENTER"/></div>
</row>
</body>
Обратите внимание, что с точки зрения микшера поток экрана - такой же участник, поэтому дескриптор на 3 потока в микшере в данном случае описывает два потока участников плюс экран одного из участников
Если файла *.desktopmix
нет для заданного количества участников, и в микшер добавлен поток экрана, будет использовано стандартное размещение картинок для демонстрации экрана
Обработка ошибок¶
-
Если вариант размещения картинок не содержит описания для определенного количества участников, будет использован вариант, заданный в настройке
По умолчанию, используется
GridLayout
-
Если имя потока не соответствует ни одному шаблону в описании текущего количества участников, аудио и видео из такого потока не будет добавлено в выходной поток микшера
Примеры¶
Распределение картинок согласно именам потоков¶
Рассмотрим вариант размещения в микшере с выходным потоком 640x360 до трех участников. Обратите внимание, что в данном случае размеры картинок для всех потоков заданы явным образом, и не должны превышать размеров холста микшера.
Описание на одного участника:
1_test.mix
<?xml version="1.0" encoding="utf-8"?>
<body xsi:noNamespaceSchemaLocation="schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<div width="320" height="180" padding-left="0" padding-right="0" padding-bottom="0" align="TOP_CENTER">
<video crop="false">test1.*</video>
</div>
<div width="320" height="180" padding-left="0" padding-right="0" padding-bottom="0" align="BOTTOM_CENTER">
<video crop="false">test2.*</video>
</div>
</body>
Описание на двух участников
2_test.mix
<?xml version="1.0" encoding="utf-8"?>
<body xsi:noNamespaceSchemaLocation="schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<div width="320" height="180" padding-left="0" padding-right="0" padding-bottom="0" align="TOP_CENTER">
<video crop="false">test1.*</video>
</div>
<div width="320" height="180" padding-left="0" padding-right="0" padding-bottom="0" align="BOTTOM_CENTER">
<video crop="false">test2.*</video>
</div>
</body>
Описание на трех участников
3_test.mix
<?xml version="1.0" encoding="utf-8"?>
<body xsi:noNamespaceSchemaLocation="schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<div width="320" height="180" padding-left="0" padding-right="0" padding-bottom="0" align="LEFT">
<video crop="false">test1.*</video>
</div>
<div width="320" height="180" padding-left="0" padding-right="0" padding-bottom="0" align="RIGHT">
<video crop="false">test2.*</video>
</div>
<div width="320" height="180" padding-left="0" padding-right="0" padding-bottom="0" align="BOTTOM_CENTER">
<video crop="false">test3.*</video>
</div>
</body>
Пример отображения потока test1
Пример отображения двух потоков test1
и test2
Пример отображения потоков test1
, test2
и test3
Распределение картинок случайным образом, без строгого указания размера¶
Описание на одного участника:
1_participants.mix
Описание на двух участников
2_participants.mix
Описание на трех участников
3_participants.mix
<?xml version="1.0" encoding="utf-8"?>
<body>
<row height="50%" align="INLINE_VERTICAL_CENTER">
<div width="50%" height="100%" align="INLINE_HORIZONTAL_CENTER"><video width="100%" align="CENTER"/></div>
<div width="50%" height="100%" align="INLINE_HORIZONTAL_CENTER"><video width="100%" align="CENTER"/></div>
</row>
<row height="50%" align="INLINE_VERTICAL_CENTER">
<video width="100%" align="CENTER"/>
</row>
</body>
Пример отображения одного потока
Пример отображения двух потоков
Пример отображения трех потоков
Инструмент для отображения размещения картинок¶
В сборке 5.2.1035 добавлен инструмент для отображения вариантов размещения картинок, запускаемый из командной строки
cd /usr/local/FlashphonerWebCallServer/tools
bash ./mixer_layout_tool.sh /path/to/mixer_layout -o=/path/to/output
Инструмент выводит в указанный каталог одну картинку в формате PNG на один файл описания количества участников.
Поддерживаются следующие параметры:
/path/to/mixer_layout
- путь к каталогу варианта размещения картинок, обязательный параметр-o=/path/to/output
- путь к каталогу для вывода картинок-n=1
- количество участников в микшере, для которого должна быть выведена картинка; если не задано, будут выведены картинки для всех файлов описаний в данном варианте размещения-N=test1,test2,test3
- список имен потоков, используемых при формировании картинок: если имен потоков в списке меньше, чем заданное количество участников, будут автоматически сгенерированы именаstream0
,stream1
и т.д.-p=test
- префикс для генерации имен потоков, используемых при формировании картинок; имена генерируются последовательно, начиная с 0, напримерtest0
,test1
,test2
и т.д.-a
- отрисовка рамок индикатора речи вокруг всех картинок-s=640:360
- размер картинки, имитирующей поток участника, по умолчанию совпадает с размером микшера-h
- выводит список параметров инструмента
Инструмент использует текущие настройки микшера из файла flashphoner.properties
Примеры отображения¶
Рассмотрим примеры отображения варианта расположения картинок, приведенного выше
-
Картинка для одного участника с отображением рамки индикатора речи, имена потоков задаются явно
Файл
/tmp/1_test.png
-
Картинка для трех участников с указанием префикса и автоматическим формированием имен потоков
Файл
/tmp/3_test.png
Шаблоны имен потоков в описаниях данного варианта заданы явным образом как test1.*
, test2.*
, test3.*
. При автоматической генерации имен потоков отсчет начинается с 0, поэтому для данного количества участников были созданы имена test0
, test1
, test2
. В этом случае для недостающего потока test3
имя отображается как No stream for: test3.*
Обработка ошибок¶
-
Если размер картинки в описании варианта размещения картинок превышает размеры холста микшера, инструмент выведет сообщение об ошибке, файл PNG не будет сгенерирован:
Если создать микшер с таким вариантом размещения картинок, микшер будет закрыт с таким же сообщением об ошибке.13:54:49,232 INFO toryLayoutController - Mixer got 2 frames. Using 2_test.mix descriptor Computed layout would produce exception: java.lang.RuntimeException: Computed layout element: Layout{point=java.awt.Point[x=-106,y=0], dimension=java.awt.Dimension[width=852,height=478], frame:true} out of bounds Please check configuration for this set of participants: [test1, test2]
-
Если для какого-то количества участников нет файлов описания
*.mix
и*.desktopmix
, инструмент выведет для этого количества участников картинку с суффиксом_fallback
, используя стандартное размещение из настроек WCS.
Реализация стандартных размещений картинок на языке разметки¶
В архиве Layouts.tar.gz
приведены примеры реализации стандартных размещений картинок в микшере, совместимый со сборками WCS, начиная с 5.2.1094 и новее
Архив содержит следующие каталоги:
-
GridLayout
- реализация размещения картинок сеткой с промежутками между картинками
-
CenterNoPaddingGridLayout
- реализация размещения картинок сеткой без промежутков между картинками
-
СropNoPaddingGridLayout
- реализация размещения картинок сеткой без промежутков между картинками c увеличением и обрезкой вокруг центральной части кадра
-
samples
- каталог с примерами картинок выходного потока микшера
Использование¶
-
Распаковать архив в каталог
/opt
-
В файле настроек
либо указывать нужное размещение при создании микшера по REST APIflashphoner.properties
указать нужное размещение картинок в качестве используемого по умолчанию
Реализация размещения "картинка-в-картинке"¶
Чтобы разместить одну из картинок, например, трансляцию рабочего стола, фоном для картинок остальных потоков, необходимо элемент row
, в котором отображается рабочий стол, сделать родительским для элементов row
, содержащих картинки остальных потоков, например:
<?xml version="1.0" encoding="utf-8"?>
<body>
<row height="100%" align="CENTER">
<video width="100%" align="CENTER">.*_desktop.*</video>
<row height="20%" align="BOTTOM">
<div width="1col" height="100%" align="INLINE_HORIZONTAL"/>
<div width="1col" height="100%" align="INLINE_HORIZONTAL"><video width="95%" height="95%" align="CENTER"/></div>
<div width="1col" height="100%" align="INLINE_HORIZONTAL"><video width="95%" height="95%" align="CENTER"/></div>
<div width="1col" height="100%" align="INLINE_HORIZONTAL"><video width="95%" height="95%" align="CENTER"/></div>
<div width="1col" height="100%" align="INLINE_HORIZONTAL"/>
</row>
</row>
</body>
Пример описания размещения картинок до 10 участников + 1 поток рабочего стола приведен в архиве FullscreenDesktopLayout.tar.gz
FullscreenDesktopLayout.tar.gz
Поток рабочего стола должен иметь имя с суффиксом _desktop
, например user1_desktop-room123456