mirror of
				https://github.com/blakeblackshear/frigate.git
				synced 2025-10-27 10:52:11 +01:00 
			
		
		
		
	Load labels dynamically for event filters (#6896)
* Load labels dynamically to include custom events and audio, do not include attribute labels * Formatting * Fix sorting * Also filter tracked object list on camera page * isort * Don't fail before load
This commit is contained in:
		
							parent
							
								
									3d40ed5d47
								
							
						
					
					
						commit
						ece070fee1
					
				@ -12,6 +12,16 @@ PLUS_ENV_VAR = "PLUS_API_KEY"
 | 
			
		||||
PLUS_API_HOST = "https://api.frigate.video"
 | 
			
		||||
BTBN_PATH = "/usr/lib/btbn-ffmpeg"
 | 
			
		||||
 | 
			
		||||
# Attributes
 | 
			
		||||
 | 
			
		||||
ATTRIBUTE_LABEL_MAP = {
 | 
			
		||||
    "person": ["face", "amazon"],
 | 
			
		||||
    "car": ["ups", "fedex", "amazon", "license_plate"],
 | 
			
		||||
}
 | 
			
		||||
ALL_ATTRIBUTE_LABELS = [
 | 
			
		||||
    item for sublist in ATTRIBUTE_LABEL_MAP.values() for item in sublist
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
# Regex Consts
 | 
			
		||||
 | 
			
		||||
REGEX_CAMERA_NAME = r"^[a-zA-Z0-9_-]+$"
 | 
			
		||||
 | 
			
		||||
@ -410,6 +410,24 @@ def set_sub_label(id):
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route("/labels")
 | 
			
		||||
def get_labels():
 | 
			
		||||
    camera = request.args.get("camera", type=str, default="")
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        if camera:
 | 
			
		||||
            events = Event.select(Event.label).where(Event.camera == camera).distinct()
 | 
			
		||||
        else:
 | 
			
		||||
            events = Event.select(Event.label).distinct()
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
        return jsonify(
 | 
			
		||||
            {"success": False, "message": f"Failed to get labels: {e}"}, "404"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    labels = sorted([e.label for e in events])
 | 
			
		||||
    return jsonify(labels)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route("/sub_labels")
 | 
			
		||||
def get_sub_labels():
 | 
			
		||||
    split_joined = request.args.get("split_joined", type=int)
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,7 @@ import numpy as np
 | 
			
		||||
from setproctitle import setproctitle
 | 
			
		||||
 | 
			
		||||
from frigate.config import CameraConfig, DetectConfig
 | 
			
		||||
from frigate.const import CACHE_DIR
 | 
			
		||||
from frigate.const import ALL_ATTRIBUTE_LABELS, ATTRIBUTE_LABEL_MAP, CACHE_DIR
 | 
			
		||||
from frigate.detectors.detector_config import PixelFormatEnum
 | 
			
		||||
from frigate.log import LogPipe
 | 
			
		||||
from frigate.motion import MotionDetector
 | 
			
		||||
@ -723,14 +723,6 @@ def process_frames(
 | 
			
		||||
    stop_event,
 | 
			
		||||
    exit_on_empty: bool = False,
 | 
			
		||||
):
 | 
			
		||||
    # attribute labels are not tracked and are not assigned regions
 | 
			
		||||
    attribute_label_map = {
 | 
			
		||||
        "person": ["face", "amazon"],
 | 
			
		||||
        "car": ["ups", "fedex", "amazon", "license_plate"],
 | 
			
		||||
    }
 | 
			
		||||
    all_attribute_labels = [
 | 
			
		||||
        item for sublist in attribute_label_map.values() for item in sublist
 | 
			
		||||
    ]
 | 
			
		||||
    fps = process_info["process_fps"]
 | 
			
		||||
    detection_fps = process_info["detection_fps"]
 | 
			
		||||
    current_frame_time = process_info["detection_frame"]
 | 
			
		||||
@ -906,7 +898,7 @@ def process_frames(
 | 
			
		||||
                tracked_detections = [
 | 
			
		||||
                    d
 | 
			
		||||
                    for d in consolidated_detections
 | 
			
		||||
                    if d[0] not in all_attribute_labels
 | 
			
		||||
                    if d[0] not in ALL_ATTRIBUTE_LABELS
 | 
			
		||||
                ]
 | 
			
		||||
                # now that we have refined our detections, we need to track objects
 | 
			
		||||
                object_tracker.match_and_update(frame_time, tracked_detections)
 | 
			
		||||
@ -916,7 +908,7 @@ def process_frames(
 | 
			
		||||
 | 
			
		||||
        # group the attribute detections based on what label they apply to
 | 
			
		||||
        attribute_detections = {}
 | 
			
		||||
        for label, attribute_labels in attribute_label_map.items():
 | 
			
		||||
        for label, attribute_labels in ATTRIBUTE_LABEL_MAP.items():
 | 
			
		||||
            attribute_detections[label] = [
 | 
			
		||||
                d for d in consolidated_detections if d[0] in attribute_labels
 | 
			
		||||
            ]
 | 
			
		||||
 | 
			
		||||
@ -22,6 +22,7 @@ const emptyObject = Object.freeze({});
 | 
			
		||||
 | 
			
		||||
export default function Camera({ camera }) {
 | 
			
		||||
  const { data: config } = useSWR('config');
 | 
			
		||||
  const { data: trackedLabels } = useSWR(['labels', { camera }]);
 | 
			
		||||
  const apiHost = useApiHost();
 | 
			
		||||
  const [showSettings, setShowSettings] = useState(false);
 | 
			
		||||
  const [viewMode, setViewMode] = useState('live');
 | 
			
		||||
@ -121,7 +122,9 @@ export default function Camera({ camera }) {
 | 
			
		||||
            <div className="max-w-5xl">
 | 
			
		||||
              <video-stream
 | 
			
		||||
                mode="mse"
 | 
			
		||||
                src={new URL(`${baseUrl.replace(/^http/, 'ws')}live/webrtc/api/ws?src=${cameraConfig.live.stream_name}`)}
 | 
			
		||||
                src={
 | 
			
		||||
                  new URL(`${baseUrl.replace(/^http/, 'ws')}live/webrtc/api/ws?src=${cameraConfig.live.stream_name}`)
 | 
			
		||||
                }
 | 
			
		||||
              />
 | 
			
		||||
            </div>
 | 
			
		||||
          </Fragment>
 | 
			
		||||
@ -203,7 +206,7 @@ export default function Camera({ camera }) {
 | 
			
		||||
      <div className="space-y-4">
 | 
			
		||||
        <Heading size="sm">Tracked objects</Heading>
 | 
			
		||||
        <div className="flex flex-wrap justify-start">
 | 
			
		||||
          {cameraConfig.objects.track.map((objectType) => (
 | 
			
		||||
          {(trackedLabels || []).map((objectType) => (
 | 
			
		||||
            <Card
 | 
			
		||||
              className="mb-4 mr-4"
 | 
			
		||||
              key={objectType}
 | 
			
		||||
 | 
			
		||||
@ -106,6 +106,7 @@ export default function Events({ path, ...props }) {
 | 
			
		||||
 | 
			
		||||
  const { data: config } = useSWR('config');
 | 
			
		||||
 | 
			
		||||
  const { data: allLabels } = useSWR(['labels']);
 | 
			
		||||
  const { data: allSubLabels } = useSWR(['sub_labels', { split_joined: 1 }]);
 | 
			
		||||
 | 
			
		||||
  const filterValues = useMemo(
 | 
			
		||||
@ -120,15 +121,10 @@ export default function Events({ path, ...props }) {
 | 
			
		||||
          .filter((value, i, self) => self.indexOf(value) === i),
 | 
			
		||||
        'None',
 | 
			
		||||
      ],
 | 
			
		||||
      labels: Object.values(config?.cameras || {})
 | 
			
		||||
        .reduce((memo, camera) => {
 | 
			
		||||
          memo = memo.concat(camera?.objects?.track || []);
 | 
			
		||||
          return memo;
 | 
			
		||||
        }, config?.objects?.track || [])
 | 
			
		||||
        .filter((value, i, self) => self.indexOf(value) === i),
 | 
			
		||||
      labels: Object.values(allLabels || {}),
 | 
			
		||||
      sub_labels: (allSubLabels || []).length > 0 ? [...Object.values(allSubLabels), 'None'] : [],
 | 
			
		||||
    }),
 | 
			
		||||
    [config, allSubLabels]
 | 
			
		||||
    [config, allLabels, allSubLabels]
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const onSave = async (e, eventId, save) => {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user