Sfoglia il codice sorgente

change the ffmpeg config for global defaults and overrides

Blake Blackshear 5 anni fa
parent
commit
3a3afe14bf
5 ha cambiato i file con 161 aggiunte e 60 eliminazioni
  1. 1 1
      README.md
  2. 52 34
      config/config.example.yml
  3. 24 1
      detect_objects.py
  4. 74 0
      docs/DEVICES.md
  5. 10 24
      frigate/video.py

+ 1 - 1
README.md

@@ -55,7 +55,7 @@ Example docker-compose:
       FRIGATE_RTSP_PASSWORD: "password"
 ```
 
-A `config.yml` file must exist in the `config` directory. See example [here](config/config.yml).
+A `config.yml` file must exist in the `config` directory. See example [here](config/config.yml) and device specific info can be found [here](docs/DEVICES.md).
 
 Access the mjpeg stream at `http://localhost:5000/<camera_name>` and the best person snapshot at `http://localhost:5000/<camera_name>/best_person.jpg`
 

+ 52 - 34
config/config.example.yml

@@ -7,11 +7,60 @@ mqtt:
 #  user: username # Optional -- Uncomment for use
 #  password: password # Optional -- Uncomment for use
 
+#################
+# Default ffmpeg args. Optional and can be overwritten per camera.
+# Should work with most RTSP cameras that send h264 video
+# Built from the properties below with:
+# "ffmpeg" + global_args + input_args + "-i" + input + output_args
+#################
+# ffmpeg:
+#   global_args:
+#     - -hide_banner
+#     - -loglevel
+#     - panic
+#   hwaccel_args: []
+#   input_args:
+#     - -avoid_negative_ts
+#     - make_zero
+#     - -fflags
+#     - nobuffer
+#     - -flags
+#     - low_delay
+#     - -strict
+#     - experimental
+#     - -fflags
+#     - +genpts+discardcorrupt
+#     - -vsync
+#     - drop
+#     - -rtsp_transport
+#     - tcp
+#     - -stimeout
+#     - '5000000'
+#     - -use_wallclock_as_timestamps
+#     - '1'
+#   output_args:
+#     - -vf
+#     - mpdecimate
+#     - -f
+#     - rawvideo
+#     - -pix_fmt
+#     - rgb24
+  
 cameras:
   back:
-    # Source passed to ffmpeg after the -i parameter. Supports anything compatible with OpenCV and FFmpeg.
-    # Environment variables that begin with 'FRIGATE_' may be referenced in {}
-    ffmpeg_input: rtsp://viewer:{FRIGATE_RTSP_PASSWORD}@10.0.10.10:554/cam/realmonitor?channel=1&subtype=2
+    ffmpeg:
+      ################
+      # Source passed to ffmpeg after the -i parameter. Supports anything compatible with OpenCV and FFmpeg.
+      # Environment variables that begin with 'FRIGATE_' may be referenced in {}
+      ################
+      input: rtsp://viewer:{FRIGATE_RTSP_PASSWORD}@10.0.10.10:554/cam/realmonitor?channel=1&subtype=2
+      #################
+      # These values will override default values for just this camera
+      #################
+      # global_args: []
+      # hwaccel_args: []
+      # input_args: []
+      # output_args: []
 
     ################
     ## Optional mask. Must be the same dimensions as your video feed.
@@ -29,37 +78,6 @@ cameras:
     # 3 every 3rd frame, etc.
     ################
     take_frame: 1
-
-    ################
-    # Optional hardware acceleration parameters for ffmpeg. If your hardware supports it, it can
-    # greatly reduce the CPU power used to decode the video stream. You will need to determine which
-    # parameters work for your specific hardware. These may work for those with Intel hardware that
-    # supports QuickSync.
-    ################
-    # ffmpeg_hwaccel_args:
-    #   - -hwaccel
-    #   - vaapi
-    #   - -hwaccel_device
-    #   - /dev/dri/renderD128
-    #   - -hwaccel_output_format
-    #   - yuv420p
-
-    ################
-    # FFmpeg log level. Default is "panic". https://ffmpeg.org/ffmpeg.html#Generic-options
-    ################
-    # ffmpeg_log_level: panic
-
-    ################
-    # Optional custom input args. Some cameras may need custom ffmpeg params to work reliably. Specifying
-    # these will replace the default input params.
-    ################
-    # ffmpeg_input_args: []
-
-    ################
-    # Optional custom output args. Some cameras may need custom ffmpeg params to work reliably. Specifying
-    # these will replace the default output params.
-    ################
-    # ffmpeg_output_args: []
     
     ################
     # size: size of the region in pixels

+ 24 - 1
detect_objects.py

@@ -19,6 +19,29 @@ MQTT_USER = CONFIG.get('mqtt', {}).get('user')
 MQTT_PASS = CONFIG.get('mqtt', {}).get('password')
 MQTT_CLIENT_ID = CONFIG.get('mqtt', {}).get('client_id', 'frigate')
 
+# Set the default FFmpeg config
+FFMPEG_CONFIG = CONFIG.get('ffmpeg', {})
+FFMPEG_DEFAULT_CONFIG = {
+    'global_args': FFMPEG_CONFIG.get('global_args', 
+        ['-hide_banner','-loglevel','panic']),
+    'hwaccel_args': FFMPEG_CONFIG.get('hwaccel_args', 
+        []),
+    'input_args': FFMPEG_CONFIG.get('input_args',
+        ['-avoid_negative_ts', 'make_zero',
+         '-fflags', 'nobuffer',
+         '-flags', 'low_delay',
+         '-strict', 'experimental',
+         '-fflags', '+genpts+discardcorrupt',
+         '-vsync', 'drop',
+         '-rtsp_transport', 'tcp',
+         '-stimeout', '5000000',
+         '-use_wallclock_as_timestamps', '1']),
+    'output_args': FFMPEG_CONFIG.get('output_args',
+        ['-vf', 'mpdecimate',
+         '-f', 'rawvideo',
+         '-pix_fmt', 'rgb24'])
+}
+
 WEB_PORT = CONFIG.get('web_port', 5000)
 DEBUG = (CONFIG.get('debug', '0') == '1')
 
@@ -51,7 +74,7 @@ def main():
 
     cameras = {}
     for name, config in CONFIG['cameras'].items():
-        cameras[name] = Camera(name, config, prepped_frame_queue, client, MQTT_TOPIC_PREFIX)
+        cameras[name] = Camera(name, FFMPEG_DEFAULT_CONFIG, config, prepped_frame_queue, client, MQTT_TOPIC_PREFIX)
 
     prepped_queue_processor = PreppedQueueProcessor(
         cameras,

+ 74 - 0
docs/DEVICES.md

@@ -0,0 +1,74 @@
+# Configuration Examples
+
+### Default (most RTSP cameras)
+This is the default ffmpeg command and should work with most RTSP cameras that send h264 video
+```yaml
+ffmpeg:
+  global_args:
+    - -hide_banner
+    - -loglevel
+    - panic
+  hwaccel_args: []
+  input_args:
+    - -avoid_negative_ts
+    - make_zero 
+    - -fflags
+    - nobuffer
+    - -flags
+    - low_delay
+    - -strict
+    - experimental
+    - -fflags
+    - +genpts+discardcorrupt
+    - -vsync
+    - drop
+    - -rtsp_transport
+    - tcp
+    - -stimeout
+    - '5000000' 
+    - -use_wallclock_as_timestamps
+    - '1'
+  output_args:
+    - -vf
+    - mpdecimate
+    - -f
+    - rawvideo
+    - -pix_fmt
+    - rgb24
+```
+
+### RTMP Cameras
+The input parameters need to be adjusted for RTMP cameras
+```yaml
+ffmpeg:
+input_args:
+    - -avoid_negative_ts
+    - make_zero
+    - -fflags
+    - nobuffer
+    - -flags
+    - low_delay
+    - -strict
+    - experimental
+    - -fflags
+    - +genpts+discardcorrupt
+    - -vsync
+    - drop
+    - -use_wallclock_as_timestamps
+    - '1'
+```
+
+
+### Hardware Acceleration
+
+Intel Quicksync
+```yaml
+ffmpeg:
+  hwaccel_args:
+    - -hwaccel
+    - vaapi
+    - -hwaccel_device
+    - /dev/dri/renderD128
+    - -hwaccel_output_format
+    - yuv420p
+```

+ 10 - 24
frigate/video.py

@@ -111,30 +111,20 @@ class CameraCapture(threading.Thread):
                 self.camera.frame_ready.notify_all()
 
 class Camera:
-    def __init__(self, name, config, prepped_frame_queue, mqtt_client, mqtt_prefix):
+    def __init__(self, name, ffmpeg_config, config, prepped_frame_queue, mqtt_client, mqtt_prefix):
         self.name = name
         self.config = config
         self.detected_objects = []
         self.recent_frames = {}
-        self.ffmpeg_input = get_ffmpeg_input(self.config['ffmpeg_input'])
+
+        self.ffmpeg = config.get('ffmpeg', {})
+        self.ffmpeg_input = get_ffmpeg_input(self.ffmpeg['input'])
+        self.ffmpeg_global_args = self.ffmpeg.get('global_args', ffmpeg_config['global_args'])
+        self.ffmpeg_hwaccel_args = self.ffmpeg.get('hwaccel_args', ffmpeg_config['hwaccel_args'])
+        self.ffmpeg_input_args = self.ffmpeg.get('input_args', ffmpeg_config['input_args'])
+        self.ffmpeg_output_args = self.ffmpeg.get('output_args', ffmpeg_config['output_args'])
+
         self.take_frame = self.config.get('take_frame', 1)
-        self.ffmpeg_log_level = self.config.get('ffmpeg_log_level', 'panic')
-        self.ffmpeg_hwaccel_args = self.config.get('ffmpeg_hwaccel_args', [])
-        self.ffmpeg_input_args = self.config.get('ffmpeg_input_args', [
-            '-avoid_negative_ts', 'make_zero', 
-            '-fflags', 'nobuffer',
-            '-flags', 'low_delay',
-            '-strict', 'experimental',
-            '-fflags', '+genpts+discardcorrupt',
-            '-vsync', 'drop',
-            '-rtsp_transport', 'tcp', 
-            '-stimeout', '5000000', 
-            '-use_wallclock_as_timestamps', '1'
-        ])
-        self.ffmpeg_output_args = self.config.get('ffmpeg_output_args', [
-            '-f', 'rawvideo',
-            '-pix_fmt', 'rgb24'
-        ])
         self.regions = self.config['regions']
         self.frame_shape = get_frame_shape(self.ffmpeg_input)
         self.frame_size = self.frame_shape[0] * self.frame_shape[1] * self.frame_shape[2]
@@ -232,12 +222,8 @@ class Camera:
         self.capture_thread.start()
     
     def start_ffmpeg(self):
-        ffmpeg_global_args = [
-            '-hide_banner', '-loglevel', self.ffmpeg_log_level
-        ]
-
         ffmpeg_cmd = (['ffmpeg'] +
-            ffmpeg_global_args +
+            self.ffmpeg_global_args +
             self.ffmpeg_hwaccel_args +
             self.ffmpeg_input_args +
             ['-i', self.ffmpeg_input] +