diff --git a/docker/rootfs/usr/local/go2rtc/create_config.py b/docker/rootfs/usr/local/go2rtc/create_config.py index 580963431..28f884fe6 100644 --- a/docker/rootfs/usr/local/go2rtc/create_config.py +++ b/docker/rootfs/usr/local/go2rtc/create_config.py @@ -5,8 +5,12 @@ import os import sys import yaml +sys.path.insert(0, "/opt/frigate") +from frigate.const import BIRDSEYE_PIPE, BTBN_PATH +from frigate.ffmpeg_presets import parse_preset_hardware_acceleration_encode +sys.path.remove("/opt/frigate") + -BTBN_PATH = "/usr/lib/btbn-ffmpeg" FRIGATE_ENV_VARS = {k: v for k, v in os.environ.items() if k.startswith("FRIGATE_")} config_file = os.environ.get("CONFIG_FILE", "/config/config.yml") @@ -19,9 +23,9 @@ with open(config_file) as f: raw_config = f.read() if config_file.endswith((".yaml", ".yml")): - config = yaml.safe_load(raw_config) + config: dict[str, any] = yaml.safe_load(raw_config) elif config_file.endswith(".json"): - config = json.loads(raw_config) + config: dict[str, any] = json.loads(raw_config) go2rtc_config: dict[str, any] = config.get("go2rtc", {}) @@ -34,7 +38,9 @@ elif go2rtc_config["log"].get("format") is None: if not go2rtc_config.get("webrtc", {}).get("candidates", []): default_candidates = [] # use internal candidate if it was discovered when running through the add-on - internal_candidate = os.environ.get("FRIGATE_GO2RTC_WEBRTC_CANDIDATE_INTERNAL", None) + internal_candidate = os.environ.get( + "FRIGATE_GO2RTC_WEBRTC_CANDIDATE_INTERNAL", None + ) if internal_candidate is not None: default_candidates.append(internal_candidate) # should set default stun server so webrtc can work @@ -42,8 +48,11 @@ if not go2rtc_config.get("webrtc", {}).get("candidates", []): go2rtc_config["webrtc"] = {"candidates": default_candidates} else: - print("[INFO] Not injecting WebRTC candidates into go2rtc config as it has been set manually", file=sys.stderr) - + print( + "[INFO] Not injecting WebRTC candidates into go2rtc config as it has been set manually", + file=sys.stderr, + ) + # sets default RTSP response to be equivalent to ?video=h264,h265&audio=aac # this means user does not need to specify audio codec when using restream # as source for frigate and the integration supports HLS playback @@ -62,14 +71,29 @@ if not os.path.exists(BTBN_PATH): go2rtc_config["ffmpeg"][ "rtsp" ] = "-fflags nobuffer -flags low_delay -stimeout 5000000 -user_agent go2rtc/ffmpeg -rtsp_transport tcp -i {input}" - + for name in go2rtc_config.get("streams", {}): stream = go2rtc_config["streams"][name] if isinstance(stream, str): - go2rtc_config["streams"][name] = go2rtc_config["streams"][name].format(**FRIGATE_ENV_VARS) + go2rtc_config["streams"][name] = go2rtc_config["streams"][name].format( + **FRIGATE_ENV_VARS + ) elif isinstance(stream, list): for i, stream in enumerate(stream): go2rtc_config["streams"][name][i] = stream.format(**FRIGATE_ENV_VARS) +# add birdseye restream stream if enabled +if config.get("birdseye", {}).get("restream", False): + birdseye: dict[str, any] = config.get("birdseye") + + input = f"-f rawvideo -pix_fmt yuv420p -video_size {birdseye.get('width', 1280)}x{birdseye.get('height', 720)} -r 10 -i {BIRDSEYE_PIPE}" + ffmpeg_cmd = f"exec:{parse_preset_hardware_acceleration_encode(config.get('ffmpeg', {}).get('hwaccel_args'), input, '-rtsp_transport tcp -f rtsp {output}')}" + + if go2rtc_config.get("streams"): + go2rtc_config["streams"]["birdseye"] = ffmpeg_cmd + else: + go2rtc_config["streams"] = {"birdseye": ffmpeg_cmd} + + print(json.dumps(go2rtc_config)) diff --git a/frigate/app.py b/frigate/app.py index c5cc8411a..df89dd8b6 100644 --- a/frigate/app.py +++ b/frigate/app.py @@ -28,7 +28,6 @@ from frigate.object_processing import TrackedObjectProcessor from frigate.output import output_frames from frigate.plus import PlusApi from frigate.record import RecordingCleanup, RecordingMaintainer -from frigate.restream import RestreamApi from frigate.stats import StatsEmitter, stats_init from frigate.storage import StorageMaintainer from frigate.version import VERSION @@ -173,10 +172,6 @@ class FrigateApp: self.plus_api, ) - def init_restream(self) -> None: - self.restream = RestreamApi(self.config) - self.restream.add_cameras() - def init_dispatcher(self) -> None: comms: list[Communicator] = [] @@ -381,7 +376,6 @@ class FrigateApp: print(e) self.log_process.terminate() sys.exit(1) - self.init_restream() self.start_detectors() self.start_video_output_processor() self.start_detected_frames_processor() diff --git a/frigate/restream.py b/frigate/restream.py deleted file mode 100644 index 95582ff98..000000000 --- a/frigate/restream.py +++ /dev/null @@ -1,33 +0,0 @@ -"""Controls go2rtc restream.""" - - -import logging -import requests - -from frigate.config import FrigateConfig -from frigate.const import BIRDSEYE_PIPE -from frigate.ffmpeg_presets import ( - parse_preset_hardware_acceleration_encode, -) - -logger = logging.getLogger(__name__) - - -class RestreamApi: - """Control go2rtc relay API.""" - - def __init__(self, config: FrigateConfig) -> None: - self.config: FrigateConfig = config - - def add_cameras(self) -> None: - """Add cameras to go2rtc.""" - self.relays: dict[str, str] = {} - - if self.config.birdseye.restream: - self.relays[ - "birdseye" - ] = f"exec:{parse_preset_hardware_acceleration_encode(self.config.ffmpeg.hwaccel_args, f'-f rawvideo -pix_fmt yuv420p -video_size {self.config.birdseye.width}x{self.config.birdseye.height} -r 10 -i {BIRDSEYE_PIPE}', '-rtsp_transport tcp -f rtsp {output}')}" - - for name, path in self.relays.items(): - params = {"src": path, "name": name} - requests.put("http://127.0.0.1:1984/api/streams", params=params)