Repository: blakeblackshear/frigate

Issue:
[Support]: Exception on API call /stats [GET] due to missing clips/recordings directories
### Describe the problem you are having


On startup Frigate creates 'clips' and 'recordings'. However, today the API started causing an exception when /stats [GET] is called, saying "No such file or directory: '/media/frigate/clips'". Indeed the 'clips' directory was gone, even though Frigate auto-creates 'clips' and 'recordings' at each startup. I tried starting fresh by deleting the database and directories. On startup Frigate creates the directories, but thereafter it auto-deletes them if they are empty. So, probably the stats API should be changed to handle the case of a missing directory by realizing it means zero storage is utilized. Further, it seems contradictory to delete /clips directory, when part of the startup routine is making sure it is created. 

(As for why my clips directory is empty, this might be a separate issue? Right now I'm seeing recordings are being saved without any corresponding snapshots being saved.)

EDIT: For future reference, my /clips folder was being deleted by a rogue application on my NAS, Asustor Surveillance Center. 

### Version

frigate:0.12.0-beta3

### Frigate config file

```yaml
# yaml-language-server: $schema=http://192.168.1.2:5000/api/config/schema
mqtt:
  host: xxxxx
  port: 1883
  user: xxxx
  password: xxxxxxxxxxxxxxx
  
detectors:      
  cpu1:          
    type: cpu
    num_threads: 3
  cpu2:
    type: cpu
    num_threads: 3  

database:
  path: /db/frigate.db        #specify db since otherwise it would go on NAS

record: 
  enabled: True 
  events:
    pre_capture: 10
    post_capture: 10
    
snapshots:
  enabled: True

detect:
  fps: 5
  
#restream: 
#  birdseye: True    

motion:
  threshold: 40       # default 25
  contour_area: 30   #default 30
  
objects: 
  filters: 
    person:
      threshold: 0.65
    car:
      threshold: 0.65
    dog:
      threshold: 0.74
       
cameras:
  gate:
    ffmpeg:
      inputs:                  
        - path: xxxxxx
          roles:              #subfeed for detection. 
            - detect        
        - path: xxxxxxx
          roles:             #main feed for recording, rebroadcast
            - record
            - restream
    
    detect:
      width: 704
      height: 480
     
        
    objects:
      track:
        - person
        - car
        - dog

  reardoor:      
    ffmpeg:
      inputs:                  
        - path: xxxxx
          roles:              
            - detect                
        - path: xxxxxx
          roles:             
            - record
            - restream
      
    detect:
      width: 704
      height: 480  

    objects:
      track:
        - person
        - dog
```


### Relevant log output

```shell
2023-01-12 09:24:13.139562458  [2023-01-12 09:24:13] frigate.http                   ERROR   : Exception on /stats [GET]
2023-01-12 09:24:13.139565458  Traceback (most recent call last):
2023-01-12 09:24:13.139567058    File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 2525, in wsgi_app
2023-01-12 09:24:13.139568558      response = self.full_dispatch_request()
2023-01-12 09:24:13.139570158    File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 1822, in full_dispatch_request
2023-01-12 09:24:13.139571658      rv = self.handle_user_exception(e)
2023-01-12 09:24:13.139575058    File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 1820, in full_dispatch_request
2023-01-12 09:24:13.139578258      rv = self.dispatch_request()
2023-01-12 09:24:13.139580258    File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 1796, in dispatch_request
2023-01-12 09:24:13.139582058      return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
2023-01-12 09:24:13.139583758    File "/opt/frigate/frigate/http.py", line 779, in stats
2023-01-12 09:24:13.139585158      stats = stats_snapshot(
2023-01-12 09:24:13.139586958    File "/opt/frigate/frigate/stats.py", line 244, in stats_snapshot
2023-01-12 09:24:13.139588658      storage_stats = shutil.disk_usage(path)
2023-01-12 09:24:13.139590358    File "/usr/lib/python3.9/shutil.py", line 1262, in disk_usage
2023-01-12 09:24:13.139591857      st = os.statvfs(path)
2023-01-12 09:24:13.139593557  FileNotFoundError: [Errno 2] No such file or directory: '/media/frigate/clips'
```


### FFprobe output from your camera

```shell
n/a
```


### Frigate stats

_No response_

### Operating system

Windows

### Install method

Docker Compose

version: "3.9"
services:
  frigate:
    container_name: frigate
    privileged: true
    restart: unless-stopped
    image: ghcr.io/blakeblackshear/frigate:0.12.0-beta3
    shm_size: "256mb"
    volumes:
      - \\wsl.localhost\Ubuntu-20.04\etc\localtime:/etc/localtime:ro
      - C:/docker/frigate/config.yml:/config/config.yml   #config file
      - NAS_frigate:/media/frigate        #NAS storage - defined below
      - C:/docker/volumes/frigate/db:/db   #db 
      - type: tmpfs
        target: /tmp/cache
        tmpfs:
          size: 1000000000
    ports:
      - "5000:5000"
      - "1935:1935" 
      - "8554:8554"
    environment:
      FRIGATE_RTSP_PASSWORD: xxxxxxxxxxxxxxxx
      PLUS_API_KEY: xxxxxxxxxxxxx
      TZ: xxxxxxxxxxx
      
volumes:
  NAS_frigate:
    driver_opts:
      type: cifs
      o: "username=xxxxxx,password=xxxxxxxxxxx,file_mode=0777,dir_mode=0777"
      device: "//xxxxxxxxxxx/Surveillance/frigate"
       

### Coral version

CPU (no coral)

### Network connection

Wired

### Camera make and model

amcrest

### Any other information that may be helpful

_No response_


Discussion:
Show your docker compose file
> Show your docker compose file

Updated above. /media/frigate is mapped to my NAS. (it's working, recordings are being saved)
Nowhere in frigate do we delete the clips directory so that is very confusing. In any case agree that we should catch the file not found error
Weird, maybe my cameras are deleting it. Didn't seem to happen previously. I will try separating the NAS directories for frigate and the cameras. 

Edit: Not the cameras. If I create another directory /test and put some file in it, even this gets deleted. But /recordings does not get deleted while it contains recordings. 

Resolving patch:
diff --git a/frigate/http.py b/frigate/http.py
--- a/frigate/http.py
+++ b/frigate/http.py
@@ -884,6 +884,10 @@ def get_recordings_storage_usage():
         current_app.stats_tracking,
         current_app.hwaccel_errors,
     )["service"]["storage"][RECORD_DIR]
+
+    if not recording_stats:
+        return jsonify({})
+
     total_mb = recording_stats["total"]
 
     camera_usages: dict[
diff --git a/frigate/stats.py b/frigate/stats.py
--- a/frigate/stats.py
+++ b/frigate/stats.py
@@ -241,7 +241,11 @@ def stats_snapshot(
     }
 
     for path in [RECORD_DIR, CLIPS_DIR, CACHE_DIR, "/dev/shm"]:
-        storage_stats = shutil.disk_usage(path)
+        try:
+            storage_stats = shutil.disk_usage(path)
+        except FileNotFoundError:
+            stats["service"]["storage"][path] = {}
+
         stats["service"]["storage"][path] = {
             "total": round(storage_stats.total / 1000000, 1),
             "used": round(storage_stats.used / 1000000, 1),


Test patch: