Compare commits

..

1 Commits

Author SHA1 Message Date
GuoQing Liu
39fd108334
Merge 9e72a825f3 into ba4a6a53d7 2026-05-01 08:24:34 -06:00
8 changed files with 17 additions and 59 deletions

View File

@ -10,14 +10,11 @@ If you've found a bug and want to fix it, go for it. Link to the relevant issue
### New features
A pull request is more than just code — it's a request for the maintainers to review, integrate, and support the change long-term. We're selective about what we take on, and prioritize changes that align with the project's direction and can be responsibly maintained in the long term.
**Large or highly-requested features** raise the bar even higher. Popularity signals demand, but it doesn't pre-approve any particular implementation. The bigger the change, the higher the long-term cost, and the more important it is that we're aligned on scope and approach before any code is written. A large PR that lands without prior discussion is unlikely to be merged as-is, no matter how well it's implemented.
Before writing code for a new feature:
Every new feature adds scope that the maintainers must test, maintain, and support long-term. Before writing code for a new feature:
1. **Check for existing discussion.** Search [feature requests](https://github.com/blakeblackshear/frigate/issues) and [discussions](https://github.com/blakeblackshear/frigate/discussions) to see if it's been proposed or discussed. Feature requests tagged with "planned" are on our radar — we plan to get to them, but we don't maintain a public roadmap or timeline. Check in with us first if you have interest in contributing to one.
2. **Start a discussion or feature request first.** This helps ensure your idea aligns with Frigate's direction before you invest time building it. Community interest in a feature request helps us gauge demand, though a great idea is a great idea even without a crowd behind it.
3. **Be open to "no".** We try to be thoughtful about what we take on, and sometimes that means saying no to good code if the feature isn't the right fit for the project. These calls are sometimes subjective, and we won't always get them right. We're happy to discuss and reconsider.
## AI usage policy
@ -42,8 +39,6 @@ We're not trying to gatekeep how you write code. Use whatever tools make you pro
Some honest context: when we review a PR, we're not just evaluating whether the code works today. We're evaluating whether we can maintain it, debug it, and extend it long-term — often without the original author's involvement. Code that the author doesn't deeply understand is code that nobody understands, and that's a liability.
One more thing worth saying directly: most maintainers already have access to the same AI tools you do. A PR that's entirely AI-generated — where the author can't explain the design, debug issues independently, or engage substantively in design discussions — doesn't offer something we couldn't produce ourselves. What makes a contribution genuinely valuable is the human judgment and domain understanding behind it, as well as the engagement during review that shapes it into something we can confidently take on long-term.
## Pull request guidelines
### Before submitting

View File

@ -108,18 +108,14 @@
.select {
cursor: pointer;
appearance: none;
-moz-appearance: none;
-webkit-appearance: none;
background: var(--ifm-background-color)
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23666' d='M6 8L1 3h10z'/%3E%3C/svg%3E")
no-repeat right 0.75rem center / 12px 12px;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23666' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 0.75rem center;
padding-right: 2rem;
}
[data-theme="light"] .select {
background: #fff
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23555' d='M6 8L1 3h10z'/%3E%3C/svg%3E")
no-repeat right 0.75rem center / 12px 12px;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
}
.helpText {

View File

@ -146,13 +146,8 @@ def config(request: Request):
for name, detector in config_obj.detectors.items()
}
# remove environment_vars for non-admin users
if request.headers.get("remote-role") != "admin":
config.pop("environment_vars", None)
# remove mqtt credentials
# remove the mqtt password
config["mqtt"].pop("password", None)
config["mqtt"].pop("user", None)
# remove the proxy secret
config["proxy"].pop("auth_secret", None)

View File

@ -52,12 +52,6 @@ class OvDetector(DetectionApi):
self.h = detector_config.model.height
self.w = detector_config.model.width
logger.info(
"Loading OpenVINO model %s on device %s",
detector_config.model.path,
detector_config.device,
)
self.runner = OpenVINOModelRunner(
model_path=detector_config.model.path,
device=detector_config.device,

View File

@ -349,13 +349,6 @@ def move_preview_frames(loc: str) -> None:
if not os.path.exists(preview_holdover):
return
if not os.access(preview_holdover, os.R_OK | os.W_OK):
logger.error(
"Insufficient permissions on preview restart cache at %s",
preview_holdover,
)
return
shutil.move(preview_holdover, preview_cache)
except shutil.Error:
logger.error("Failed to restore preview cache.")

View File

@ -361,17 +361,14 @@ class PreviewRecorder:
small_frame,
cv2.COLOR_YUV2BGR_I420,
)
cache_path = get_cache_image_name(self.camera_name, frame_time)
if not cv2.imwrite(
cache_path,
cv2.imwrite(
get_cache_image_name(self.camera_name, frame_time),
small_frame,
[
int(cv2.IMWRITE_WEBP_QUALITY),
PREVIEW_QUALITY_WEBP[self.config.record.preview.quality],
],
):
logger.error("Failed to write preview frame to %s", cache_path)
)
def write_data(
self,

View File

@ -38,22 +38,6 @@ export function getChunkedTimeDay(timeRange: TimeRange): TimeRange[] {
return data;
}
/**
* Find the chunk index that contains the given timestamp.
* Uses half-open intervals [after, before) for all chunks except the last,
* which uses a closed interval [after, before] so the terminal boundary
* is always reachable.
*/
export function findChunkIndex(chunks: TimeRange[], timestamp: number): number {
return chunks.findIndex((chunk, i) => {
const isLast = i === chunks.length - 1;
return (
chunk.after <= timestamp &&
(isLast ? chunk.before >= timestamp : chunk.before > timestamp)
);
});
}
export function getChunkedTimeRange(
startTimestamp: number,
endTimestamp: number,

View File

@ -26,7 +26,7 @@ import {
ReviewSummary,
ZoomLevel,
} from "@/types/review";
import { findChunkIndex, getChunkedTimeDay } from "@/utils/timelineUtil";
import { getChunkedTimeDay } from "@/utils/timelineUtil";
import {
MutableRefObject,
useCallback,
@ -169,7 +169,9 @@ export function RecordingView({
[timeRange],
);
const [selectedRangeIdx, setSelectedRangeIdx] = useState(
findChunkIndex(chunkedTimeRange, startTime),
chunkedTimeRange.findIndex((chunk) => {
return chunk.after <= startTime && chunk.before >= startTime;
}),
);
const currentTimeRange = useMemo<TimeRange>(
() =>
@ -272,7 +274,9 @@ export function RecordingView({
const updateSelectedSegment = useCallback(
(currentTime: number, updateStartTime: boolean) => {
const index = findChunkIndex(chunkedTimeRange, currentTime);
const index = chunkedTimeRange.findIndex(
(seg) => seg.after <= currentTime && seg.before >= currentTime,
);
if (index != -1) {
if (updateStartTime) {