Overview

Since build 5.2.1009 it is possible to to configure custom mixer layout with a special XML-based language. In this case, no need to develop custom Java class.

Custom mixer layout is a set of XML files with .mix extension placed in the same folder. Every file should describe layout for a certain number of participants: 1, 2, 3, 4 etc. File name should start from participants number followed by understrike character, the rest of file name should contain various alphanumeric characters, for example

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
...

One mixer layout descripotion files should be placed in one folder. One participans count should be described by one, and only one, file. Mixing of two layouts in the same folder is not allowedТаким образом, смешивать в одном и том же каталоге два различных варианта не допускается.

A full path to mixer layout folder may be set with the following parameter in flashphoner.properties file

mixer_layout_dir=/opt/test-mixer-layout

In this case, the layout will be applied by default to all the mixers on the server.

Also, the path to mixer layout folder can be passed in REST API query /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"
}

Layout description file format

Layout description XML file must conform tho the following XSD scheme

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" 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 type="xs:int" name="x" use="optional" default="0"/>
        <xs:attribute type="xs:int" name="y" use="optional" default="0"/>
        <xs:attribute type="xs:int" name="width" use="optional" default="0"/>
        <xs:attribute type="xs:int" name="height" use="optional" default="0"/>
        <xs:attribute type="xs:int" name="padding-left" use="optional" default="0"/>
        <xs:attribute type="xs:int" name="padding-right" use="optional" default="0"/>
        <xs:attribute type="xs:int" name="padding-top" use="optional" default="0"/>
        <xs:attribute type="xs:int" name="padding-bottom" use="optional" default="0"/>
        <xs:attribute type="xs:string" name="align" use="optional" default="LEFT"/>
        <xs:attribute type="xs:boolean" name="crop" use="optional" default="false"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
  <xs:complexType name="divType">
    <xs:choice minOccurs="1">
      <xs:element name="video" type="videoType"/>
      <xs:element type="divType" name="div"/>
    </xs:choice>
    <xs:attribute type="xs:int" name="x" use="optional" default="0"/>
    <xs:attribute type="xs:int" name="y" use="optional" default="0"/>
    <xs:attribute type="xs:int" name="width" use="optional" default="0"/>
    <xs:attribute type="xs:int" name="height" use="optional" default="0"/>
    <xs:attribute type="xs:int" name="padding-left" use="optional" default="0"/>
    <xs:attribute type="xs:int" name="padding-right" use="optional" default="0"/>
    <xs:attribute type="xs:int" name="padding-top" use="optional" default="0"/>
    <xs:attribute type="xs:int" name="padding-bottom" use="optional" default="0"/>
    <xs:attribute type="xs:string" name="align" use="optional" default="LEFT"/>
  </xs:complexType>
  <xs:complexType name="bodyType">
    <xs:sequence minOccurs="1">
      <xs:choice>
        <xs:element type="divType" name="div"/>
        <xs:element type="videoType" name="video"/>
      </xs:choice>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

The following elements are supported:

div element

The div element is a container for other div or video elements. The followin attributes are supported:

align attribute supports the following possible values

If left top corner coordinates are set explicitly, align attribute is not applied

video element

Represents stream picture in parent container. The same attributes are supported as div element, with additional attribute

crop attribute may be true или false (by default).

A stream name template can be set in video element. For example

<video>test</video>

will display only stream named 'test', and will not be applied to any stream with other name.

The template can be set as regular expression, for example

<video>test1.*</video>

In this case this element can display streams named test1, test1#room1, test11 etc

If the stream name does not meet any template in the file, and there is empty video element in the file, this element will be used for that stream. For example, here is a description for one participant

<?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>

In this case test3 will be displayed in last video element

Configuration errors handling

1. If the mixer layout contains no description file for a certain participants number, the layout class set in the following parameter will be applied

mixer_layout_class=com.flashphoner.media.mixer.video.presentation.GridLayout

By default, GridLayout will be used

2. If stream name does not meet any template in description file for a current number of participants, audio and vido from this stream will not be added to mixer output stream

Custom layout example

Lets' create a custom mixer layout for 640x360 mixer stream up to three participants. Note that all the picture sizes should be set explicitly, and should not exceed mixer canvas size.

One participant description:

<?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>

Two participans description

<?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>

Three participants description

<?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>

The mixer with test1 stream output example

The mixer with test1 and test2 streams output example

The mixer with test1, test2, test3 streams output example

Custom layout displaying tool

Since build 5.2.1035 custom mixer layout displaying tool is added. The tool should be launched from command line

cd /usr/local/FlashphonerWebCallServer/tools
bash ./mixer_layout_tool.sh /path/to/mixer_layout -o=/path/to/output

The tool writes mixer layout pictures to the folder defined, one PNG picture per one layout descriptor file

The following parameters are supported:

The tool uses current mixer settings from flashphoner.properties file

Displaying examples

Look at pictures displaying examples for the custom layout described above

1. The picture for one participant with speech indicator displaying, stream names are set explicitly

bash ./mixer_layout_tool.sh /opt/mixer_layout -o=/tmp -N=test1,test2,test3 -n=1 -a

Output file /tmp/1_test.png

2. The picture for three participants, stream names are formed automatically with the prefix set

bash ./mixer_layout_tool.sh /opt/mixer_layouts -o=/tmp -p=test -n=3

Output file /tmp/3_test.png

Stream names templates in this layout descriptors are set explicitly as test1.*, test2.*, test3.*. When stream names are generated automatically, streams count starts from 0, therefore the following names were generated for this participants count: test0, test1, test2. In this case, for missed stream test3 name is displayed as No stream for: test3.*

Error handling

If one of the pictures size in custom layout descriptor exceeds mixer canvas size, the tool will display the following error message, and PNG file will not be generated:

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]

If a mixer is created with such custom layout, the mixer will be closed with the same error message.