Repository: blakeblackshear/frigate

Issue:
Add global timestamp configuration
**Describe what you are trying to accomplish and why in non technical terms**
In frigate It looks like the new timestamp (pre-release 9.0) in config is only defined for camera specific configuration... there is no global... Thoughts on added a global for the timestamp?  This would allow a generic to be setup for global timestamp setup, and then you could tweak it per camera if needed.

**Describe the solution you'd like**
Add the ability to globally define timestamp.

**Describe alternatives you've considered**
Continue to be only defined at the camera level.

**Additional context**
None.

Add global timestamp configuration
**Describe what you are trying to accomplish and why in non technical terms**
In frigate It looks like the new timestamp (pre-release 9.0) in config is only defined for camera specific configuration... there is no global... Thoughts on added a global for the timestamp?  This would allow a generic to be setup for global timestamp setup, and then you could tweak it per camera if needed.

**Describe the solution you'd like**
Add the ability to globally define timestamp.

**Describe alternatives you've considered**
Continue to be only defined at the camera level.

**Additional context**
None.



Discussion:

Resolving patch:
diff --git a/frigate/config.py b/frigate/config.py
--- a/frigate/config.py
+++ b/frigate/config.py
@@ -432,7 +432,7 @@ class CameraMqttConfig(BaseModel):
     )
 
 
-class CameraRtmpConfig(BaseModel):
+class RtmpConfig(BaseModel):
     enabled: bool = Field(default=True, title="RTMP restreaming enabled.")
 
 
@@ -454,8 +454,8 @@ class CameraConfig(BaseModel):
     record: RecordConfig = Field(
         default_factory=RecordConfig, title="Record configuration."
     )
-    rtmp: CameraRtmpConfig = Field(
-        default_factory=CameraRtmpConfig, title="RTMP restreaming configuration."
+    rtmp: RtmpConfig = Field(
+        default_factory=RtmpConfig, title="RTMP restreaming configuration."
     )
     live: CameraLiveConfig = Field(
         default_factory=CameraLiveConfig, title="Live playback settings."
@@ -656,6 +656,9 @@ class FrigateConfig(BaseModel):
     snapshots: SnapshotsConfig = Field(
         default_factory=SnapshotsConfig, title="Global snapshots configuration."
     )
+    rtmp: RtmpConfig = Field(
+        default_factory=RtmpConfig, title="Global RTMP restreaming configuration."
+    )
     birdseye: BirdseyeConfig = Field(
         default_factory=BirdseyeConfig, title="Birdseye configuration."
     )
@@ -672,6 +675,10 @@ class FrigateConfig(BaseModel):
         default_factory=DetectConfig, title="Global object tracking configuration."
     )
     cameras: Dict[str, CameraConfig] = Field(title="Camera configuration.")
+    timestamp_style: TimestampStyleConfig = Field(
+        default_factory=TimestampStyleConfig,
+        title="Global timestamp style configuration.",
+    )
 
     @property
     def runtime_config(self) -> FrigateConfig:
@@ -687,10 +694,12 @@ def runtime_config(self) -> FrigateConfig:
             include={
                 "record": ...,
                 "snapshots": ...,
+                "rtmp": ...,
                 "objects": ...,
                 "motion": ...,
                 "detect": ...,
                 "ffmpeg": ...,
+                "timestamp_style": ...,
             },
             exclude_unset=True,
         )


Test patch:
diff --git a/frigate/test/test_config.py b/frigate/test/test_config.py
--- a/frigate/test/test_config.py
+++ b/frigate/test/test_config.py
@@ -884,6 +884,156 @@ def test_global_snapshots_merge(self):
         assert runtime_config.cameras["back"].snapshots.height == 150
         assert runtime_config.cameras["back"].snapshots.enabled
 
+    def test_global_rtmp(self):
+
+        config = {
+            "mqtt": {"host": "mqtt"},
+            "rtmp": {"enabled": True},
+            "cameras": {
+                "back": {
+                    "ffmpeg": {
+                        "inputs": [
+                            {
+                                "path": "rtsp://10.0.0.1:554/video",
+                                "roles": ["detect"],
+                            },
+                        ]
+                    },
+                }
+            },
+        }
+        frigate_config = FrigateConfig(**config)
+        assert config == frigate_config.dict(exclude_unset=True)
+
+        runtime_config = frigate_config.runtime_config
+        assert runtime_config.cameras["back"].rtmp.enabled
+
+    def test_default_rtmp(self):
+
+        config = {
+            "mqtt": {"host": "mqtt"},
+            "cameras": {
+                "back": {
+                    "ffmpeg": {
+                        "inputs": [
+                            {
+                                "path": "rtsp://10.0.0.1:554/video",
+                                "roles": ["detect"],
+                            },
+                        ]
+                    }
+                }
+            },
+        }
+        frigate_config = FrigateConfig(**config)
+        assert config == frigate_config.dict(exclude_unset=True)
+
+        runtime_config = frigate_config.runtime_config
+        assert runtime_config.cameras["back"].rtmp.enabled
+
+    def test_global_rtmp_merge(self):
+
+        config = {
+            "mqtt": {"host": "mqtt"},
+            "rtmp": {"enabled": False},
+            "cameras": {
+                "back": {
+                    "ffmpeg": {
+                        "inputs": [
+                            {
+                                "path": "rtsp://10.0.0.1:554/video",
+                                "roles": ["detect"],
+                            },
+                        ]
+                    },
+                    "rtmp": {
+                        "enabled": True,
+                    },
+                }
+            },
+        }
+        frigate_config = FrigateConfig(**config)
+        assert config == frigate_config.dict(exclude_unset=True)
+
+        runtime_config = frigate_config.runtime_config
+        assert runtime_config.cameras["back"].rtmp.enabled
+
+    def test_global_timestamp_style(self):
+
+        config = {
+            "mqtt": {"host": "mqtt"},
+            "timestamp_style": {"position": "bl", "scale": 1.5},
+            "cameras": {
+                "back": {
+                    "ffmpeg": {
+                        "inputs": [
+                            {
+                                "path": "rtsp://10.0.0.1:554/video",
+                                "roles": ["detect"],
+                            },
+                        ]
+                    },
+                }
+            },
+        }
+        frigate_config = FrigateConfig(**config)
+        assert config == frigate_config.dict(exclude_unset=True)
+
+        runtime_config = frigate_config.runtime_config
+        assert runtime_config.cameras["back"].timestamp_style.position == "bl"
+        assert runtime_config.cameras["back"].timestamp_style.scale == 1.5
+
+    def test_default_timestamp_style(self):
+
+        config = {
+            "mqtt": {"host": "mqtt"},
+            "cameras": {
+                "back": {
+                    "ffmpeg": {
+                        "inputs": [
+                            {
+                                "path": "rtsp://10.0.0.1:554/video",
+                                "roles": ["detect"],
+                            },
+                        ]
+                    }
+                }
+            },
+        }
+        frigate_config = FrigateConfig(**config)
+        assert config == frigate_config.dict(exclude_unset=True)
+
+        runtime_config = frigate_config.runtime_config
+        assert runtime_config.cameras["back"].timestamp_style.position == "tl"
+        assert runtime_config.cameras["back"].timestamp_style.scale == 1.0
+
+    def test_global_timestamp_style_merge(self):
+
+        config = {
+            "mqtt": {"host": "mqtt"},
+            "rtmp": {"enabled": False},
+            "timestamp_style": {"position": "br", "scale": 2.0},
+            "cameras": {
+                "back": {
+                    "ffmpeg": {
+                        "inputs": [
+                            {
+                                "path": "rtsp://10.0.0.1:554/video",
+                                "roles": ["detect"],
+                            },
+                        ]
+                    },
+                    "timestamp_style": {"position": "bl", "scale": 1.5},
+                }
+            },
+        }
+        frigate_config = FrigateConfig(**config)
+        assert config == frigate_config.dict(exclude_unset=True)
+
+        runtime_config = frigate_config.runtime_config
+        assert runtime_config.cameras["back"].timestamp_style.position == "bl"
+        assert runtime_config.cameras["back"].timestamp_style.scale == 1.5
+
 
 if __name__ == "__main__":
     unittest.main(verbosity=2)