Building a 16 tiles mosaic with FFMPEG

At work we recently (not that recently) we purchased a HDMI encoder. The product comes with 16 HDMI inputs and outputs everything to the network to be consumed via RTSP, RTMP, HLS and more. However the bloody device doesn’t bring any embedded solution to merge all the outputs into a single screen. You have to treat it separately. Crazy, right?!

So, the solution then was to find something that would build the mosaic of the 16 outputs. I looked quickly for a opensource tool that would do that for you, but didn’t find anything useful. Then, had to go to old friend linux and its gizmos.

FFMPEG, I knew would do the job, but as always it would take some tinkering and lots or reading…I had no choice but go with it.. and to my surprise was quicker, simpler and funnier than I thought.

Enough with the mumbling…show me the code!

First, I need a server to collect all the streams from the encoder and then publish to be viewed somewhere else. VLC maybe. This server, had to be able to receive a single stream and then publish it.. yes we are talking about NGINX.

The ubuntu/debian package doesnt come with the RTMP server plugin enabled and you have to compile from source to have it included.
Install the dependencies for the NGINX in your selected server.

$ sudo apt-get install build-essential libpcre3 libpcre3-dev libssl-dev

Then get the latest version of the NGINX source:>

wget https://nginx.org/download/nginx-1.14.0.tar.gz
git clone https://github.com/arut/nginx-rtmp-module
tar -xvf nginx-1.14.0.tar.gz
cd nginx-1.14.0
./configure --add-module=../nginx-rtmp-module/
make -j8
sudo make install

Open your config file, located by default at /usr/local/nginx/conf/nginx.conf and add the following at the very end of the file:

rtmp {
server {
listen 1935;
chunk_size 4096;
application live {
live on;
record off;
}
}
}

Voilá! now, you just need to start the NGINX with the RTMP module and it will be ready to receive the streams. Latter on I discovered that more configurations on the NGINX config file was needed. Here is the final piece for your amusement.

#user nobody;
#user root;
worker_processes 1;
error_log logs/error.log debug;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 8080;
server_name localhost;
location /stat {
rtmp_stat all;
rtmp_stat_stylesheet stat.xsl;
}
location /stat.xsl {
# you can move stat.xsl to a different location
root /usr/build/nginx-rtmp-module;
}
# rtmp control
location /control {
rtmp_control all;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
rtmp {
server {
listen 1935;
chunk_size 4096;
ping 30s;
notify_method get;
application live {
live on;
record off;
allow publish all;
allow play all;
}
}
}

The config above is basically changing NGINX to run on port 8080 as I had apache2 already installed on the same machine..
Now, the FFMPEG part.

I basically used this link as reference – https://trac.ffmpeg.org/wiki/Create a mosaic out of several input videos to have my stuff done. The only difference that needed to be taken into consideration is that instead of four tiles, I wanted 16. So I just applied the same logic and the following gigantic command is formed:

/usr/bin/ffmpeg -analyzeduration 10M -probesize 10M -re -i http://encoderaddress/0.ts
-i http://encoderaddress/0.ts -i http://encoderaddress/0.ts -i http://encoderaddress/0.ts
-i http://encoderaddress/0.ts -i http://encoderaddress/0.ts -i http://encoderaddress/0.ts
-i http://encoderaddress/0.ts -i http://encoderaddress/0.ts -i http://encoderaddress/0.ts
-i http://encoderaddress/0.ts -i http://encoderaddress/0.ts -i http://encoderaddress/0.ts
-i http://encoderaddress.ts -i http://encoderaddress/0.ts -i http://encoderaddress/0.ts
-filter_complex "
nullsrc=size=1920x1080 [base];
[0:v] setpts=PTS-STARTPTS, scale=480x270 [video1];
[1:v] setpts=PTS-STARTPTS, scale=480x270 [video2];
[2:v] setpts=PTS-STARTPTS, scale=480x270 [video3];
[3:v] setpts=PTS-STARTPTS, scale=480x270 [video4];
[4:v] setpts=PTS-STARTPTS, scale=480x270 [video5];
[5:v] setpts=PTS-STARTPTS, scale=480x270 [video6];
[6:v] setpts=PTS-STARTPTS, scale=480x270 [video7];
[7:v] setpts=PTS-STARTPTS, scale=480x270 [video8];
[8:v] setpts=PTS-STARTPTS, scale=480x270 [video9];
[9:v] setpts=PTS-STARTPTS, scale=480x270 [video10];
[10:v] setpts=PTS-STARTPTS, scale=480x270 [video11];
[11:v] setpts=PTS-STARTPTS, scale=480x270 [video12];
[12:v] setpts=PTS-STARTPTS, scale=480x270 [video13];
[13:v] setpts=PTS-STARTPTS, scale=480x270 [video14];
[14:v] setpts=PTS-STARTPTS, scale=480x270 [video15];
[15:v] setpts=PTS-STARTPTS, scale=480x270 [video16];
[base][video1] overlay=shortest=0 [tmp1];
[tmp1][video2] overlay=shortest=0:x=480 [tmp2];
[tmp2][video3] overlay=shortest=0:x=960 [tmp3];
[tmp3][video4] overlay=shortest=0:x=1440 [tmp4];
[tmp4][video5] overlay=shortest=0:y=270 [tmp5];
[tmp5][video6] overlay=shortest=0:x=480:y=270 [tmp6];
[tmp6][video7] overlay=shortest=0:x=960:y=270 [tmp7];
[tmp7][video8] overlay=shortest=0:x=1440:y=270 [tmp8];
[tmp8][video9] overlay=shortest=0:y=540 [tmp9];
[tmp9][video10] overlay=shortest=0:x=480:y=540 [tmp10];
[tmp10][video11] overlay=shortest=0:x=960:y=540 [tmp11];
[tmp11][video12] overlay=shortest=0:x=1440:y=540 [tmp12];
[tmp12][video13] overlay=shortest=0:y=810 [tmp13];
[tmp13][video14] overlay=shortest=0:x=480:y=810 [tmp14];
[tmp14][video15] overlay=shortest=0:x=960:y=810 [tmp15];
[tmp15][video16] overlay=shortest=0:x=1440:y=810
" -c:v libx264 -c:a aac -f flv rtmp://NGINXSERVER/live/mosaic

After running the FFMPEG command ( it does take a while to process everything), the url rmtp://NGINXSERVER/live/mosaic is ready to be consumed by VLC or any other player of your choice.

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *