How to Use Frigate's Profile System for Camera State Management: A Complete Guide
Frigate's profile system lets you define named configuration overrides for cameras and switch between them dynamically at runtime without restarting, enabling modes like "armed," "disarmed," or "night" through the activate_profile() method in ProfileManager.
Frigate's profile system provides a powerful mechanism for runtime camera state management, allowing users to toggle between predefined operating modes instantly. This feature eliminates the need to restart the service when changing detection sensitivity, enabling cameras, or modifying zone configurations. By leveraging the ProfileManager class and CameraProfileConfig models defined in the source code, you can implement complex security scenarios like home/away modes directly through the API or configuration files.
Architecture of the Profile System
The profile implementation centers on two core modules that handle configuration snapshots and state transitions:
frigate/config/camera/profile.py– Defines theCameraProfileConfigPydantic model that holds optional overrides for each configurable camera section (detect, motion, objects, zones, etc.)frigate/config/profile_manager.py– Orchestrates snapshotting of original camera configs, applying selected profiles, resetting to base configurations, and dispatching ZMQ updates to downstream components
When ProfileManager initializes, it immediately calls _snapshot_base_configs() to capture the unmodified state of every camera. This creates two internal stores: _base_configs containing the raw dictionary representations and _base_api_configs holding JSON-ready versions of detect, motion, record, zones, and other sections.
How Profile Activation Works
The activate_profile(name) method in ProfileManager executes a three-phase transition process:
- Reset Phase – Calls
_reset_to_base()to restore every camera to its original snapshot state, including enabled flags and zone definitions - Apply Phase – Invokes
_apply_profile_overrides(name)which walks each camera'sprofilesdictionary, merges the specified profile's sections onto the base configs usingdeep_merge, and updates camera objects viaapply_section_update - Publish Phase – Triggers
_publish_updates()to emit ZMQ messages only for sections that actually changed, notifying detection, motion, and recording components
Passing None to activate_profile() triggers a full reset to base configuration with no active profile. After successful activation, the manager persists the active profile name to CONFIG_DIR/.profiles (the PERSISTENCE_FILE), restoring it automatically on startup via load_persisted_profile().
Configuring Profiles in YAML
Define profiles in your top-level config.yml under the profiles key. Each profile specifies a friendly_name and per-camera overrides for any supported section:
profiles:
armed:
friendly_name: "Armed"
camera:
front:
enabled: true
motion:
threshold: 0.5
zones:
driveway:
coordinates: [[0,0],[640,0],[640,480],[0,480]]
disarmed:
friendly_name: "Disarmed"
camera:
front:
enabled: false
Only sections listed in PROFILE_SECTION_UPDATES support overrides: audio, birdseye, detect, face_recognition, lpr, motion, notifications, objects, record, review, snapshots, and zones. Overrides are partial—any field left unset (None) inherits the camera's original base value.
Programmatic Profile Management
Interact with the profile system programmatically using the ProfileManager class alongside CameraConfigUpdatePublisher for ZMQ communication:
# Activate a profile from Python code
from frigate.config.profile_manager import ProfileManager
from frigate.config.config import FrigateConfig
from frigate.config.camera.updater import CameraConfigUpdatePublisher
# Assume `config` is the parsed FrigateConfig and `updater` is running
pm = ProfileManager(config, CameraConfigUpdatePublisher())
error = pm.activate_profile("armed")
if error:
print("Failed:", error)
else:
print("Profile 'armed' activated")
Reset all cameras to base configuration by passing None:
# Deactivate any active profile (reset to base)
pm.activate_profile(None) # Resets all cameras to original config
Query current state through API helper methods:
# Query the currently active profile via the API helper
active = pm.get_profile_info()
print("Active profile:", active["active_profile"])
print("Available profiles:", [p["name"] for p in active["profiles"]])
Zone Handling and Merging Behavior
Zones require special handling during profile application because they are stored as ZoneConfig objects rather than plain dictionaries. When _apply_profile_overrides() processes zone overrides, it:
- Merges the profile's zone dictionary onto the base zones configuration
- Calls
generate_contourto ensure each zone has valid coordinates - Preserves the original zone color if the profile omits the color field
This ensures that temporary profiles can modify zone geometry or disable specific zones without losing visual styling defined in the base configuration.
REST API Integration
The ProfileManager exposes helper methods that feed the REST API and WebSocket interfaces:
get_base_configs_for_api()– Returns the original unmodified configuration for referenceget_available_profiles()– Lists all profiles defined in the top-level configurationget_profile_info()– Returns the active profile name and available options
These methods support the /api/config endpoint, allowing external home automation systems to query state and trigger profile changes via HTTP POST requests to /config/set with a profile parameter.
Summary
- ProfileManager in
frigate/config/profile_manager.pyhandles all runtime profile switching throughactivate_profile(), maintaining base configuration snapshots and managing ZMQ update publication. - CameraProfileConfig in
frigate/config/camera/profile.pydefines the override structure for per-camera settings including detect, motion, objects, and zones. - Profiles support partial overrides—unspecified fields inherit from base configuration, while specified fields replace base values completely.
- The system persists active profiles to
CONFIG_DIR/.profilesand automatically restores the last active state on Frigate startup. - Zone configurations merge specially to preserve contours and colors while allowing coordinate overrides.
Frequently Asked Questions
What sections of the camera configuration can profiles override?
Profiles can override any of the following sections as defined in PROFILE_SECTION_UPDATES: audio, birdseye, detect, face_recognition, lpr, motion, notifications, objects, record, review, snapshots, and zones. Each profile defines per-camera overrides for only the sections you want to change, leaving other settings at their base values.
How do I temporarily disable all detection without restarting Frigate?
Create a "disarmed" profile in your config.yml that sets enabled: false for your cameras, then activate it via the API or Python code using pm.activate_profile("disarmed"). To restore normal operation, call pm.activate_profile(None) to reset to base configuration or activate your "armed" profile.
Are profile changes persistent across Frigate restarts?
Yes. The ProfileManager automatically writes the active profile name to a hidden persistence file at CONFIG_DIR/.profiles after each successful activation. On startup, load_persisted_profile() reads this file and restores the last active profile, ensuring your cameras return to their intended state after system reboots.
Can I modify zones dynamically using profiles?
Yes. Profiles support zone overrides in the zones section. When applying a profile, the system merges your zone configuration onto the base zones, regenerates contours, and preserves original colors if not specified. This allows you to enable/disable specific zones or adjust their coordinates for different security modes without touching the base configuration.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →