mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-09-26 21:38:56 +03:00
Add sub stream recording with adaptive quality playback (#24009)
* add sub stream recording with adaptive quality playback Optionally record a second, lower bitrate stream alongside the main recording stream via a `record_sub` input role and `record.sub` config block, with its own retention windows. Recordings rows now carry the stream type plus the media details needed to serve both streams from one manifest: video codec, audio presence, audio codec and rate, and a record-time keyframe index. Playback resolves coverage across both streams and merges them into a single VOD sequence, falling back to a discontinuity manifest with per-clip init segments when the media signatures differ. The player exposes a quality selector, and an auto governor picks the stream from stall time, bandwidth, codec support, and the save-data hint. * fix tests and i18n
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { isIOS } from "react-device-detect";
|
||||
import { useTimelineUtils } from "./use-timeline-utils";
|
||||
import { FrigateConfig } from "@/types/frigateConfig";
|
||||
import useSWR from "swr";
|
||||
@@ -10,6 +11,11 @@ import useUserInteraction from "./use-user-interaction";
|
||||
|
||||
const DRAG_STATE_COMMIT_MS = 100;
|
||||
|
||||
// iOS Safari synthesizes a click shortly after a drag's touchend even
|
||||
// though the touchend handler calls preventDefault; clicks observed in
|
||||
// traces arrive ~50ms after release
|
||||
const GHOST_CLICK_WINDOW_MS = 400;
|
||||
|
||||
type DraggableElementProps = {
|
||||
contentRef: React.RefObject<HTMLElement | null>;
|
||||
timelineRef: React.RefObject<HTMLDivElement | null>;
|
||||
@@ -164,9 +170,28 @@ function useDraggableElement({
|
||||
setDraggableElementTime(pendingDragTimeRef.current);
|
||||
pendingDragTimeRef.current = null;
|
||||
}
|
||||
|
||||
// iOS Safari synthesizes a click after touchend despite the
|
||||
// preventDefault, hit-tested at the drag origin where a segment
|
||||
// now sits; its onClick would yank the handlebar back
|
||||
if (isIOS && "TouchEvent" in window && e instanceof TouchEvent) {
|
||||
const swallow = (clickEvent: MouseEvent) => {
|
||||
cleanup();
|
||||
if (timelineRef.current?.contains(clickEvent.target as Node)) {
|
||||
clickEvent.preventDefault();
|
||||
clickEvent.stopPropagation();
|
||||
}
|
||||
};
|
||||
const cleanup = () => {
|
||||
document.removeEventListener("click", swallow, true);
|
||||
window.clearTimeout(timer);
|
||||
};
|
||||
const timer = window.setTimeout(cleanup, GHOST_CLICK_WINDOW_MS);
|
||||
document.addEventListener("click", swallow, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
[isDragging, setIsDragging, setDraggableElementTime],
|
||||
[isDragging, setIsDragging, setDraggableElementTime, timelineRef],
|
||||
);
|
||||
|
||||
const timestampToPixels = useCallback(
|
||||
|
||||
Reference in New Issue
Block a user