Skip to content

Commit

Permalink
rtsp-simple-server to MediaMTX (#759)
Browse files Browse the repository at this point in the history
* Add `SUB_QUALITY` option #755

* timelapse/save multiple snapshots #757

* rtsp-simple-server to MediaMTX
  • Loading branch information
mrlt8 authored Apr 3, 2023
1 parent 56d59ca commit 566b4a3
Show file tree
Hide file tree
Showing 14 changed files with 75 additions and 93 deletions.
10 changes: 5 additions & 5 deletions app/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ FROM base as builder
ENV PYTHONUNBUFFERED=1
ARG ARM
ARG LIB_ARCH=${ARM:+arm}
ARG RTSP_ARCH=${ARM:+armv7}
ARG MTX_ARCH=${ARM:+armv7}
ARG FFMPEG_ARCH=${ARM:+armv7l}
RUN apt-get update \
&& apt-get install -y tar unzip curl jq g++ git \
Expand All @@ -18,16 +18,16 @@ COPY *.lib /tmp/lib/
RUN mkdir -p /build/app /build/tokens /build/img \
&& curl -L https://github.com/homebridge/ffmpeg-for-homebridge/releases/latest/download/ffmpeg-debian-${FFMPEG_ARCH:-x86_64}.tar.gz \
| tar xzf - -C /build \
&& RTSP_TAG=$(curl -s https://api.github.com/repos/aler9/rtsp-simple-server/releases/latest | jq -r .tag_name) \
&& echo -n $RTSP_TAG > /build/RTSP_TAG \
&& curl -L https://github.com/aler9/rtsp-simple-server/releases/download/${RTSP_TAG}/rtsp-simple-server_${RTSP_TAG}_linux_${RTSP_ARCH:-amd64}.tar.gz \
&& MTX_TAG=$(curl -s https://api.github.com/repos/aler9/mediamtx/releases/latest | jq -r .tag_name) \
&& echo -n $MTX_TAG > /build/MTX_TAG \
&& curl -L https://github.com/aler9/mediamtx/releases/download/${MTX_TAG}/mediamtx_${MTX_TAG}_linux_${MTX_ARCH:-amd64}.tar.gz \
| tar xzf - -C /build/app \
&& cp /tmp/lib/${LIB_ARCH:-amd}.lib /build/usr/local/lib/libIOTCAPIs_ALL.so\
&& rm -rf /tmp/*
COPY . /build/app/

FROM base
ENV PYTHONUNBUFFERED=1 RTSP_PROTOCOLS=tcp RTSP_READTIMEOUT=20s RTSP_LOGLEVEL=warn RTSP_WEBRTCICEUDPMUXADDRESS=:8189 SDK_KEY=AQAAAIZ44fijz5pURQiNw4xpEfV9ZysFH8LYBPDxiONQlbLKaDeb7n26TSOPSGHftbRVo25k3uz5of06iGNB4pSfmvsCvm/tTlmML6HKS0vVxZnzEuK95TPGEGt+aE15m6fjtRXQKnUav59VSRHwRj9Z1Kjm1ClfkSPUF5NfUvsb3IAbai0WlzZE1yYCtks7NFRMbTXUMq3bFtNhEERD/7oc504b FLASK_APP=frontend
ENV PYTHONUNBUFFERED=1 MTX_PROTOCOLS=tcp MTX_READTIMEOUT=20s MTX_LOGLEVEL=warn MTX_WEBRTCICEUDPMUXADDRESS=:8189 SDK_KEY=AQAAAIZ44fijz5pURQiNw4xpEfV9ZysFH8LYBPDxiONQlbLKaDeb7n26TSOPSGHftbRVo25k3uz5of06iGNB4pSfmvsCvm/tTlmML6HKS0vVxZnzEuK95TPGEGt+aE15m6fjtRXQKnUav59VSRHwRj9Z1Kjm1ClfkSPUF5NfUvsb3IAbai0WlzZE1yYCtks7NFRMbTXUMq3bFtNhEERD/7oc504b FLASK_APP=frontend
COPY --from=builder /build /
WORKDIR /app
CMD [ "flask", "run", "--host=0.0.0.0"]
8 changes: 4 additions & 4 deletions app/Dockerfile.arm
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ FROM base as builder
ENV PYTHONUNBUFFERED=1
ARG ARM
ARG LIB_ARCH=${ARM:+arm}
ARG RTSP_ARCH=${ARM:+armv7}
ARG MTX_ARCH=${ARM:+armv7}
ARG FFMPEG_ARCH=${ARM:+armv7l}
RUN apt-get update \
&& apt-get install -y tar unzip curl jq g++ git \
Expand All @@ -18,9 +18,9 @@ COPY *.lib /tmp/lib/
RUN mkdir -p /build/app /build/tokens /build/img \
&& curl -L https://github.com/homebridge/ffmpeg-for-homebridge/releases/latest/download/ffmpeg-debian-${FFMPEG_ARCH:-x86_64}.tar.gz \
| tar xzf - -C /build \
&& RTSP_TAG=$(curl -s https://api.github.com/repos/aler9/rtsp-simple-server/releases/latest | jq -r .tag_name) \
&& echo -n $RTSP_TAG > /build/RTSP_TAG \
&& curl -L https://github.com/aler9/rtsp-simple-server/releases/download/${RTSP_TAG}/rtsp-simple-server_${RTSP_TAG}_linux_${RTSP_ARCH:-amd64}.tar.gz \
&& MTX_TAG=$(curl -s https://api.github.com/repos/aler9/mediamtx/releases/latest | jq -r .tag_name) \
&& echo -n $MTX_TAG > /build/MTX_TAG \
&& curl -L https://github.com/aler9/mediamtx/releases/download/${MTX_TAG}/mediamtx_${MTX_TAG}_linux_${MTX_ARCH:-amd64}.tar.gz \
| tar xzf - -C /build/app \
&& cp /tmp/lib/${LIB_ARCH:-amd}.lib /build/usr/local/lib/libIOTCAPIs_ALL.so\
&& rm -rf /tmp/*
Expand Down
30 changes: 0 additions & 30 deletions app/Dockerfile.armv6

This file was deleted.

10 changes: 5 additions & 5 deletions app/Dockerfile.hwaccel
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ FROM base as builder
ENV PYTHONUNBUFFERED=1
ARG ARM
ARG LIB_ARCH=${ARM:+arm}
ARG RTSP_ARCH=${ARM:+armv7}
ARG MTX_ARCH=${ARM:+armv7}
ARG FFMPEG_ARCH=${ARM:+armv7l}
RUN apt-get update \
&& apt-get install -y tar unzip curl jq g++ git xz-utils \
Expand All @@ -18,15 +18,15 @@ COPY *.lib /tmp/lib/
RUN mkdir -p /build/app /build/tokens /build/img \
&& curl -L https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linux64-gpl.tar.xz \
| tar --strip-components=1 -C /build/usr/local -Jxf - --wildcards '*ffmpeg' \
&& RTSP_TAG=$(curl -s https://api.github.com/repos/aler9/rtsp-simple-server/releases/latest | jq -r .tag_name) \
&& echo -n $RTSP_TAG > /build/RTSP_TAG \
&& curl -L https://github.com/aler9/rtsp-simple-server/releases/download/${RTSP_TAG}/rtsp-simple-server_${RTSP_TAG}_linux_${RTSP_ARCH:-amd64}.tar.gz \
&& MTX_TAG=$(curl -s https://api.github.com/repos/aler9/mediamtx/releases/latest | jq -r .tag_name) \
&& echo -n $MTX_TAG > /build/MTX_TAG \
&& curl -L https://github.com/aler9/mediamtx/releases/download/${MTX_TAG}/mediamtx_${MTX_TAG}_linux_${MTX_ARCH:-amd64}.tar.gz \
| tar xzf - -C /build/app \
&& cp /tmp/lib/${LIB_ARCH:-amd}.lib /build/usr/local/lib/libIOTCAPIs_ALL.so\
&& rm -rf /tmp/*
COPY . /build/app/
FROM base
ENV PYTHONUNBUFFERED=1 RTSP_PROTOCOLS=tcp RTSP_READTIMEOUT=20s RTSP_LOGLEVEL=warn RTSP_WEBRTCICEUDPMUXADDRESS=:8189 SDK_KEY=AQAAAIZ44fijz5pURQiNw4xpEfV9ZysFH8LYBPDxiONQlbLKaDeb7n26TSOPSGHftbRVo25k3uz5of06iGNB4pSfmvsCvm/tTlmML6HKS0vVxZnzEuK95TPGEGt+aE15m6fjtRXQKnUav59VSRHwRj9Z1Kjm1ClfkSPUF5NfUvsb3IAbai0WlzZE1yYCtks7NFRMbTXUMq3bFtNhEERD/7oc504b FLASK_APP=frontend
ENV PYTHONUNBUFFERED=1 MTX_PROTOCOLS=tcp MTX_READTIMEOUT=20s MTX_LOGLEVEL=warn MTX_WEBRTCICEUDPMUXADDRESS=:8189 SDK_KEY=AQAAAIZ44fijz5pURQiNw4xpEfV9ZysFH8LYBPDxiONQlbLKaDeb7n26TSOPSGHftbRVo25k3uz5of06iGNB4pSfmvsCvm/tTlmML6HKS0vVxZnzEuK95TPGEGt+aE15m6fjtRXQKnUav59VSRHwRj9Z1Kjm1ClfkSPUF5NfUvsb3IAbai0WlzZE1yYCtks7NFRMbTXUMq3bFtNhEERD/7oc504b FLASK_APP=frontend
COPY --from=builder /build /
WORKDIR /app
CMD [ "flask", "run", "--host=0.0.0.0"]
2 changes: 1 addition & 1 deletion app/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
"SUBSTREAM": "bool?"
}
],
"RTSP_SIMPLE_SERVER": [
"MEDIAMTX": [
"match(^\\w+=.*)?"
],
"WB_HLS_URL": "str?",
Expand Down
10 changes: 5 additions & 5 deletions app/multi-arch.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ FROM base_$TARGETARCH as builder
ENV PYTHONUNBUFFERED=1
ARG ARM
ARG LIB_ARCH=${ARM:+arm}
ARG RTSP_ARCH=${ARM:+armv7}
ARG MTX_ARCH=${ARM:+armv7}
ARG FFMPEG_ARCH=${ARM:+armv7l}
RUN apt-get update \
&& apt-get install -y tar unzip curl jq g++ git \
Expand All @@ -20,16 +20,16 @@ COPY *.lib /tmp/lib/
RUN mkdir -p /build/app /build/tokens /build/img \
&& curl -L https://github.com/homebridge/ffmpeg-for-homebridge/releases/latest/download/ffmpeg-debian-${FFMPEG_ARCH:-x86_64}.tar.gz \
| tar xzf - -C /build \
&& RTSP_TAG=$(curl -s https://api.github.com/repos/aler9/rtsp-simple-server/releases/latest | jq -r .tag_name) \
&& echo -n $RTSP_TAG > /build/RTSP_TAG \
&& curl -L https://github.com/aler9/rtsp-simple-server/releases/download/${RTSP_TAG}/rtsp-simple-server_${RTSP_TAG}_linux_${RTSP_ARCH:-amd64}.tar.gz \
&& MTX_TAG=$(curl -s https://api.github.com/repos/aler9/mediamtx/releases/latest | jq -r .tag_name) \
&& echo -n $MTX_TAG > /build/MTX_TAG \
&& curl -L https://github.com/aler9/mediamtx/releases/download/${MTX_TAG}/mediamtx_${MTX_TAG}_linux_${MTX_ARCH:-amd64}.tar.gz \
| tar xzf - -C /build/app \
&& cp /tmp/lib/${LIB_ARCH:-amd}.lib /build/usr/local/lib/libIOTCAPIs_ALL.so\
&& rm -rf /tmp/*
COPY . /build/app/

FROM base_$TARGETARCH
ENV PYTHONUNBUFFERED=1 RTSP_PROTOCOLS=tcp RTSP_READTIMEOUT=20s RTSP_LOGLEVEL=warn RTSP_WEBRTCICEUDPMUXADDRESS=:8189 SDK_KEY=AQAAADQA6XDOFkuqH88f65by3FGpOiz2Dm6VtmRcohNFh/rK6OII97hoGzIJJv/qRjS3EDx17r7hKtmDA/a6oBLGOTC5Gml7PgFGe26VYBaZqQF34BwIwAMQX7BGsONLW8cqQbdI5Nm560hm50N6cYfT2YpE9ctsv5vP5S49Q5gg864IauaY3NuO1e9ZVOvJyLcIJqJRy95r4fMkTAwXZiQuFDAb FLASK_APP=frontend
ENV PYTHONUNBUFFERED=1 MTX_PROTOCOLS=tcp MTX_READTIMEOUT=20s MTX_LOGLEVEL=warn MTX_WEBRTCICEUDPMUXADDRESS=:8189 SDK_KEY=AQAAADQA6XDOFkuqH88f65by3FGpOiz2Dm6VtmRcohNFh/rK6OII97hoGzIJJv/qRjS3EDx17r7hKtmDA/a6oBLGOTC5Gml7PgFGe26VYBaZqQF34BwIwAMQX7BGsONLW8cqQbdI5Nm560hm50N6cYfT2YpE9ctsv5vP5S49Q5gg864IauaY3NuO1e9ZVOvJyLcIJqJRy95r4fMkTAwXZiQuFDAb FLASK_APP=frontend
COPY --from=builder /build /
WORKDIR /app
CMD [ "flask", "run", "--host=0.0.0.0"]
4 changes: 2 additions & 2 deletions app/translations/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ configuration:
name: Print WebRTC Credentials
WB_SHOW_VIDEO:
name: HLS Player in Web-UI
RTSP_SIMPLE_SERVER:
name: rtsp-simple-server config
MEDIAMTX:
name: MediaMTX config
description: Use `=` to specify the value and use `_` in place of spaces.
BOA_ENABLED:
name: Enable Boa HTTP*
Expand Down
7 changes: 4 additions & 3 deletions app/wyze_bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from wyzebridge import config
from wyzebridge.bridge_utils import env_bool, env_cam
from wyzebridge.logging import logger
from wyzebridge.rtsp_server import RtspServer
from wyzebridge.rtsp_server import MtxServer
from wyzebridge.stream import StreamManager
from wyzebridge.wyze_api import WyzeApi
from wyzebridge.wyze_stream import WyzeStream, WyzeStreamOptions
Expand All @@ -23,7 +23,7 @@ def __init__(self) -> None:
print(f"\n🚀 STARTING DOCKER-WYZE-BRIDGE v{config.VERSION}\n")
self.api: WyzeApi = WyzeApi()
self.streams: StreamManager = StreamManager()
self.rtsp: RtspServer = RtspServer(config.BRIDGE_IP)
self.rtsp: MtxServer = MtxServer(config.BRIDGE_IP)

if config.LLHLS:
self.rtsp.setup_llhls(config.TOKEN_PATH, bool(config.HASS_TOKEN))
Expand Down Expand Up @@ -69,7 +69,8 @@ def add_substream(self, cam, options):
if env_bool(f"SUBSTREAM_{cam.name_uri}") or (
env_bool("SUBSTREAM") and cam.can_substream
):
sub_opt = replace(options, quality="sd30", substream=True)
quality = env_bool("sub_quality", "sd30")
sub_opt = replace(options, quality=quality, substream=True)
sub = WyzeStream(cam, sub_opt)
self.rtsp.add_path(sub.uri, on_demand=True)
self.streams.add(sub)
Expand Down
10 changes: 9 additions & 1 deletion app/wyzebridge/config.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import json
from os import getenv, makedirs
from os import environ, getenv, makedirs

from wyzebridge.bridge_utils import env_bool, split_int_str
from wyzebridge.hass import setup_hass
Expand All @@ -17,6 +17,7 @@
IMG_PATH: str = f'/{env_bool("IMG_DIR", "img").strip("/")}/'

SNAPSHOT_TYPE, SNAPSHOT_INT = split_int_str(env_bool("SNAPSHOT"), min=15, default=180)
SNAPSHOT_FORMAT: str = env_bool("SNAPSHOT_FORMAT", style="original").strip("/")


BRIDGE_IP: str = env_bool("WB_IP")
Expand Down Expand Up @@ -48,3 +49,10 @@
for env in DEPRECATED:
if getenv(env):
print(f"\n\n[!] WARNING: {env} is deprecated\n\n")

for key, value in environ.items():
if key.startswith("RTSP_") and key != "RTSP_FW":
mtx_key = f"MTX{key[4:]}"
print(f"\n[!] WARNING: {key} is deprecated. Please use {mtx_key} instead\n")
environ.pop(key, None)
environ[mtx_key] = value
20 changes: 13 additions & 7 deletions app/wyzebridge/ffmpeg.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import os
from datetime import datetime

from wyzebridge import config
from wyzebridge.bridge_utils import env_bool, env_cam
from wyzebridge.config import IMG_PATH, SNAPSHOT_FORMAT
from wyzebridge.logging import logger


Expand Down Expand Up @@ -36,7 +37,7 @@ def get_ffmpeg_cmd(
audio_in = f"-thread_queue_size 96 -f {audio['codec']} -ar {audio['rate']} -i /tmp/{uri}.wav"
audio_out = audio["codec_out"] or "copy"
a_filter = ["-filter:a"] + env_bool("AUDIO_FILTER", "volume=5").split()
rtsp_transport = "udp" if "udp" in env_bool("RTSP_PROTOCOLS") else "tcp"
rtsp_transport = "udp" if "udp" in env_bool("MTX_PROTOCOLS") else "tcp"
rss_cmd = f"[{{}}f=rtsp:{rtsp_transport=:}:bsfs/v=dump_extra=freq=keyframe]rtsp://0.0.0.0:8554/{uri}"
rtsp_ss = rss_cmd.format("")
if env_cam("AUDIO_STREAM", uri) and audio:
Expand Down Expand Up @@ -171,14 +172,19 @@ def get_livestream_cmd(uri: str) -> str:
return cmd


def rtsp_snap_cmd(cam_name: str):
def rtsp_snap_cmd(cam_name: str, interval: bool = False):
if auth := os.getenv(f"RTSP_PATHS_{cam_name.upper()}_READUSER", ""):
auth += f':{os.getenv(f"RTSP_PATHS_{cam_name.upper()}_READPASS","")}@'
img = f"{config.IMG_PATH}{cam_name}.{env_bool('IMG_TYPE','jpg')}"
img = f"{IMG_PATH}{cam_name}.{env_bool('IMG_TYPE','jpg')}"

if interval and SNAPSHOT_FORMAT:
file = datetime.now().strftime(f"{IMG_PATH}{SNAPSHOT_FORMAT}")
img = file.format(cam_name=cam_name, CAM_NAME=cam_name.upper())
os.makedirs(os.path.dirname(img), exist_ok=True)

return (
["ffmpeg", "-loglevel", "fatal", "-threads", "1"]
+ ["-analyzeduration", "10000000", "-probesize", "10000000"]
["ffmpeg", "-loglevel", "fatal", "-analyzeduration", "0", "-probesize", "32"]
+ ["-f", "rtsp", "-rtsp_transport", "tcp", "-thread_queue_size", "500"]
+ ["-i", f"rtsp://{auth}0.0.0.0:8554/{cam_name}", "-an"]
+ ["-i", f"rtsp://{auth}0.0.0.0:8554/{cam_name}", "-map", "0:v:0"]
+ ["-f", "image2", "-frames:v", "1", "-y", img]
)
7 changes: 3 additions & 4 deletions app/wyzebridge/hass.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from typing import Optional

import requests

import wyzecam
from wyzebridge.logging import logger

Expand Down Expand Up @@ -54,11 +53,11 @@ def setup_hass(hass_token: Optional[str]) -> None:
if "SUBSTREAM" in cam:
environ[f"SUBSTREAM_{cam_name}"] = str(cam["SUBSTREAM"])

if rtsp_options := conf.pop("RTSP_SIMPLE_SERVER", None):
for opt in rtsp_options:
if mtx_options := conf.pop("MEDIAMTX", None):
for opt in mtx_options:
if (split_opt := opt.split("=", 1)) and len(split_opt) == 2:
key = split_opt[0].strip().upper()
key = key if key.startswith("RTSP_") else f"RTSP_{key}"
key = key if key.startswith("MTX_") else f"MTX_{key}"
environ[key] = split_opt[1].strip()

for k, v in conf.items():
Expand Down
4 changes: 2 additions & 2 deletions app/wyzebridge/rtsp_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@

class RtspEvent:
"""
Reads from the `/tmp/rtsp_event` named pipe and logs events.
Reads from the `/tmp/mtx_event` named pipe and logs events.
"""

FIFO = "/tmp/rtsp_event"
FIFO = "/tmp/mtx_event"
__slots__ = "pipe_fd", "streams"

def __init__(self, streams):
Expand Down
Loading

0 comments on commit 566b4a3

Please sign in to comment.