Record any RTSP (or other ffmpeg‑readable) camera stream to a local file on demand from Home Assistant. Start when motion begins, keep recording as long as you want, and stop when motion clears — or just tap a dashboard button to toggle recording.
Privacy: All example addresses and paths below use placeholders like
<CAMERA_HOST>,<PORT>, and<STREAM_PATH>. Replace them with your actual values.
Why? Home Assistant’s built‑in
camera.recordmakes fixed‑length clips. Cam Record lets you start/stop freely, so your clip can be minutes or hours — limited mainly by storage.
-
Two services to control a background
ffmpegprocess:cam_record.record_start(stream_url, filename, recording_id?)cam_record.record_stop(recording_id or stream_url)
-
Works with RTSP (and anything
ffmpegcan read). -
Saves anywhere you choose (e.g., under
/media/so clips appear in HA’s Media browser). -
Designed for automations (motion start/stop, doorbell press) and dashboard toggles.
Tip: If your camera is quirky, run it through go2rtc and use a stable RTSP/MP4‑friendly URL.
- Home Assistant (recent version)
ffmpegavailable in the HA environment (included in HA OS/Container)- A writable output directory (create it first). Recommended: a subfolder under
/media/.
- HACS → Integrations → ⋯ → Custom repositories → add
https://github.com/B0st0wn/cam_record(Category: Integration). - Install Cam Record.
- Restart Home Assistant.
-
Copy the folder to your HA config:
<config>/custom_components/cam_record/ -
Restart Home Assistant.
The services will appear automatically in Developer Tools → Services.
Add these lines to your configuration.yaml and restart Home Assistant:
ffmpeg:
cam_record:Starts an ffmpeg process and writes the stream to the provided path.
Fields
stream_url(string, required): RTSP/HTTP/etc. (e.g.,rtsp://cam:554/stream).filename(string, required): Absolute output path (e.g.,/media/front_door/2025-08-17_11-45-00.mp4).recording_id(string, optional): Stable key to stop later without depending on exact URL text.
Example
service: cam_record.record_start
data:
recording_id: front_door_motion
stream_url: rtsp://<CAMERA_HOST>:<PORT>/<STREAM_PATH>?mp4
filename: /media/front_door/front_door_{{ now().strftime('%Y-%m-%d_%H-%M-%S') }}.mp4Stops a recording by recording_id (recommended) or by stream_url.
Fields
recording_id(string, optional): Preferred stop key if you set one on start.stream_url(string, optional): Fallback stop key if norecording_idwas used.- At least one of
recording_idorstream_urlis required.
Example
service: cam_record.record_stop
data:
recording_id: front_door_motion- Create a directory for recordings, e.g.
/media/front_door. - From Developer Tools → Services, call
cam_record.record_startwith your RTSP URL and a filename under that folder. - When you’re done, call
cam_record.record_stopwith the samerecording_id(or the same URL if you did not set one).
alias: Front Door - Record while motion
mode: restart
trigger:
- platform: state
entity_id: binary_sensor.front_door_motion
to: "on"
- platform: state
entity_id: binary_sensor.front_door_motion
to: "off"
for: "00:00:10" # optional grace period to avoid rapid stop/start
variables:
recording_id: front_door_motion
stream_url: rtsp://<CAMERA_HOST>:<PORT>/<STREAM_PATH>?mp4
outdir: /media/front_door
action:
- choose:
- conditions: "{{ trigger.to_state.state == 'on' }}"
sequence:
- service: cam_record.record_start
data:
recording_id: "{{ recording_id }}"
stream_url: "{{ stream_url }}"
filename: "{{ outdir }}/front_door_{{ now().strftime('%Y-%m-%d_%H-%M-%S') }}.mp4"
- conditions: "{{ trigger.to_state.state == 'off' }}"
sequence:
- service: cam_record.record_stop
data:
recording_id: "{{ recording_id }}"Create a helper and two tiny automations that react to it.
Helper
input_boolean:
front_door_recording:
name: Front Door RecordingAutomation: ON → start recording
alias: Front Door Recording - Start
trigger:
- platform: state
entity_id: input_boolean.front_door_recording
to: "on"
action:
- service: cam_record.record_start
data:
recording_id: front_door_toggle
stream_url: rtsp://<CAMERA_HOST>:<PORT>/<STREAM_PATH>?mp4
filename: /media/front_door/front_door_{{ now().strftime('%Y-%m-%d_%H-%M-%S') }}.mp4
mode: singleAutomation: OFF → stop recording
alias: Front Door Recording - Stop
trigger:
- platform: state
entity_id: input_boolean.front_door_recording
to: "off"
action:
- service: cam_record.record_stop
data:
recording_id: front_door_toggle
mode: singleLovelace (example button)
type: button
entity: input_boolean.front_door_recording
name: Record Front Door
icon: mdi:record-circle
show_state: true- No file appears → Ensure the parent folder exists and is writable (try under
/media). - Cannot stop recording → Use a
recording_idin both start/stop calls to avoid URL mismatch issues. - RTSP instability → Prefer TCP RTSP URLs (many cameras accept
?mp4/TCP variants) or normalize via go2rtc. - Storage growth → Long clips grow quickly; use dated filenames/folders and prune periodically.
-
Domain:
cam_record -
Structure:
custom_components/cam_record/__init__.py— registersrecord_start/record_stopand tracks processesservices.yaml— schemas and field hintsmanifest.json— integration metadatarecorder.py— thin wrapper aroundffmpegexecution
Contributions welcome!