feat: Add support for Frigate reviews / detections [initial PR] (#2315)
- Add support for Frigate reviews / detections. - Add support for GenAI metadata. - Significant internal refactor to more flexible "UnifiedQuery" to allow mixing cameras with simple metadata and review metadata (e.g. a timeline view of a Frigate camera with reviews, and a Reolink camera with simple metadata). - Add support for folder media as camera media. There are a few more PRs to commit prior to this going live, but commiting this for now due to the scale of the change. BREAKING CHANGE: `media_type` and `events_type` are retired under `live`, `viewer` and `timeline` configuration sections, instead media type is associated (once) with the camera under `media`.
This commit is contained in:
@@ -8,12 +8,17 @@ import {
|
||||
getRecordingID,
|
||||
getRecordingMediaContentID,
|
||||
getRecordingTitle,
|
||||
getReviewMediaContentID,
|
||||
getReviewSeverity,
|
||||
getReviewThumbnailURL,
|
||||
getReviewTitle,
|
||||
} from '../../../src/camera-manager/frigate/util';
|
||||
import { CameraConfig } from '../../../src/config/schema/cameras';
|
||||
import {
|
||||
createCameraConfig,
|
||||
createFrigateEvent,
|
||||
createFrigateRecording,
|
||||
createFrigateReview,
|
||||
} from '../../test-utils';
|
||||
|
||||
describe('getEventTitle', () => {
|
||||
@@ -152,3 +157,108 @@ describe('getRecordingID', () => {
|
||||
).toBe('//1682776800000/1682780399000');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getReviewTitle', () => {
|
||||
const start = new Date('2023-05-06T10:43:00');
|
||||
const end = new Date('2023-05-06T10:44:12');
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it('should get finished review title without objects', () => {
|
||||
expect(
|
||||
getReviewTitle(
|
||||
createFrigateReview({
|
||||
start_time: start.getTime() / 1000,
|
||||
end_time: end.getTime() / 1000,
|
||||
data: {
|
||||
objects: [],
|
||||
zones: [],
|
||||
},
|
||||
}),
|
||||
),
|
||||
).toBe('2023-05-06 10:43 [72s]');
|
||||
});
|
||||
|
||||
it('should get finished review title with objects', () => {
|
||||
expect(
|
||||
getReviewTitle(
|
||||
createFrigateReview({
|
||||
start_time: start.getTime() / 1000,
|
||||
end_time: end.getTime() / 1000,
|
||||
data: {
|
||||
objects: ['person', 'dog'],
|
||||
},
|
||||
}),
|
||||
),
|
||||
).toBe('Person, Dog');
|
||||
});
|
||||
|
||||
it('should get in-progress review title', () => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(add(start, { seconds: 60 }));
|
||||
|
||||
expect(
|
||||
getReviewTitle(
|
||||
createFrigateReview({
|
||||
start_time: start.getTime() / 1000,
|
||||
end_time: null,
|
||||
data: {
|
||||
objects: [],
|
||||
},
|
||||
}),
|
||||
),
|
||||
).toBe('2023-05-06 10:43 [60s]');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getReviewMediaContentID', () => {
|
||||
it('should get review content ID', () => {
|
||||
expect(
|
||||
getReviewMediaContentID(
|
||||
'clientid',
|
||||
'kitchen',
|
||||
createFrigateReview({
|
||||
start_time: new Date('2023-04-29T14:00:00').getTime() / 1000,
|
||||
}),
|
||||
),
|
||||
).toBe('media-source://frigate/clientid/recordings/kitchen/2023-04-29/14');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getReviewThumbnailURL', () => {
|
||||
it('should get thumbnail URL', () => {
|
||||
expect(
|
||||
getReviewThumbnailURL(
|
||||
'clientid',
|
||||
createFrigateReview({
|
||||
thumb_path: '/media/frigate/thumb.jpg',
|
||||
}),
|
||||
),
|
||||
).toBe('/api/frigate/clientid/thumb.jpg');
|
||||
});
|
||||
|
||||
it('should return null when no thumb path', () => {
|
||||
expect(
|
||||
getReviewThumbnailURL(
|
||||
'clientid',
|
||||
createFrigateReview({
|
||||
thumb_path: null,
|
||||
}),
|
||||
),
|
||||
).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getReviewSeverity', () => {
|
||||
it('should get alert severity', () => {
|
||||
expect(getReviewSeverity('alert')).toBe('high');
|
||||
});
|
||||
it('should get detection severity', () => {
|
||||
expect(getReviewSeverity('detection')).toBe('medium');
|
||||
});
|
||||
it('should get significant_motion severity', () => {
|
||||
expect(getReviewSeverity('significant_motion')).toBe('low');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user