diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index d5a8d049a..10ba723eb 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -65,7 +65,7 @@ jobs: - name: Check out the repository uses: actions/checkout@v4 - name: Set up Python ${{ env.DEFAULT_PYTHON }} - uses: actions/setup-python@v4.7.0 + uses: actions/setup-python@v4.7.1 with: python-version: ${{ env.DEFAULT_PYTHON }} - name: Install requirements diff --git a/docker/main/Dockerfile b/docker/main/Dockerfile index c7fd149fd..aee067b25 100644 --- a/docker/main/Dockerfile +++ b/docker/main/Dockerfile @@ -33,7 +33,7 @@ RUN --mount=type=tmpfs,target=/tmp --mount=type=tmpfs,target=/var/cache/apt \ FROM scratch AS go2rtc ARG TARGETARCH WORKDIR /rootfs/usr/local/go2rtc/bin -ADD --link --chmod=755 "https://github.com/AlexxIT/go2rtc/releases/download/v1.7.1/go2rtc_linux_${TARGETARCH}" go2rtc +ADD --link --chmod=755 "https://github.com/AlexxIT/go2rtc/releases/download/v1.8.1/go2rtc_linux_${TARGETARCH}" go2rtc #### diff --git a/docker/main/install_deps.sh b/docker/main/install_deps.sh index a42b439ca..43fff479b 100755 --- a/docker/main/install_deps.sh +++ b/docker/main/install_deps.sh @@ -55,24 +55,16 @@ fi # arch specific packages if [[ "${TARGETARCH}" == "amd64" ]]; then - # use debian bookworm for AMD hwaccel packages - echo 'deb https://deb.debian.org/debian bookworm main contrib' >/etc/apt/sources.list.d/debian-bookworm.list + # use debian bookworm for hwaccel packages + echo 'deb https://deb.debian.org/debian bookworm main contrib non-free' >/etc/apt/sources.list.d/debian-bookworm.list apt-get -qq update - apt-get -qq install --no-install-recommends --no-install-suggests -y \ - mesa-va-drivers radeontop - rm -f /etc/apt/sources.list.d/debian-bookworm.list - - # Use debian testing repo only for intel hwaccel packages - echo 'deb http://deb.debian.org/debian testing main non-free' >/etc/apt/sources.list.d/debian-testing.list - apt-get -qq update - # intel-opencl-icd specifically for GPU support in OpenVino apt-get -qq install --no-install-recommends --no-install-suggests -y \ intel-opencl-icd \ - libva-drm2 intel-media-va-driver-non-free i965-va-driver libmfx1 intel-gpu-tools + mesa-va-drivers radeontop libva-drm2 intel-media-va-driver-non-free i965-va-driver libmfx1 intel-gpu-tools # something about this dependency requires it to be installed in a separate call rather than in the line above apt-get -qq install --no-install-recommends --no-install-suggests -y \ i965-va-driver-shaders - rm -f /etc/apt/sources.list.d/debian-testing.list + rm -f /etc/apt/sources.list.d/debian-bookworm.list fi if [[ "${TARGETARCH}" == "arm64" ]]; then diff --git a/docker/main/requirements-dev.txt b/docker/main/requirements-dev.txt index 0acd15ae4..9a68e601d 100644 --- a/docker/main/requirements-dev.txt +++ b/docker/main/requirements-dev.txt @@ -1,3 +1,3 @@ -black == 23.3.* +black == 23.10.* isort ruff diff --git a/docker/main/requirements-wheels.txt b/docker/main/requirements-wheels.txt index e01b4a15a..37028d33b 100644 --- a/docker/main/requirements-wheels.txt +++ b/docker/main/requirements-wheels.txt @@ -2,12 +2,12 @@ click == 8.1.* Flask == 2.3.* imutils == 0.5.* matplotlib == 3.7.* -mypy == 1.4.1 +mypy == 1.6.1 numpy == 1.23.* onvif_zeep == 0.2.12 opencv-python-headless == 4.7.0.* paho-mqtt == 1.6.* -peewee == 3.16.* +peewee == 3.17.* peewee_migrate == 1.12.* psutil == 5.9.* pydantic == 1.10.* @@ -15,7 +15,7 @@ git+https://github.com/fbcotter/py3nvml#egg=py3nvml PyYAML == 6.0.* pytz == 2023.3 ruamel.yaml == 0.17.* -tzlocal == 5.0.* +tzlocal == 5.1 types-PyYAML == 6.0.* requests == 2.31.* types-requests == 2.31.* diff --git a/docker/main/rootfs/usr/local/nginx/conf/nginx.conf b/docker/main/rootfs/usr/local/nginx/conf/nginx.conf index a857461b5..6d0861406 100644 --- a/docker/main/rootfs/usr/local/nginx/conf/nginx.conf +++ b/docker/main/rootfs/usr/local/nginx/conf/nginx.conf @@ -149,62 +149,55 @@ http { location /ws { proxy_pass http://mqtt_ws/; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_set_header Host $host; + include proxy.conf; } location /live/jsmpeg/ { proxy_pass http://jsmpeg/; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_set_header Host $host; + include proxy.conf; } location /live/mse/ { proxy_pass http://go2rtc/; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_set_header Host $host; + include proxy.conf; } location /live/webrtc/ { proxy_pass http://go2rtc/; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_set_header Host $host; + include proxy.conf; } location ~* /api/go2rtc([/]?.*)$ { proxy_pass http://go2rtc; rewrite ^/api/go2rtc(.*)$ /api$1 break; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_set_header Host $host; + include proxy.conf; } location ~* /api/.*\.(jpg|jpeg|png)$ { rewrite ^/api/(.*)$ $1 break; proxy_pass http://frigate_api; - proxy_pass_request_headers on; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; + include proxy.conf; } location /api/ { add_header Cache-Control "no-store"; expires off; proxy_pass http://frigate_api/; - proxy_pass_request_headers on; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; + include proxy.conf; + + location /api/stats { + access_log off; + rewrite ^/api/(.*)$ $1 break; + proxy_pass http://frigate_api; + include proxy.conf; + } + + location /api/version { + access_log off; + rewrite ^/api/(.*)$ $1 break; + proxy_pass http://frigate_api; + include proxy.conf; + } } location / { diff --git a/docker/main/rootfs/usr/local/nginx/conf/proxy.conf b/docker/main/rootfs/usr/local/nginx/conf/proxy.conf new file mode 100644 index 000000000..442c78718 --- /dev/null +++ b/docker/main/rootfs/usr/local/nginx/conf/proxy.conf @@ -0,0 +1,4 @@ +proxy_http_version 1.1; +proxy_set_header Upgrade $http_upgrade; +proxy_set_header Connection "Upgrade"; +proxy_set_header Host $host; \ No newline at end of file diff --git a/docs/docs/configuration/advanced.md b/docs/docs/configuration/advanced.md index e32795946..d652b3526 100644 --- a/docs/docs/configuration/advanced.md +++ b/docs/docs/configuration/advanced.md @@ -120,7 +120,7 @@ NOTE: The folder that is mapped from the host needs to be the folder that contai ## Custom go2rtc version -Frigate currently includes go2rtc v1.7.1, there may be certain cases where you want to run a different version of go2rtc. +Frigate currently includes go2rtc v1.8.1, there may be certain cases where you want to run a different version of go2rtc. To do this: diff --git a/docs/docs/configuration/camera_specific.md b/docs/docs/configuration/camera_specific.md index 270b12f70..2567b2c81 100644 --- a/docs/docs/configuration/camera_specific.md +++ b/docs/docs/configuration/camera_specific.md @@ -140,7 +140,7 @@ go2rtc: - rtspx://192.168.1.1:7441/abcdefghijk ``` -[See the go2rtc docs for more information](https://github.com/AlexxIT/go2rtc/tree/v1.7.1#source-rtsp) +[See the go2rtc docs for more information](https://github.com/AlexxIT/go2rtc/tree/v1.8.1#source-rtsp) In the Unifi 2.0 update Unifi Protect Cameras had a change in audio sample rate which causes issues for ffmpeg. The input rate needs to be set for record and rtmp if used directly with unifi protect. diff --git a/docs/docs/configuration/index.md b/docs/docs/configuration/index.md index db59cd62d..f659b5339 100644 --- a/docs/docs/configuration/index.md +++ b/docs/docs/configuration/index.md @@ -436,7 +436,7 @@ rtmp: enabled: False # Optional: Restream configuration -# Uses https://github.com/AlexxIT/go2rtc (v1.7.1) +# Uses https://github.com/AlexxIT/go2rtc (v1.8.1) go2rtc: # Optional: jsmpeg stream configuration for WebUI diff --git a/docs/docs/configuration/live.md b/docs/docs/configuration/live.md index f061d65ff..452daa68c 100644 --- a/docs/docs/configuration/live.md +++ b/docs/docs/configuration/live.md @@ -115,4 +115,4 @@ services: ::: -See [go2rtc WebRTC docs](https://github.com/AlexxIT/go2rtc/tree/v1.7.1#module-webrtc) for more information about this. +See [go2rtc WebRTC docs](https://github.com/AlexxIT/go2rtc/tree/v1.8.1#module-webrtc) for more information about this. diff --git a/docs/docs/configuration/restream.md b/docs/docs/configuration/restream.md index 405ffa7d4..319884ff0 100644 --- a/docs/docs/configuration/restream.md +++ b/docs/docs/configuration/restream.md @@ -7,7 +7,7 @@ title: Restream Frigate can restream your video feed as an RTSP feed for other applications such as Home Assistant to utilize it at `rtsp://:8554/`. Port 8554 must be open. [This allows you to use a video feed for detection in Frigate and Home Assistant live view at the same time without having to make two separate connections to the camera](#reduce-connections-to-camera). The video feed is copied from the original video feed directly to avoid re-encoding. This feed does not include any annotation by Frigate. -Frigate uses [go2rtc](https://github.com/AlexxIT/go2rtc/tree/v1.7.1) to provide its restream and MSE/WebRTC capabilities. The go2rtc config is hosted at the `go2rtc` in the config, see [go2rtc docs](https://github.com/AlexxIT/go2rtc/tree/v1.7.1#configuration) for more advanced configurations and features. +Frigate uses [go2rtc](https://github.com/AlexxIT/go2rtc/tree/v1.8.1) to provide its restream and MSE/WebRTC capabilities. The go2rtc config is hosted at the `go2rtc` in the config, see [go2rtc docs](https://github.com/AlexxIT/go2rtc/tree/v1.8.1#configuration) for more advanced configurations and features. :::note @@ -138,7 +138,7 @@ cameras: ## Advanced Restream Configurations -The [exec](https://github.com/AlexxIT/go2rtc/tree/v1.7.1#source-exec) source in go2rtc can be used for custom ffmpeg commands. An example is below: +The [exec](https://github.com/AlexxIT/go2rtc/tree/v1.8.1#source-exec) source in go2rtc can be used for custom ffmpeg commands. An example is below: NOTE: The output will need to be passed with two curly braces `{{output}}` diff --git a/docs/docs/guides/configuring_go2rtc.md b/docs/docs/guides/configuring_go2rtc.md index 8c9a492af..37ea0f819 100644 --- a/docs/docs/guides/configuring_go2rtc.md +++ b/docs/docs/guides/configuring_go2rtc.md @@ -11,7 +11,7 @@ Use of the bundled go2rtc is optional. You can still configure FFmpeg to connect # Setup a go2rtc stream -First, you will want to configure go2rtc to connect to your camera stream by adding the stream you want to use for live view in your Frigate config file. If you set the stream name under go2rtc to match the name of your camera, it will automatically be mapped and you will get additional live view options for the camera. Avoid changing any other parts of your config at this step. Note that go2rtc supports [many different stream types](https://github.com/AlexxIT/go2rtc/tree/v1.7.1#module-streams), not just rtsp. +First, you will want to configure go2rtc to connect to your camera stream by adding the stream you want to use for live view in your Frigate config file. If you set the stream name under go2rtc to match the name of your camera, it will automatically be mapped and you will get additional live view options for the camera. Avoid changing any other parts of your config at this step. Note that go2rtc supports [many different stream types](https://github.com/AlexxIT/go2rtc/tree/v1.8.1#module-streams), not just rtsp. ```yaml go2rtc: @@ -24,7 +24,7 @@ The easiest live view to get working is MSE. After adding this to the config, re ### What if my video doesn't play? -If you are unable to see your video feed, first check the go2rtc logs in the Frigate UI under Logs in the sidebar. If go2rtc is having difficulty connecting to your camera, you should see some error messages in the log. If you do not see any errors, then the video codec of the stream may not be supported in your browser. If your camera stream is set to H265, try switching to H264. You can see more information about [video codec compatibility](https://github.com/AlexxIT/go2rtc/tree/v1.7.1#codecs-madness) in the go2rtc documentation. If you are not able to switch your camera settings from H265 to H264 or your stream is a different format such as MJPEG, you can use go2rtc to re-encode the video using the [FFmpeg parameters](https://github.com/AlexxIT/go2rtc/tree/v1.7.1#source-ffmpeg). It supports rotating and resizing video feeds and hardware acceleration. Keep in mind that transcoding video from one format to another is a resource intensive task and you may be better off using the built-in jsmpeg view. Here is an example of a config that will re-encode the stream to H264 without hardware acceleration: +If you are unable to see your video feed, first check the go2rtc logs in the Frigate UI under Logs in the sidebar. If go2rtc is having difficulty connecting to your camera, you should see some error messages in the log. If you do not see any errors, then the video codec of the stream may not be supported in your browser. If your camera stream is set to H265, try switching to H264. You can see more information about [video codec compatibility](https://github.com/AlexxIT/go2rtc/tree/v1.8.1#codecs-madness) in the go2rtc documentation. If you are not able to switch your camera settings from H265 to H264 or your stream is a different format such as MJPEG, you can use go2rtc to re-encode the video using the [FFmpeg parameters](https://github.com/AlexxIT/go2rtc/tree/v1.8.1#source-ffmpeg). It supports rotating and resizing video feeds and hardware acceleration. Keep in mind that transcoding video from one format to another is a resource intensive task and you may be better off using the built-in jsmpeg view. Here is an example of a config that will re-encode the stream to H264 without hardware acceleration: ```yaml go2rtc: diff --git a/docs/docs/troubleshooting/faqs.md b/docs/docs/troubleshooting/faqs.md index da334d26e..ca64974fa 100644 --- a/docs/docs/troubleshooting/faqs.md +++ b/docs/docs/troubleshooting/faqs.md @@ -23,6 +23,17 @@ Ensure your cameras send h264 encoded video, or [transcode them](/configuration/ You can open `chrome://media-internals/` in another tab and then try to playback, the media internals page will give information about why playback is failing. +### What do I do if my cameras sub stream is not good enough? + +Frigate generally [recommends cameras with configurable sub streams](/frigate/hardware.md). However, if your camera does not have a sub stream that a suitable resolution, the main stream can be resized. + +To do this efficiently the following setup is required: +1. A GPU or iGPU must be available to do the scaling. +2. [ffmpeg presets for hwaccel](/configuration/hardware_acceleration.md) must be used +3. Set the desired detection resolution for `detect -> width` and `detect -> height`. + +When this is done correctly, the GPU will do the decoding and scaling which will result in a small increase in CPU usage but with better results. + ### My mjpeg stream or snapshots look green and crazy This almost always means that the width/height defined for your camera are not correct. Double check the resolution with VLC or another player. Also make sure you don't have the width and height values backwards. diff --git a/docs/sidebars.js b/docs/sidebars.js index 079af88f7..c814e6e6a 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -21,7 +21,7 @@ module.exports = { { type: "link", label: "Go2RTC Configuration Reference", - href: "https://github.com/AlexxIT/go2rtc/tree/v1.7.1#configuration", + href: "https://github.com/AlexxIT/go2rtc/tree/v1.8.1#configuration", }, ], Detectors: [ diff --git a/frigate/app.py b/frigate/app.py index 2549b4ebb..5ff3f8f16 100644 --- a/frigate/app.py +++ b/frigate/app.py @@ -36,7 +36,7 @@ from frigate.events.external import ExternalEventProcessor from frigate.events.maintainer import EventProcessor from frigate.http import create_app from frigate.log import log_process, root_configurer -from frigate.models import Event, Recordings, RecordingsToDelete, Timeline +from frigate.models import Event, Recordings, RecordingsToDelete, Regions, Timeline from frigate.object_detection import ObjectDetectProcess from frigate.object_processing import TrackedObjectProcessor from frigate.output import output_frames @@ -49,6 +49,7 @@ from frigate.stats import StatsEmitter, stats_init from frigate.storage import StorageMaintainer from frigate.timeline import TimelineProcessor from frigate.types import CameraMetricsTypes, FeatureMetricsTypes, PTZMetricsTypes +from frigate.util.object import get_camera_regions_grid from frigate.version import VERSION from frigate.video import capture_camera, track_camera from frigate.watchdog import FrigateWatchdog @@ -69,6 +70,7 @@ class FrigateApp: self.feature_metrics: dict[str, FeatureMetricsTypes] = {} self.ptz_metrics: dict[str, PTZMetricsTypes] = {} self.processes: dict[str, int] = {} + self.region_grids: dict[str, list[list[dict[str, int]]]] = {} def set_environment_vars(self) -> None: for key, value in self.config.environment_vars.items(): @@ -161,6 +163,7 @@ class FrigateApp: # issue https://github.com/python/typeshed/issues/8799 # from mypy 0.981 onwards "frame_queue": mp.Queue(maxsize=2), + "region_grid_queue": mp.Queue(maxsize=1), "capture_process": None, "process": None, "audio_rms": mp.Value("d", 0.0), # type: ignore[typeddict-item] @@ -333,7 +336,7 @@ class FrigateApp: 60, 10 * len([c for c in self.config.cameras.values() if c.enabled]) ), ) - models = [Event, Recordings, RecordingsToDelete, Timeline] + models = [Event, Recordings, RecordingsToDelete, Regions, Timeline] self.db.bind(models) def init_stats(self) -> None: @@ -458,6 +461,17 @@ class FrigateApp: output_processor.start() logger.info(f"Output process started: {output_processor.pid}") + def init_historical_regions(self) -> None: + # delete region grids for removed or renamed cameras + cameras = list(self.config.cameras.keys()) + Regions.delete().where(~(Regions.camera << cameras)).execute() + + # create or update region grids for each camera + for camera in self.config.cameras.values(): + self.region_grids[camera.name] = get_camera_regions_grid( + camera.name, camera.detect + ) + def start_camera_processors(self) -> None: for name, config in self.config.cameras.items(): if not self.config.cameras[name].enabled: @@ -475,8 +489,10 @@ class FrigateApp: self.detection_queue, self.detection_out_events[name], self.detected_frames_queue, + self.inter_process_queue, self.camera_metrics[name], self.ptz_metrics[name], + self.region_grids[name], ), ) camera_process.daemon = True @@ -617,6 +633,7 @@ class FrigateApp: self.start_detectors() self.start_video_output_processor() self.start_ptz_autotracker() + self.init_historical_regions() self.start_detected_frames_processor() self.start_camera_processors() self.start_camera_capture_processes() diff --git a/frigate/comms/dispatcher.py b/frigate/comms/dispatcher.py index 789531ee9..15ce9d34d 100644 --- a/frigate/comms/dispatcher.py +++ b/frigate/comms/dispatcher.py @@ -5,10 +5,11 @@ from abc import ABC, abstractmethod from typing import Any, Callable from frigate.config import FrigateConfig -from frigate.const import INSERT_MANY_RECORDINGS +from frigate.const import INSERT_MANY_RECORDINGS, REQUEST_REGION_GRID from frigate.models import Recordings from frigate.ptz.onvif import OnvifCommandEnum, OnvifController from frigate.types import CameraMetricsTypes, FeatureMetricsTypes, PTZMetricsTypes +from frigate.util.object import get_camera_regions_grid from frigate.util.services import restart_frigate logger = logging.getLogger(__name__) @@ -90,6 +91,11 @@ class Dispatcher: restart_frigate() elif topic == INSERT_MANY_RECORDINGS: Recordings.insert_many(payload).execute() + elif topic == REQUEST_REGION_GRID: + camera = payload + self.camera_metrics[camera]["region_grid_queue"].put( + get_camera_regions_grid(camera, self.config.cameras[camera].detect) + ) else: self.publish(topic, payload, retain=False) diff --git a/frigate/comms/ws.py b/frigate/comms/ws.py index 3c1d2eb12..151093779 100644 --- a/frigate/comms/ws.py +++ b/frigate/comms/ws.py @@ -85,7 +85,10 @@ class WebSocketClient(Communicator): # type: ignore[misc] logger.debug(f"payload for {topic} wasn't text. Skipping...") return - self.websocket_server.manager.broadcast(ws_message) + try: + self.websocket_server.manager.broadcast(ws_message) + except ConnectionResetError: + pass def stop(self) -> None: self.websocket_server.manager.close_all() diff --git a/frigate/const.py b/frigate/const.py index 93a999975..40bdbe08f 100644 --- a/frigate/const.py +++ b/frigate/const.py @@ -12,7 +12,7 @@ FRIGATE_LOCALHOST = "http://127.0.0.1:5000" PLUS_ENV_VAR = "PLUS_API_KEY" PLUS_API_HOST = "https://api.frigate.video" -# Attributes +# Attribute & Object Consts ATTRIBUTE_LABEL_MAP = { "person": ["face", "amazon"], @@ -21,6 +21,11 @@ ATTRIBUTE_LABEL_MAP = { ALL_ATTRIBUTE_LABELS = [ item for sublist in ATTRIBUTE_LABEL_MAP.values() for item in sublist ] +LABEL_CONSOLIDATION_MAP = { + "car": 0.8, + "face": 0.5, +} +LABEL_CONSOLIDATION_DEFAULT = 0.9 # Audio Consts @@ -51,6 +56,7 @@ MAX_PLAYLIST_SECONDS = 7200 # support 2 hour segments for a single playlist to # Internal Comms Topics INSERT_MANY_RECORDINGS = "insert_many_recordings" +REQUEST_REGION_GRID = "request_region_grid" # Autotracking diff --git a/frigate/events/cleanup.py b/frigate/events/cleanup.py index 1f1fb5f76..faba73979 100644 --- a/frigate/events/cleanup.py +++ b/frigate/events/cleanup.py @@ -83,14 +83,19 @@ class EventCleanup(threading.Thread): datetime.datetime.now() - datetime.timedelta(days=expire_days) ).timestamp() # grab all events after specific time - expired_events = Event.select( - Event.id, - Event.camera, - ).where( - Event.camera.not_in(self.camera_keys), - Event.start_time < expire_after, - Event.label == event.label, - Event.retain_indefinitely == False, + expired_events = ( + Event.select( + Event.id, + Event.camera, + ) + .where( + Event.camera.not_in(self.camera_keys), + Event.start_time < expire_after, + Event.label == event.label, + Event.retain_indefinitely == False, + ) + .namedtuples() + .iterator() ) # delete the media from disk for event in expired_events: @@ -136,14 +141,19 @@ class EventCleanup(threading.Thread): datetime.datetime.now() - datetime.timedelta(days=expire_days) ).timestamp() # grab all events after specific time - expired_events = Event.select( - Event.id, - Event.camera, - ).where( - Event.camera == name, - Event.start_time < expire_after, - Event.label == event.label, - Event.retain_indefinitely == False, + expired_events = ( + Event.select( + Event.id, + Event.camera, + ) + .where( + Event.camera == name, + Event.start_time < expire_after, + Event.label == event.label, + Event.retain_indefinitely == False, + ) + .namedtuples() + .iterator() ) # delete the grabbed clips from disk diff --git a/frigate/http.py b/frigate/http.py index 64ba51ea0..0061d338f 100644 --- a/frigate/http.py +++ b/frigate/http.py @@ -261,7 +261,7 @@ def send_to_plus(id): except Exception as ex: logger.exception(ex) return make_response( - jsonify({"success": False, "message": str(ex)}), + jsonify({"success": False, "message": "Error uploading image"}), 400, ) @@ -281,7 +281,7 @@ def send_to_plus(id): except Exception as ex: logger.exception(ex) return make_response( - jsonify({"success": False, "message": str(ex)}), + jsonify({"success": False, "message": "Error uploading annotation"}), 400, ) @@ -352,7 +352,7 @@ def false_positive(id): except Exception as ex: logger.exception(ex) return make_response( - jsonify({"success": False, "message": str(ex)}), + jsonify({"success": False, "message": "Error uploading false positive"}), 400, ) @@ -455,8 +455,9 @@ def get_labels(): else: events = Event.select(Event.label).distinct() except Exception as e: + logger.error(e) return make_response( - jsonify({"success": False, "message": f"Failed to get labels: {e}"}), 404 + jsonify({"success": False, "message": "Failed to get labels"}), 404 ) labels = sorted([e.label for e in events]) @@ -469,9 +470,9 @@ def get_sub_labels(): try: events = Event.select(Event.sub_label).distinct() - except Exception as e: + except Exception: return make_response( - jsonify({"success": False, "message": f"Failed to get sub_labels: {e}"}), + jsonify({"success": False, "message": "Failed to get sub_labels"}), 404, ) @@ -516,6 +517,7 @@ def delete_event(id): media.unlink(missing_ok=True) event.delete_instance() + Timeline.delete().where(Timeline.source_id == id).execute() return make_response( jsonify({"success": True, "message": "Event " + id + " deleted"}), 200 ) @@ -648,7 +650,7 @@ def event_snapshot(id): ) # read snapshot from disk with open( - os.path.join(CLIPS_DIR, f"{event.camera}-{id}.jpg"), "rb" + os.path.join(CLIPS_DIR, f"{event.camera}-{event.id}.jpg"), "rb" ) as image_file: jpg_bytes = image_file.read() except DoesNotExist: @@ -740,7 +742,7 @@ def event_clip(id): jsonify({"success": False, "message": "Clip not available"}), 404 ) - file_name = f"{event.camera}-{id}.mp4" + file_name = f"{event.camera}-{event.id}.mp4" clip_path = os.path.join(CLIPS_DIR, file_name) if not os.path.isfile(clip_path): @@ -956,9 +958,10 @@ def events(): .order_by(Event.start_time.desc()) .limit(limit) .dicts() + .iterator() ) - return jsonify([e for e in events]) + return jsonify(list(events)) @bp.route("/events//