Add auto-generation of config files

This commit is contained in:
Santiago Lo Coco 2024-11-21 00:12:34 +01:00
parent 6ca41c929f
commit a414694036
14 changed files with 310 additions and 143 deletions

9
.env.dev Normal file
View File

@ -0,0 +1,9 @@
IP=192.168.137.1
PORT_1=8100
LISTENER_PORT_1=8101
PORT_2=8200
LISTENER_PORT_2=8201
PORT_3=8300
LISTENER_PORT_3=8301
# PORT_4=8400
# LISTENER_PORT_4=8401

138
.gitignore vendored
View File

@ -1 +1,139 @@
creation creation
# mediamtx_*.yml
# ./start.bat
docker-compose.yml
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pdm
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
.idea/
html/

38
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,38 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
- id: check-executables-have-shebangs
- id: check-merge-conflict
- id: check-symlinks
- id: check-yaml
exclude: (observability|testing/tavern)
- id: debug-statements
exclude: tests/
- id: destroyed-symlinks
- id: end-of-file-fixer
files: \.(py|sh|rst|yml|yaml)$
- id: mixed-line-ending
- id: trailing-whitespace
files: \.(py|sh|rst|yml|yaml)$
- repo: https://github.com/ambv/black
rev: 23.10.0
hooks:
- id: black
- repo: https://github.com/pycqa/flake8
rev: 6.0.0
hooks:
- id: flake8
args: [--config, src/setup.cfg]
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
args: [
'--profile',
'black',
'--src-path',
'src',
]

View File

@ -17,3 +17,10 @@
## IP address configuration ## IP address configuration
The `docker-compose.yaml` is hardcoded to use the IP address `192.168.137.1`. You must update this to your specific network IP from the mobile hotspot configuration. The `docker-compose.yaml` is hardcoded to use the IP address `192.168.137.1`. You must update this to your specific network IP from the mobile hotspot configuration.
## Build
```
docker build -t se23m504/startstreaming .\src -f .\docker\Dockerfile
docker run --rm -v ${PWD}:/app/data se23m504/startstreaming
```

View File

@ -1,22 +0,0 @@
name: streaming
services:
mediamtx-1: &default
container_name: mediamtx-1
environment:
- MTX_WEBRTCADDITIONALHOSTS=192.168.137.1
image: bluenviron/mediamtx
ports:
- 8100:8100
- 8101:8101/udp
volumes:
- ./mediamtx/mediamtx_1.yml:/mediamtx.yml
mediamtx-2:
<<: *default
container_name: mediamtx-2
ports:
- 8200:8200
- 8201:8201/udp
volumes:
- ./mediamtx/mediamtx_2.yml:/mediamtx.yml

10
docker/Dockerfile Normal file
View File

@ -0,0 +1,10 @@
FROM python:3.11-slim
ENV PYTHONUNBUFFERED=1
WORKDIR /app/data
COPY config.py /app/bin/
COPY generate.py /app/bin/
CMD ["python", "/app/bin/generate.py"]

View File

@ -1,58 +0,0 @@
webrtcAddress: :8100
webrtcLocalUDPAddress: :8101
webrtcLocalTCPAddress: ''
webrtcEncryption: no
webrtcAllowOrigin: '*'
webrtcTrustedProxies: []
webrtcIPsFromInterfaces: yes
webrtcIPsFromInterfacesList: []
webrtcAdditionalHosts: []
webrtcICEServers2: []
logLevel: debug
logDestinations: [stdout]
logFile: mediamtx.log
readTimeout: 10s
writeTimeout: 10s
writeQueueSize: 512
udpMaxPayloadSize: 1472
runOnConnectRestart: no
api: no
metrics: no
pprof: no
playback: no
rtsp: no
rtmp: no
hls: no
srt: no
webrtc: yes
authMethod: internal
authInternalUsers:
- user: any
pass:
ips: []
permissions:
- action: publish
path:
- action: read
path:
- action: playback
path:
pathDefaults:
source: publisher
sourceFingerprint:
sourceOnDemand: no
sourceOnDemandStartTimeout: 10s
sourceOnDemandCloseAfter: 10s
maxReaders: 0
srtReadPassphrase:
fallback:
paths:
all_others:

View File

@ -1,58 +0,0 @@
webrtcAddress: :8200
webrtcLocalUDPAddress: :8201
webrtcLocalTCPAddress: ''
webrtcEncryption: no
webrtcAllowOrigin: '*'
webrtcTrustedProxies: []
webrtcIPsFromInterfaces: yes
webrtcIPsFromInterfacesList: []
webrtcAdditionalHosts: []
webrtcICEServers2: []
logLevel: debug
logDestinations: [stdout]
logFile: mediamtx.log
readTimeout: 10s
writeTimeout: 10s
writeQueueSize: 512
udpMaxPayloadSize: 1472
runOnConnectRestart: no
api: no
metrics: no
pprof: no
playback: no
rtsp: no
rtmp: no
hls: no
srt: no
webrtc: yes
authMethod: internal
authInternalUsers:
- user: any
pass:
ips: []
permissions:
- action: publish
path:
- action: read
path:
- action: playback
path:
pathDefaults:
source: publisher
sourceFingerprint:
sourceOnDemand: no
sourceOnDemandStartTimeout: 10s
sourceOnDemandCloseAfter: 10s
maxReaders: 0
srtReadPassphrase:
fallback:
paths:
all_others:

90
src/config.py Normal file
View File

@ -0,0 +1,90 @@
import os
import re
def load_env(filename=".env"):
env_vars = {}
with open(filename) as f:
for line in f:
if "=" in line:
key, value = line.strip().split("=", 1)
env_vars[key] = value
return env_vars
def count_servers(env_vars):
server_keys = [key for key in env_vars if re.match(r"PORT_\d+", key)]
return len(server_keys)
def generate_docker_compose(env_vars, num_servers):
ip = env_vars.get("IP")
services = []
for i in range(1, num_servers + 1):
port = env_vars.get(f"PORT_{i}")
listener_port = env_vars.get(f"LISTENER_PORT_{i}")
service = f"""
mediamtx-{i}:
container_name: mediamtx-{i}
environment:
- MTX_WEBRTCADDITIONALHOSTS={ip}
image: bluenviron/mediamtx
ports:
- {port}:{port}
- {listener_port}:{listener_port}/udp
volumes:
- ./mediamtx/mediamtx_{i}.yml:/mediamtx.yml
"""
services.append(service)
compose_content = f"""
name: streaming
services:
{''.join(services)}
"""
with open("docker-compose.yml", "w") as f:
f.write(compose_content)
def generate_mediamtx_files(env_vars, num_servers):
# os.makedirs("mediamtx")
mediamtx_dir = "mediamtx"
if not os.path.exists(mediamtx_dir):
os.makedirs(mediamtx_dir)
with open("templates/mediamtx.yml", "r") as template_file:
template_content = template_file.read()
for i in range(1, num_servers + 1):
port = env_vars.get(f"PORT_{i}")
listener_port = env_vars.get(f"LISTENER_PORT_{i}")
generated_content = template_content.replace("{{WEBRTC_PORT}}", port).replace("{{WEBRTC_LISTENER_PORT}}", listener_port)
with open(f"mediamtx/mediamtx_{i}.yml", "w") as f:
f.write(generated_content)
existing_files = os.listdir("mediamtx")
for file in existing_files:
if file.startswith("mediamtx_"):
file_num = int(file.split("_")[1].split(".")[0])
if file_num > num_servers:
os.remove(f"mediamtx/{file}")
print(f"Removed extra file: {file}")
def generate_start_bat(num_servers):
with open("templates/start.bat", "r") as template_file:
bat_template = template_file.read()
obs_instances = ""
for i in range(1, num_servers + 1):
obs_instance = f"""
echo Launching OBS instance {i}
start /MIN "OBS{i}" /D "C:\\Program Files\\obs-studio\\bin\\64bit" "obs64.exe" --profile "Profile{i}" --collection "Profile{i}" --multi --startstreaming
timeout /t 1 >nul
"""
obs_instances += obs_instance
bat_content = bat_template.replace("{{OBS_INSTANCES}}", obs_instances)
with open("start.bat", "w") as f:
f.write(bat_content)

13
src/generate.py Normal file
View File

@ -0,0 +1,13 @@
import os
from config import *
def main():
env_vars = load_env(".env")
num_servers = count_servers(env_vars)
generate_docker_compose(env_vars, num_servers)
generate_mediamtx_files(env_vars, num_servers)
generate_start_bat(num_servers)
if __name__ == "__main__":
main()

1
src/requirements.txt Normal file
View File

@ -0,0 +1 @@
python-dotenv==1.0.1

2
src/setup.cfg Normal file
View File

@ -0,0 +1,2 @@
[flake8]
max-line-length = 110

View File

@ -24,9 +24,6 @@ echo Starting docker compose
cd ".\mediamtx" cd ".\mediamtx"
docker compose up -d docker compose up -d
echo Launching OBS instances {{OBS_INSTANCES}}
start /MIN "OBS1" /D "C:\Program Files\obs-studio\bin\64bit" "obs64.exe" --profile "Profile1" --collection "Profile1" --multi --startstreaming
timeout /t 1 >nul
start /MIN "OBS2" /D "C:\Program Files\obs-studio\bin\64bit" "obs64.exe" --profile "Profile2" --collection "Profile2" --multi --startstreaming
pause pause