Table of Contents
This is effort to create containerized services for Wireguard VPN, Zookeeper, PostgreSQL database, MediaMTX proxy with ffmpeg, dynamic DNS updater.
The goal is to enable automatic connection of Media Recorder instances to single Media Proxy Platform.
Each Media Recorder instance should open the VPN tunnel, using Wireguard VPN. That enables direct communication with the MediaMTX proxy, as well as with other services.
Once the VPN tunnel is open, Media Recorder instance should register itself to the Zookeeper, e.g. it should provide its IP address, so that MediaMTX and other services can access the Media Recorder instance.
That is a helper service, or a provider of raw TCP and HTTP interface, to obtain a list of registered Media Recorder instances.
MediaMTX proxy will accept RTMP video stream(s), and start the ffmpeg utility to forward streams to the Media Recorder instances.
The DuckDNS updater will update the DNS record aeromonitor.duckdns.org with the correct public IP address, so that the Media Proxy Platform will be available for the VPN clients.
The SQL database servers merly to store Wireguard VPN peer data, and interface configuration. This project provides some initial SQL file(s) to populate it.
There are few things to check before you start.
This project use and has dependency on Docker community edition software packages. To install it, use
apt update
apt install apt-transport-https curl
and add the Docker APT repository locally.
mkdir -p /etc/apt/keyrings/
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
and
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Once the repository is defined, run package index update again.
apt update
and install Docker.
apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
You might consider testing your installation
systemctl is-active docker
and
docker run hello-world
which is optional step.
Next requirement are the free TCP and UDP ports that should be available for services to bind. Here is the table that defines which ports are, by default, used for this project.
| Protocol | Port | Service |
|---|---|---|
| UDP | 56820 | Wireguard VPN |
| TCP | 1935 | MediaMTX RTMP |
| TCP | 2181 | ZooKeeper |
| TCP | 5001 | Media Nodes |
| TCP | 5002 | Media Nodes |
| TCP | 5432 | PostgreSQL |
| TCP | 8888 | WG Portal Web |
To check that none of the existing services on the system occupied ports from the table, issue
for TCP in 1935 2181 5001 5002 5432 8888 ; do nc -z localhost $TCP ; if [ $? -eq 0 ] ; then echo "TCP port $TCP occupied." ; else echo "TCP port $TCP available." ; fi ; done
The output should tell you that all ports are available. If not, some services might not start at all, causing the Media Proxy Platform to malfunction.
To build the Debian package use
deb/create-deb-package.sh
program. It will pack all the files into single *.deb file. You might use it to install all into /opt/media-proxy-platform and autostart the services, e.g. Docker containers. Please note that you might need to install dpkg-dev program package first.
If the prerequisites are met at this point, try to install and start all with
apt install ./media-proxy-platform-1.0.0-0.deb
command. E.g.
Reading package lists... Done
Building dependency tree
Reading state information... Done
Note, selecting 'media-proxy-platform' instead of './media-proxy-platform-1.0.0-0.deb'
The following packages were automatically installed and are no longer required:
libhiredis0.14 libjemalloc2 liblua5.1-0 lua-bitop lua-cjson postgresql redis-server redis-tools
Use 'apt autoremove' to remove them.
The following NEW packages will be installed:
media-proxy-platform
0 upgraded, 1 newly installed, 0 to remove and 61 not upgraded.
Need to get 0 B/18.6 kB of archives.
After this operation, 1049 kB of additional disk space will be used.
Get:1 /var/tmp/media-proxy-platform-1.0.0-0.deb media-proxy-platform amd64 1.0.0-0 [18.6 kB]
Selecting previously unselected package media-proxy-platform.
(Reading database ... 128494 files and directories currently installed.)
Preparing to unpack .../media-proxy-platform-1.0.0-0.deb ...
Unpacking media-proxy-platform (1.0.0-0) ...
Setting up media-proxy-platform (1.0.0-0) ...
INFO: Building Media Nodes docker image ...
[+] Building 48.6s (23/23) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 2.76kB 0.0s
=> [internal] load metadata for docker.io/library/eclipse-temurin:17-jdk-noble 1.7s
=> [internal] load metadata for docker.io/library/eclipse-temurin:17-jre-noble 1.7s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [stage-1 1/3] FROM docker.io/library/eclipse-temurin:17-jre-noble@sha256:fe29e96933d584ff5f2f8efa148103517974 4.3s
=> => resolve docker.io/library/eclipse-temurin:17-jre-noble@sha256:fe29e96933d584ff5f2f8efa148103517974941f72e6 0.0s
=> => sha256:fe29e96933d584ff5f2f8efa148103517974941f72e68e6db13e1888e9919cfa 7.85kB / 7.85kB 0.0s
. . .
At the end of the output, the table shows if the containers has been successfully started.
[+] Running 6/6
✔ Container duckdns Running 0.0s
✔ Container postgres-db Healthy 5.8s
✔ Container wg-portal Started 0.4s
✔ Container media-nodes Started 0.2s
✔ Container zookeeper Started 0.2s
✔ Container mediamtx Started 0.2s
Later are details how to inspect and possibly manually (re)start containers.
Since Debian package is just a handy way to pack all together and invoke few docker ... commands, that step can be skipped entirely. However, pay attention to the prerequisites, since you need to have Docker community edition software packages installed on your host system.
Clone the repository, e.g.
git clone https://www.github.com/idelac3/media-proxy-platform.git
Enter the folder
cd media-proxy-plaform
and continue from here.
Next what you can do, is to manually build the idelac/media-nodes image.
cd media-nodes
docker build . -t idelac/media-nodes
cd ..
Then start the services.
docker compose up -d
and provide the initial data to the PostgreSQL database, for the wg-portal service.
docker exec -i postgres-db psql --quiet --username=wgportal --dbname=wgportal --file=/var/lib/import/wgportal.sql
Please check the folder postgresql-import/ for the proper name of the SQL file(s). In this example, its wgportal.sql. In the future this folder might contain more than one SQL file.
If you followed all the steps till here, with success, consider Administration section as next.
The main folder which keeps the docker compistion YAML file is at /opt/media-proxy-platform path.
root@idelac-ubuntu20-mmp:/opt/media-proxy-platform# ls -l
total 24
-rw-rw-r-- 1 root root 3442 Dec 23 09:16 compose.yaml
drwxrwxr-x 2 root root 4096 Dec 23 09:17 media-nodes
drwxrwxr-x 2 root root 4096 Dec 23 09:17 mediamtx
drwx------ 19 systemd-coredump root 4096 Dec 23 09:26 postgresql-data
drwxrwxr-x 2 root root 4096 Dec 23 09:17 postgresql-import
drwxrwxr-x 4 root root 4096 Dec 23 09:17 wg-portal
root@idelac-ubuntu20-mmp:/opt/media-proxy-platform#
The compose.yaml is the main entry point, which is used by the docker do initialize container(s). It defines all the services, network, port numbers, etc.
Subfolders like wg-portal are used as volumes that are mounted by the running services inside containers.
Ensure that the workding folder is /opt/media-proxy-platform which contains docker compose YAML file.
To check the current state of the containers, issue
docker compose ps
command. E.g.
root@idelac-ubuntu20-mmp:/opt/media-proxy-platform# docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
duckdns lscr.io/linuxserver/duckdns:latest "/init" duckdns About an hour ago Up About an hour
media-nodes idelac/media-nodes "/__cacert_entrypoin…" media-nodes About an hour ago Up About an hour
mediamtx bluenviron/mediamtx:1.15.5-ffmpeg "/mediamtx" mediamtx About an hour ago Up About an hour
postgres-db postgres:17 "docker-entrypoint.s…" db About an hour ago Up About an hour (healthy) 127.0.0.1:5432->5432/tcp
wg-portal wgportal/wg-portal:v2 "/app/wg-portal" wg-portal About an hour ago Up About an hour 127.0.0.1:2181->2181/tcp, 0.0.0.0:1935->1935/tcp, [::]:1935->1935/tcp, 0.0.0.0:8888->8888/tcp, [::]:8888->8888/tcp, 127.0.0.1:5001-5002->5001-5002/tcp, 8787/tcp, 51820/udp, 0.0.0.0:56820->56820/udp, [::]:56820->56820/udp
zookeeper zookeeper:3.9.4-jre-17 "/docker-entrypoint.…" zookeeper About an hour ago Up About an hour
root@idelac-ubuntu20-mmp:/opt/media-proxy-platform#
Printout shows which containers are up and running. In some rare casese, some services might be down due to configuration issue, of port being already occupied by another process on the host system, etc.
To manually start the docker containers, issue
docker compose up -d
That should bring up all the services, and display the table with the result.
To bring down all, issue
docker compose down
Note that the docker daemon takes care of autostarting the containers during the system boot phase.
To examine the log of the service or a container, use docker logs command.
E.g.
docker logs zookeeper
will printout the logs from the zookeeper service. Each service inside a docker container writes to std.out log, which can be accessed by the docker log command. This can be useful to examine if the service works properly.
The zookeeper service is holds Media Recorder registrations. Each Media Recorder instance will register itself to the zookeeper service, providing it's IP address as data, which is then used by the MediaMTX proxy to properly forward video stream(s).
To check that the service works properly, first examine the log output.
root@idelac-ubuntu20-mmp:/opt/media-proxy-platform# docker logs zookeeper | grep -v INFO
ZooKeeper JMX enabled by default
Using config: /conf/zoo.cfg
2025-12-23 09:26:19,243 [myid:] - ERROR [main:o.a.z.s.q.QuorumPeerConfig@702] - Invalid configuration, only one server specified (ignoring)
2025-12-23 09:26:19,246 [myid:1] - WARN [main:o.a.z.s.q.QuorumPeerMain@139] - Either no config or no quorum defined in config, running in standalone mode
2025-12-23 09:26:19,249 [myid:1] - ERROR [main:o.a.z.s.q.QuorumPeerConfig@702] - Invalid configuration, only one server specified (ignoring)
2025-12-23 09:26:19,396 [myid:1] - WARN [main:o.e.j.s.h.ContextHandler@1662] - o.e.j.s.ServletContextHandler@4f32a3ad{/,null,STOPPED} contextPath ends with /*
2025-12-23 09:26:19,396 [myid:1] - WARN [main:o.e.j.s.h.ContextHandler@1673] - Empty contextPath
2025-12-23 09:26:19,450 [myid:1] - WARN [main:o.e.j.s.ConstraintSecurityHandler@759] - ServletContext@o.e.j.s.ServletContextHandler@4f32a3ad{/,null,STARTING} has uncovered http methods for path: /*
2025-12-23 09:26:19,481 [myid:1] - WARN [main:o.a.z.s.ServerCnxnFactory@337] - maxCnxns is not configured, using default value 0.
. . .
The log file is filtered, we don't need INFO lines. Here the errors and warnings are mainly due to configuration decision, and can be safely ignored.
To check that the znode /media-recorder really exists in the database, use
docker exec -it zookeeper bin/zkCli.sh
command.
Use internal zkCli command ls /media-recorder to examine the znode.
[zk: localhost:2181(CONNECTED) 1] ls /media-recorder
[]
[zk: localhost:2181(CONNECTED) 2]
Here the output suggests that no Media Recorder instances have been registered yet.
Once the Media Recorder instance is registered, the output should contain its name and the IP address.
[zk: localhost:2181(CONNECTED) 2] ls /media-recorder
[ide-dev01]
[zk: localhost:2181(CONNECTED) 3] get /media-recorder/ide-dev01
10.7.213.153
[zk: localhost:2181(CONNECTED) 4]
Here the internal zkCli commands ls /media-recorder and get /media-recorder/ide-dev01 are used, where ide-dev01 is just the hostname of the Media Recorder instance.
To quit the zkCli, use quit command.
[zk: localhost:2181(CONNECTED) 4] quit
WATCHER::
WatchedEvent state:Closed type:None path:null zxid: -1
2025-12-23 10:59:10,580 [myid:] - INFO [main:o.a.z.ZooKeeper@1232] - Session: 0x100000162bc0001 closed
2025-12-23 10:59:10,580 [myid:] - INFO [main-EventThread:o.a.z.ClientCnxn$EventThread@556] - EventThread shut down for session: 0x100000162bc0001
2025-12-23 10:59:10,582 [myid:] - INFO [main:o.a.z.u.ServiceUtils@45] - Exiting JVM with code 0
root@idelac-ubuntu20-mmp:/opt/media-proxy-platform#
And you can continue your work in the /opt/media-proxy-platform folder.
The helper service Media Nodes is just a HTTP and / or raw TCP interface towards the zookeeper service, to obtain a list of IP address(es) of connected or registered Media Recorder instances. Since Apache Zookeeper implementation does not provide any kind of interface, except the ZK protocol, a helper service is provisioned.
To check that the service functions correctly, examine the log.
root@idelac-ubuntu20-mmp:/opt/media-proxy-platform# docker logs media-nodes | tail
2025-12-23 10:42:26 [ZkClient-[10.25.0.1:2181]] INFO hr.dvasadva.media.nodes.ZkClient - Connecting to the Zookeeper at 10.25.0.1:2181 ...
2025-12-23 10:42:26 [ZkClient-[10.25.0.1:2181]-SendThread(10.25.0.1:2181)] WARN org.apache.zookeeper.ClientCnxn - Session 0x0 for server a87107645da9/10.25.0.1:2181, Closing socket connection. Attempting reconnect except it is a SessionExpiredException or SessionTimeoutException.
java.net.ConnectException: Connection refused
at java.base/sun.nio.ch.Net.pollConnect(Native Method)
at java.base/sun.nio.ch.Net.pollConnectNow(Unknown Source)
at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(Unknown Source)
at org.apache.zookeeper.ClientCnxnSocketNIO.doTransport(ClientCnxnSocketNIO.java:344)
at org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1290)
2025-12-23 10:42:28 [ZkClient-[10.25.0.1:2181]-EventThread] INFO hr.dvasadva.media.nodes.ZkClient - Watching '/media-recorder' znode.
2025-12-23 10:57:17 [ZkClient-[10.25.0.1:2181]-EventThread] INFO hr.dvasadva.media.nodes.ZkClient - Media Recorder List: 10.7.213.153
root@idelac-ubuntu20-mmp:/opt/media-proxy-platform#
The output suggests there were some issues while connecting to the zookeeper instance, while the last lines show that the watch to /media-recorder has been successfully installed. Also the list of media recorders contains 1 IP address.
Verify that the HTTP interface provides the list of registered Media Recorder nodes with
wget -q -O- http://localhost:5002 | xargs
command.
E.g.
root@idelac-ubuntu20-mmp:/opt/media-proxy-platform# wget -q -O- http://localhost:5002 | xargs
10.7.213.153
root@idelac-ubuntu20-mmp:/opt/media-proxy-platform#
The output should match what is stored in the zookeeper database.
In case of trouble, consider restarting the container with
docker restart media-nodes
and observer the logs. E.g.
2025-12-23 11:06:05 [main] INFO hr.dvasadva.media.nodes.MediaNodes - Using default values: MEDIA_RECORDER_ZNODE=/media-recorder, ZOOKEEPER_SERVER=localhost:2181, TCP_LISTENING_PORT=5001, HTTP_LISTENING_PORT=5002
2025-12-23 11:06:05 [main] INFO hr.dvasadva.media.nodes.MediaNodes - Using variable: ZOOKEEPER_SERVER=10.25.0.1:2181
2025-12-23 11:06:05 [main] INFO hr.dvasadva.media.nodes.MediaNodes - Using variable: TCP_LISTENING_PORT=5001
2025-12-23 11:06:05 [main] INFO hr.dvasadva.media.nodes.MediaNodes - Using variable: HTTP_LISTENING_PORT=5002
2025-12-23 11:06:05 [main] INFO hr.dvasadva.media.nodes.MediaNodes - Using variable: MEDIA_RECORDER_ZNODE=/media-recorder
2025-12-23 11:06:05 [ZkClient-[10.25.0.1:2181]] INFO hr.dvasadva.media.nodes.ZkClient - Connecting to the Zookeeper at 10.25.0.1:2181 ...
2025-12-23 11:06:05 [ZkClient-[10.25.0.1:2181]-EventThread] INFO hr.dvasadva.media.nodes.ZkClient - Media Recorder List: 10.7.213.153
2025-12-23 11:06:05 [ZkClient-[10.25.0.1:2181]-EventThread] INFO hr.dvasadva.media.nodes.ZkClient - Watching '/media-recorder' znode.
root@idelac-ubuntu20-mmp:/opt/media-proxy-platform#
Here INFO messages might contain useful information, like list of media recorders, etc.
To verify that the database instance is proper, connect to it via
docker exec -it postgres-db psql --username=wgportal --dbname=wgportal
This will open a session to the wgportal database, and allow browsing of the data stored by the wg-portal service.
wgportal=# \d
List of relations
Schema | Name | Type | Owner
--------+---------------------------+----------+----------
public | audit_entries | table | wgportal
public | audit_entries_id_seq | sequence | wgportal
public | cidrs | table | wgportal
public | interface_addresses | table | wgportal
public | interface_statuses | table | wgportal
public | interfaces | table | wgportal
public | peer_addresses | table | wgportal
public | peer_statuses | table | wgportal
public | peers | table | wgportal
public | sys_stats | table | wgportal
public | user_webauthn_credentials | table | wgportal
public | users | table | wgportal
(12 rows)
wgportal=#
Here you usually do not need to modify data. However, you might need to perform regular backup. E.g.
docker exec -it postgres-db pg_dump --username=wgportal --dbname=wgportal > /var/lib/wgportal-backup.sql
Note that the output file is really stored on the host file system, not in the docker postgres-db container.
The postgres-db instance contains initial SQL data file, stored at location /var/lib/import inside the container instance. To initiate the empty database with the data stored in the SQL file, use:
docker exec -i postgres-db psql --quiet --username=wgportal --dbname=wgportal --file=/var/lib/import/wgportal.sql
To check the proper name of the SQL file, see the postgresql-import/ local folder, which is mounted as the /var/lib/import.
The is fire and forget service, which sole purpose is to make a DNS update to a predefined DNS record.
You might inspect the log of the service.
[custom-init] No custom files found, skipping...
[ls.io-init] done.
[migrations] started
[migrations] no migrations found
usermod: no changes
───────────────────────────────────────
██╗ ███████╗██╗ ██████╗
██║ ██╔════╝██║██╔═══██╗
██║ ███████╗██║██║ ██║
██║ ╚════██║██║██║ ██║
███████╗███████║██║╚██████╔╝
╚══════╝╚══════╝╚═╝ ╚═════╝
Brought to you by linuxserver.io
───────────────────────────────────────
To support the app dev(s) visit:
DuckDNS: https://www.patreon.com/user?u=3209735
To support LSIO projects visit:
https://www.linuxserver.io/donate/
───────────────────────────────────────
GID/UID
───────────────────────────────────────
User UID: 911
User GID: 911
───────────────────────────────────────
Linuxserver.io version: 841eb03f-ls70
Build-date: 2025-12-15T04:31:56+00:00
───────────────────────────────────────
Detecting IPv4 via DuckDNS
DuckDNS request at Tue Dec 23 10:41:06 UTC 2025 successful. IP(s) unchanged.
[custom-init] No custom files found, skipping...
[ls.io-init] done.
Detecting IPv4 via DuckDNS
DuckDNS request at Tue Dec 23 10:46:39 UTC 2025 successful. IP(s) unchanged.
. . .
which might reveal problems, if any occur.
The wg-portal service is used to provide VPN service for the Media Recorder instances. Such setup allows direct communication between the MediaMTX proxy and the Media Recorder instances, bypassing firewalls and network address translators (NAT routers).
docker logs wg-portal
The log shows date and time when the process has been started, version of the wg-portal package, and ports that were open.
2025/12/23 10:42:25 INFO Starting WireGuard Portal V2... version=v2.1.1-d1a4ddd
2025/12/23 10:42:25 INFO Configuration loaded! logLevel=info
2025/12/23 10:42:26 INFO successfully setup all external auth providers
2025/12/23 10:42:26 INFO [WEBHOOK] no webhook configured, skipping event-bus subscription
2025/12/23 10:42:26 INFO interface state restored
2025/12/23 10:42:26 INFO Application startup complete
2025/12/23 10:42:26 INFO started metrics service address=:8787
2025/12/23 10:42:26 INFO started web service address=:8888
. . .
Here note that the HTTP port 8888 is used for the administrator interface.
To access the web interface from the web browser, open the URL: http://aeromonitor.duckdns.org:8888
NOTE: The URL value for the web interface is defined in the wg-portal/config/config.yaml file, section web, variable external_url. The value that is defined in the external_url must be used in the web browser to access the web interface. Failure to do that will result in the login problems.
web:
site_title: Aeromonitor WireGuard Server
site_company_name: Aeromonitor d.o.o.
listening_address: :8888
external_url: http://aeromonitor.duckdns.org:8888
csrf_secret: e4e6f2eb-b568-4b32-9fd9-fcab3b98fa7b
session_secret: 420044a8-6512-46e4-aed6-5bb20999b7ac
request_logging: trueIf you are testing and need to access the web interface, it's best to put value aeromonitor.duckdns.org in your local /etc/hosts file, and assign IP address that corresponds to your setup.
MediaMTX proxy is the main service in this docker composition. It forwards the incoming video stream to the registered Media Recorder instances.
To observe the log, use
docker logs mediamtx
The log usually reveals the program version, and initially open TCP ports.
2025/12/23 10:42:25 INF MediaMTX v1.15.5
2025/12/23 10:42:25 INF configuration loaded from /mediamtx.yml
2025/12/23 10:42:25 INF [RTSP] listener opened on :8554 (TCP)
2025/12/23 10:42:25 INF [RTMP] listener opened on :1935
2025/12/23 10:42:25 INF [WebRTC] listener opened on :8889 (HTTP), :8189 (ICE/UDP)
2025/12/23 10:42:25 INF [SRT] listener opened on :8890 (UDP)
2025/12/23 10:42:25 INF [API] listener opened on :9997
The docker compose YAML is configured to allow only RTMP connections on TCP port 1935.
Once the video stream arrives, the log should contain
. . .
2025/12/23 11:28:17 INF [RTMP] [conn 10.7.195.2:44926] opened
2025/12/23 11:28:19 INF [path cam1] runOnReady command started
2025/12/23 11:28:19 INF [RTMP] [conn 10.7.195.2:44926] is publishing to path 'cam1', 1 track (H264)
2025/12/23 11:28:19 INF Program runOnReady.sh started.
2025/12/23 11:28:19 INF Media recorders: 10.7.213.153
2025/12/23 11:28:19 INF ffmpeg filter to distribute stream(s): [f=flv:onfail=ignore]rtmp://10.7.213.153:1935/cam1
2025/12/23 11:28:19 INF ffmpeg -i rtmp://localhost:1935/cam1 -loglevel error -map 0:v -c copy -f tee [f=flv:onfail=ignore]rtmp://10.7.213.153:1935/cam1
2025/12/23 11:28:20 INF [RTMP] [conn [::1]:51684] opened
2025/12/23 11:28:20 INF [RTMP] [conn [::1]:51684] is reading from path 'cam1', 1 track (H264)
. . .
Here we can see the external IP connection of the video stream source, e.g. 10.7.195.2:44926:
2025/12/23 11:28:19 INF [RTMP] [conn 10.7.195.2:44926] is publishing to path 'cam1', 1 track (H264)
and the ffmpeg forwarding stream to the 10.7.213.153 Media Recorder instance:
2025/12/23 11:28:19 INF ffmpeg -i rtmp://localhost:1935/cam1 -loglevel error -map 0:v -c copy -f tee [f=flv:onfail=ignore]rtmp://10.7.213.153:1935/cam1
Once the streaming stops, the log will contain
2025/12/23 11:28:31 INF [path cam1] runOnReady command stopped
2025/12/23 11:28:31 INF [RTMP] [conn 10.7.195.2:44926] closed: EOF
2025/12/23 11:28:31 INF [RTMP] [conn [::1]:51684] closed: terminated
[rtmp @ 0x7fe4e5d89ec0] Cannot open connection tcp://10.7.213.153:1935?tcp_nodelay=0
[tee @ 0x7fe4e6b610c0] Slave '[f=flv:onfail=ignore]rtmp://10.7.213.153:1935/cam1': error opening: Immediate exit requested
[tee @ 0x7fe4e6b610c0] All tee outputs failed.
[out#0/tee @ 0x7fe4e1a6f5c0] Could not write header (incorrect codec parameters ?): Immediate exit requested
Error opening output file [f=flv:onfail=ignore]rtmp://10.7.213.153:1935/cam1.
Error and warnings that originate from the ffmpeg processs might be ignored in this case.