mirror of
				https://github.com/blakeblackshear/frigate.git
				synced 2025-10-27 10:52:11 +01:00 
			
		
		
		
	* POC: Added FastAPI with one endpoint (get /logs/service) * POC: Revert error_log * POC: Converted preview related endpoints to FastAPI * POC: Converted two more endpoints to FastAPI * POC: lint * Convert all media endpoints to FastAPI. Added /media prefix (/media/camera && media/events && /media/preview) * Convert all notifications API endpoints to FastAPI * Convert first review API endpoints to FastAPI * Convert remaining review API endpoints to FastAPI * Convert export endpoints to FastAPI * Fix path parameters * Convert events endpoints to FastAPI * Use body for multiple events endpoints * Use body for multiple events endpoints (create and end event) * Convert app endpoints to FastAPI * Convert app endpoints to FastAPI * Convert auth endpoints to FastAPI * Removed flask app in favour of FastAPI app. Implemented FastAPI middleware to check CSRF, connect and disconnect from DB. Added middleware x-forwared-for headers * Added starlette plugin to expose custom headers * Use slowapi as the limiter * Use query parameters for the frame latest endpoint * Use query parameters for the media snapshot.jpg endpoint * Use query parameters for the media MJPEG feed endpoint * Revert initial nginx.conf change * Added missing even_id for /events/search endpoint * Removed left over comment * Use FastAPI TestClient * severity query parameter should be a string * Use the same pattern for all tests * Fix endpoint * Revert media routers to old names. Order routes to make sure the dynamic ones from media.py are only used whenever there's no match on auth/etc * Reverted paths for media on tsx files * Deleted file * Fix test_http to use TestClient * Formatting * Bind timeline to DB * Fix http tests * Replace filename with pathvalidate * Fix latest.ext handling and disable uvicorn access logs * Add cosntraints to api provided values * Formatting * Remove unused * Remove unused * Get rate limiter working --------- Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
		
			
				
	
	
		
			114 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """Preview apis."""
 | |
| 
 | |
| import logging
 | |
| import os
 | |
| from datetime import datetime, timedelta, timezone
 | |
| 
 | |
| import pytz
 | |
| from fastapi import APIRouter
 | |
| from fastapi.responses import JSONResponse
 | |
| 
 | |
| from frigate.api.defs.tags import Tags
 | |
| from frigate.const import CACHE_DIR, PREVIEW_FRAME_TYPE
 | |
| from frigate.models import Previews
 | |
| 
 | |
| logger = logging.getLogger(__name__)
 | |
| 
 | |
| 
 | |
| router = APIRouter(tags=[Tags.preview])
 | |
| 
 | |
| 
 | |
| @router.get("/preview/{camera_name}/start/{start_ts}/end/{end_ts}")
 | |
| def preview_ts(camera_name: str, start_ts: float, end_ts: float):
 | |
|     """Get all mp4 previews relevant for time period."""
 | |
|     if camera_name != "all":
 | |
|         camera_clause = Previews.camera == camera_name
 | |
|     else:
 | |
|         camera_clause = True
 | |
| 
 | |
|     previews = (
 | |
|         Previews.select(
 | |
|             Previews.camera,
 | |
|             Previews.path,
 | |
|             Previews.duration,
 | |
|             Previews.start_time,
 | |
|             Previews.end_time,
 | |
|         )
 | |
|         .where(
 | |
|             Previews.start_time.between(start_ts, end_ts)
 | |
|             | Previews.end_time.between(start_ts, end_ts)
 | |
|             | ((start_ts > Previews.start_time) & (end_ts < Previews.end_time))
 | |
|         )
 | |
|         .where(camera_clause)
 | |
|         .order_by(Previews.start_time.asc())
 | |
|         .dicts()
 | |
|         .iterator()
 | |
|     )
 | |
| 
 | |
|     clips = []
 | |
| 
 | |
|     preview: Previews
 | |
|     for preview in previews:
 | |
|         clips.append(
 | |
|             {
 | |
|                 "camera": preview["camera"],
 | |
|                 "src": preview["path"].replace("/media/frigate", ""),
 | |
|                 "type": "video/mp4",
 | |
|                 "start": preview["start_time"],
 | |
|                 "end": preview["end_time"],
 | |
|             }
 | |
|         )
 | |
| 
 | |
|     if not clips:
 | |
|         return JSONResponse(
 | |
|             content={
 | |
|                 "success": False,
 | |
|                 "message": "No previews found.",
 | |
|             },
 | |
|             status_code=404,
 | |
|         )
 | |
| 
 | |
|     return JSONResponse(content=clips, status_code=200)
 | |
| 
 | |
| 
 | |
| @router.get("/preview/{year_month}/{day}/{hour}/{camera_name}/{tz_name}")
 | |
| def preview_hour(year_month: str, day: int, hour: int, camera_name: str, tz_name: str):
 | |
|     """Get all mp4 previews relevant for time period given the timezone"""
 | |
|     parts = year_month.split("-")
 | |
|     start_date = (
 | |
|         datetime(int(parts[0]), int(parts[1]), int(day), int(hour), tzinfo=timezone.utc)
 | |
|         - datetime.now(pytz.timezone(tz_name.replace(",", "/"))).utcoffset()
 | |
|     )
 | |
|     end_date = start_date + timedelta(hours=1) - timedelta(milliseconds=1)
 | |
|     start_ts = start_date.timestamp()
 | |
|     end_ts = end_date.timestamp()
 | |
| 
 | |
|     return preview_ts(camera_name, start_ts, end_ts)
 | |
| 
 | |
| 
 | |
| @router.get("/preview/{camera_name}/start/{start_ts}/end/{end_ts}/frames")
 | |
| def get_preview_frames_from_cache(camera_name: str, start_ts: float, end_ts: float):
 | |
|     """Get list of cached preview frames"""
 | |
|     preview_dir = os.path.join(CACHE_DIR, "preview_frames")
 | |
|     file_start = f"preview_{camera_name}"
 | |
|     start_file = f"{file_start}-{start_ts}.{PREVIEW_FRAME_TYPE}"
 | |
|     end_file = f"{file_start}-{end_ts}.{PREVIEW_FRAME_TYPE}"
 | |
|     selected_previews = []
 | |
| 
 | |
|     for file in sorted(os.listdir(preview_dir)):
 | |
|         if not file.startswith(file_start):
 | |
|             continue
 | |
| 
 | |
|         if file < start_file:
 | |
|             continue
 | |
| 
 | |
|         if file > end_file:
 | |
|             break
 | |
| 
 | |
|         selected_previews.append(file)
 | |
| 
 | |
|     return JSONResponse(
 | |
|         content=selected_previews,
 | |
|         status_code=200,
 | |
|     )
 |