Skip to content

Commit 50ac5a1

Browse files
hawkeye217NickM-27
andauthored
Miscellaneous fixes (0.17 beta) (#21764)
* Add 640x640 Intel NPU stats * use css instead of js for reviewed button hover state in filmstrip * update copilot instructions to copy HA's format * Set json schema for genai --------- Co-authored-by: Nicolas Mowen <[email protected]>
1 parent a75f694 commit 50ac5a1

File tree

8 files changed

+500
-60
lines changed

8 files changed

+500
-60
lines changed

.github/copilot-instructions.md

Lines changed: 385 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,385 @@
1-
- For Frigate NVR, never write strings in the frontend directly. Since the project uses `react-i18next`, use `t()` and write the English string in the relevant translations file in `web/public/locales/en`.
2-
- Always conform new and refactored code to the existing coding style in the project.
3-
- Always have a way to test your work and confirm your changes. When running backend tests, use `python3 -u -m unittest`.
1+
# GitHub Copilot Instructions for Frigate NVR
2+
3+
This document provides coding guidelines and best practices for contributing to Frigate NVR, a complete and local NVR designed for Home Assistant with AI object detection.
4+
5+
## Project Overview
6+
7+
Frigate NVR is a realtime object detection system for IP cameras that uses:
8+
9+
- **Backend**: Python 3.13+ with FastAPI, OpenCV, TensorFlow/ONNX
10+
- **Frontend**: React with TypeScript, Vite, TailwindCSS
11+
- **Architecture**: Multiprocessing design with ZMQ and MQTT communication
12+
- **Focus**: Minimal resource usage with maximum performance
13+
14+
## Code Review Guidelines
15+
16+
When reviewing code, do NOT comment on:
17+
18+
- Missing imports - Static analysis tooling catches these
19+
- Code formatting - Ruff (Python) and Prettier (TypeScript/React) handle formatting
20+
- Minor style inconsistencies already enforced by linters
21+
22+
## Python Backend Standards
23+
24+
### Python Requirements
25+
26+
- **Compatibility**: Python 3.13+
27+
- **Language Features**: Use modern Python features:
28+
- Pattern matching
29+
- Type hints (comprehensive typing preferred)
30+
- f-strings (preferred over `%` or `.format()`)
31+
- Dataclasses
32+
- Async/await patterns
33+
34+
### Code Quality Standards
35+
36+
- **Formatting**: Ruff (configured in `pyproject.toml`)
37+
- **Linting**: Ruff with rules defined in project config
38+
- **Type Checking**: Use type hints consistently
39+
- **Testing**: unittest framework - use `python3 -u -m unittest` to run tests
40+
- **Language**: American English for all code, comments, and documentation
41+
42+
### Logging Standards
43+
44+
- **Logger Pattern**: Use module-level logger
45+
46+
```python
47+
import logging
48+
49+
logger = logging.getLogger(__name__)
50+
```
51+
52+
- **Format Guidelines**:
53+
- No periods at end of log messages
54+
- No sensitive data (keys, tokens, passwords)
55+
- Use lazy logging: `logger.debug("Message with %s", variable)`
56+
- **Log Levels**:
57+
- `debug`: Development and troubleshooting information
58+
- `info`: Important runtime events (startup, shutdown, state changes)
59+
- `warning`: Recoverable issues that should be addressed
60+
- `error`: Errors that affect functionality but don't crash the app
61+
- `exception`: Use in except blocks to include traceback
62+
63+
### Error Handling
64+
65+
- **Exception Types**: Choose most specific exception available
66+
- **Try/Catch Best Practices**:
67+
- Only wrap code that can throw exceptions
68+
- Keep try blocks minimal - process data after the try/except
69+
- Avoid bare exceptions except in background tasks
70+
71+
Bad pattern:
72+
73+
```python
74+
try:
75+
data = await device.get_data() # Can throw
76+
# ❌ Don't process data inside try block
77+
processed = data.get("value", 0) * 100
78+
result = processed
79+
except DeviceError:
80+
logger.error("Failed to get data")
81+
```
82+
83+
Good pattern:
84+
85+
```python
86+
try:
87+
data = await device.get_data() # Can throw
88+
except DeviceError:
89+
logger.error("Failed to get data")
90+
return
91+
92+
# ✅ Process data outside try block
93+
processed = data.get("value", 0) * 100
94+
result = processed
95+
```
96+
97+
### Async Programming
98+
99+
- **External I/O**: All external I/O operations must be async
100+
- **Best Practices**:
101+
- Avoid sleeping in loops - use `asyncio.sleep()` not `time.sleep()`
102+
- Avoid awaiting in loops - use `asyncio.gather()` instead
103+
- No blocking calls in async functions
104+
- Use `asyncio.create_task()` for background operations
105+
- **Thread Safety**: Use proper synchronization for shared state
106+
107+
### Documentation Standards
108+
109+
- **Module Docstrings**: Concise descriptions at top of files
110+
```python
111+
"""Utilities for motion detection and analysis."""
112+
```
113+
- **Function Docstrings**: Required for public functions and methods
114+
115+
```python
116+
async def process_frame(frame: ndarray, config: Config) -> Detection:
117+
"""Process a video frame for object detection.
118+
119+
Args:
120+
frame: The video frame as numpy array
121+
config: Detection configuration
122+
123+
Returns:
124+
Detection results with bounding boxes
125+
"""
126+
```
127+
128+
- **Comment Style**:
129+
- Explain the "why" not just the "what"
130+
- Keep lines under 88 characters when possible
131+
- Use clear, descriptive comments
132+
133+
### File Organization
134+
135+
- **API Endpoints**: `frigate/api/` - FastAPI route handlers
136+
- **Configuration**: `frigate/config/` - Configuration parsing and validation
137+
- **Detectors**: `frigate/detectors/` - Object detection backends
138+
- **Events**: `frigate/events/` - Event management and storage
139+
- **Utilities**: `frigate/util/` - Shared utility functions
140+
141+
## Frontend (React/TypeScript) Standards
142+
143+
### Internationalization (i18n)
144+
145+
- **CRITICAL**: Never write user-facing strings directly in components
146+
- **Always use react-i18next**: Import and use the `t()` function
147+
148+
```tsx
149+
import { useTranslation } from "react-i18next";
150+
151+
function MyComponent() {
152+
const { t } = useTranslation(["views/live"]);
153+
return <div>{t("camera_not_found")}</div>;
154+
}
155+
```
156+
157+
- **Translation Files**: Add English strings to the appropriate json files in `web/public/locales/en`
158+
- **Namespaces**: Organize translations by feature/view (e.g., `views/live`, `common`, `views/system`)
159+
160+
### Code Quality
161+
162+
- **Linting**: ESLint (see `web/.eslintrc.cjs`)
163+
- **Formatting**: Prettier with Tailwind CSS plugin
164+
- **Type Safety**: TypeScript strict mode enabled
165+
- **Testing**: Vitest for unit tests
166+
167+
### Component Patterns
168+
169+
- **UI Components**: Use Radix UI primitives (in `web/src/components/ui/`)
170+
- **Styling**: TailwindCSS with `cn()` utility for class merging
171+
- **State Management**: React hooks (useState, useEffect, useCallback, useMemo)
172+
- **Data Fetching**: Custom hooks with proper loading and error states
173+
174+
### ESLint Rules
175+
176+
Key rules enforced:
177+
178+
- `react-hooks/rules-of-hooks`: error
179+
- `react-hooks/exhaustive-deps`: error
180+
- `no-console`: error (use proper logging or remove)
181+
- `@typescript-eslint/no-explicit-any`: warn (always use proper types instead of `any`)
182+
- Unused variables must be prefixed with `_`
183+
- Comma dangles required for multiline objects/arrays
184+
185+
### File Organization
186+
187+
- **Pages**: `web/src/pages/` - Route components
188+
- **Views**: `web/src/views/` - Complex view components
189+
- **Components**: `web/src/components/` - Reusable components
190+
- **Hooks**: `web/src/hooks/` - Custom React hooks
191+
- **API**: `web/src/api/` - API client functions
192+
- **Types**: `web/src/types/` - TypeScript type definitions
193+
194+
## Testing Requirements
195+
196+
### Backend Testing
197+
198+
- **Framework**: Python unittest
199+
- **Run Command**: `python3 -u -m unittest`
200+
- **Location**: `frigate/test/`
201+
- **Coverage**: Aim for comprehensive test coverage of core functionality
202+
- **Pattern**: Use `TestCase` classes with descriptive test method names
203+
```python
204+
class TestMotionDetection(unittest.TestCase):
205+
def test_detects_motion_above_threshold(self):
206+
# Test implementation
207+
```
208+
209+
### Test Best Practices
210+
211+
- Always have a way to test your work and confirm your changes
212+
- Write tests for bug fixes to prevent regressions
213+
- Test edge cases and error conditions
214+
- Mock external dependencies (cameras, APIs, hardware)
215+
- Use fixtures for test data
216+
217+
## Development Commands
218+
219+
### Python Backend
220+
221+
```bash
222+
# Run all tests
223+
python3 -u -m unittest
224+
225+
# Run specific test file
226+
python3 -u -m unittest frigate.test.test_ffmpeg_presets
227+
228+
# Check formatting (Ruff)
229+
ruff format --check frigate/
230+
231+
# Apply formatting
232+
ruff format frigate/
233+
234+
# Run linter
235+
ruff check frigate/
236+
```
237+
238+
### Frontend (from web/ directory)
239+
240+
```bash
241+
# Start dev server (AI agents should never run this directly unless asked)
242+
npm run dev
243+
244+
# Build for production
245+
npm run build
246+
247+
# Run linter
248+
npm run lint
249+
250+
# Fix linting issues
251+
npm run lint:fix
252+
253+
# Format code
254+
npm run prettier:write
255+
```
256+
257+
### Docker Development
258+
259+
AI agents should never run these commands directly unless instructed.
260+
261+
```bash
262+
# Build local image
263+
make local
264+
265+
# Build debug image
266+
make debug
267+
```
268+
269+
## Common Patterns
270+
271+
### API Endpoint Pattern
272+
273+
```python
274+
from fastapi import APIRouter, Request
275+
from frigate.api.defs.tags import Tags
276+
277+
router = APIRouter(tags=[Tags.Events])
278+
279+
@router.get("/events")
280+
async def get_events(request: Request, limit: int = 100):
281+
"""Retrieve events from the database."""
282+
# Implementation
283+
```
284+
285+
### Configuration Access
286+
287+
```python
288+
# Access Frigate configuration
289+
config: FrigateConfig = request.app.frigate_config
290+
camera_config = config.cameras["front_door"]
291+
```
292+
293+
### Database Queries
294+
295+
```python
296+
from frigate.models import Event
297+
298+
# Use Peewee ORM for database access
299+
events = (
300+
Event.select()
301+
.where(Event.camera == camera_name)
302+
.order_by(Event.start_time.desc())
303+
.limit(limit)
304+
)
305+
```
306+
307+
## Common Anti-Patterns to Avoid
308+
309+
### ❌ Avoid These
310+
311+
```python
312+
# Blocking operations in async functions
313+
data = requests.get(url) # ❌ Use async HTTP client
314+
time.sleep(5) # ❌ Use asyncio.sleep()
315+
316+
# Hardcoded strings in React components
317+
<div>Camera not found</div> # ❌ Use t("camera_not_found")
318+
319+
# Missing error handling
320+
data = await api.get_data() # ❌ No exception handling
321+
322+
# Bare exceptions in regular code
323+
try:
324+
value = await sensor.read()
325+
except Exception: # ❌ Too broad
326+
logger.error("Failed")
327+
```
328+
329+
### ✅ Use These Instead
330+
331+
```python
332+
# Async operations
333+
import aiohttp
334+
async with aiohttp.ClientSession() as session:
335+
async with session.get(url) as response:
336+
data = await response.json()
337+
338+
await asyncio.sleep(5) # ✅ Non-blocking
339+
340+
# Translatable strings in React
341+
const { t } = useTranslation();
342+
<div>{t("camera_not_found")}</div> # ✅ Translatable
343+
344+
# Proper error handling
345+
try:
346+
data = await api.get_data()
347+
except ApiException as err:
348+
logger.error("API error: %s", err)
349+
raise
350+
351+
# Specific exceptions
352+
try:
353+
value = await sensor.read()
354+
except SensorException as err: # ✅ Specific
355+
logger.exception("Failed to read sensor")
356+
```
357+
358+
## Project-Specific Conventions
359+
360+
### Configuration Files
361+
362+
- Main config: `config/config.yml`
363+
364+
### Directory Structure
365+
366+
- Backend code: `frigate/`
367+
- Frontend code: `web/`
368+
- Docker files: `docker/`
369+
- Documentation: `docs/`
370+
- Database migrations: `migrations/`
371+
372+
### Code Style Conformance
373+
374+
Always conform new and refactored code to the existing coding style in the project:
375+
376+
- Follow established patterns in similar files
377+
- Match indentation and formatting of surrounding code
378+
- Use consistent naming conventions (snake_case for Python, camelCase for TypeScript)
379+
- Maintain the same level of verbosity in comments and docstrings
380+
381+
## Additional Resources
382+
383+
- Documentation: https://docs.frigate.video
384+
- Main Repository: https://github.com/blakeblackshear/frigate
385+
- Home Assistant Integration: https://github.com/blakeblackshear/frigate-hass-integration

docs/docs/frigate/hardware.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ Inference speeds vary greatly depending on the CPU or GPU used, some known examp
167167
| Intel N100 | ~ 15 ms | s-320: 30 ms | 320: ~ 25 ms | | Can only run one detector instance |
168168
| Intel N150 | ~ 15 ms | t-320: 16 ms s-320: 24 ms | | | |
169169
| Intel Iris XE | ~ 10 ms | t-320: 6 ms t-640: 14 ms s-320: 8 ms s-640: 16 ms | 320: ~ 10 ms 640: ~ 20 ms | 320-n: 33 ms | |
170-
| Intel NPU | ~ 6 ms | s-320: 11 ms | 320: ~ 14 ms 640: ~ 34 ms | 320-n: 40 ms | |
170+
| Intel NPU | ~ 6 ms | s-320: 11 ms s-640: 30 ms | 320: ~ 14 ms 640: ~ 34 ms | 320-n: 40 ms | |
171171
| Intel Arc A310 | ~ 5 ms | t-320: 7 ms t-640: 11 ms s-320: 8 ms s-640: 15 ms | 320: ~ 8 ms 640: ~ 14 ms | | |
172172
| Intel Arc A380 | ~ 6 ms | | 320: ~ 10 ms 640: ~ 22 ms | 336: 20 ms 448: 27 ms | |
173173
| Intel Arc A750 | ~ 4 ms | | 320: ~ 8 ms | | |

0 commit comments

Comments
 (0)