Move seeking support into the engine.

This commit is contained in:
Dermot Duffy
2023-01-24 19:36:54 -08:00
parent 13816c3025
commit 6b2036676c
12 changed files with 142 additions and 176 deletions
+7
View File
@@ -77,4 +77,11 @@ export interface CameraManagerEngine {
queries: MediaQueries,
results: MediaQueriesResults,
): boolean;
getMediaSeekTime(
hass: HomeAssistant,
cameras: Map<string, CameraConfig>,
media: ViewMedia,
target: Date,
): Promise<number | null>;
}
+58
View File
@@ -392,6 +392,32 @@ export class FrigateCameraManagerEngine implements CameraManagerEngine {
);
}
public async getMediaSeekTime(
hass: HomeAssistant,
cameras: Map<string, CameraConfig>,
media: ViewMedia,
target: Date,
): Promise<number | null> {
const start = media.getStartTime();
const end = media.getEndTime();
if (!start || !end || target < start || target > end) {
return null;
}
const query: RecordingSegmentsQuery = {
cameraID: media.getCameraID(),
start: start,
end: end,
type: QueryType.RecordingSegments,
};
const segments = await this.getRecordingSegments(hass, cameras, query);
const out = segments
? this._getSeekTimeInSegments(start, target, segments.segments)
: null;
return out;
}
protected _getQueryableCameraConfig(
cameras: Map<string, CameraConfig>,
cameraID: string,
@@ -466,4 +492,36 @@ export class FrigateCameraManagerEngine implements CameraManagerEngine {
`Released ${segmentsStart - countSegments()} segment(s)`,
);
}
/**
* Get the number of seconds to seek into a video stream consisting of the
* provided segments to reach the target time provided.
* @param startTime The earliest allowable time to seek from.
* @param targetTime Target time.
* @param segments An array of segments dataset items. Must be sorted from oldest to youngest.
* @returns
*/
protected _getSeekTimeInSegments(
startTime: Date,
targetTime: Date,
segments: RecordingSegment[],
): number | null {
if (!segments.length) {
return null;
}
let seekMilliseconds = 0;
// Inspired by: https://github.com/blakeblackshear/frigate/blob/release-0.11.0/web/src/routes/Recording.jsx#L27
for (const segment of segments) {
const segmentStart = fromUnixTime(segment.start_time);
if (segmentStart > targetTime) {
break;
}
const segmentEnd = fromUnixTime(segment.end_time);
const start = segmentStart < startTime ? startTime : segmentStart;
const end = segmentEnd > targetTime ? targetTime : segmentEnd;
seekMilliseconds += end.getTime() - start.getTime();
}
return seekMilliseconds / 1000;
}
}
+1
View File
@@ -26,6 +26,7 @@ export const getRecordingsSummary = async (
type: 'frigate/recordings/summary',
instance_id: client_id,
camera: camera_name,
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
},
true,
);
+22
View File
@@ -278,6 +278,28 @@ export class CameraManager {
return true;
}
public async getMediaSeekTime(
hass: HomeAssistant,
media: ViewMedia,
target: Date,
): Promise<number | null> {
const startTime = media.getStartTime();
const endTime = media.getEndTime();
const cameraConfig = this._cameras.get(media.getCameraID());
if (
!cameraConfig ||
!startTime ||
!endTime ||
target < startTime ||
target > endTime
) {
return null;
}
const engine = this._engineFactory.getEngineForCamera(cameraConfig);
return (await engine?.getMediaSeekTime(hass, this._cameras, media, target)) ?? null;
}
protected async _handleQuery<QT extends DataQuery>(
hass: HomeAssistant,
query: QT | QT[],