Some hardware links on this page are affiliate links. As an Amazon Associate I earn from qualifying purchases. We may earn a commission if you buy through them, at no extra cost to you. See the affiliate disclosure.
A PTZ security camera already has a motor, a zoom, and a snapshot path. This workflow parks it on a sky pose, turns auto-tracking off, retriggers autofocus, then walks pan between two helper numbers while it writes frames. When you stop, tracking and your watch preset come back.
The write-up talks about an outdoor PTZ, not about which opening, yard, or window a camera covers. Point it at sky, not at neighbors.
What problem it solves
A storm rolls in and you want the timelapse, but setting it up by hand means turning off tracking, steering the camera, and remembering to put everything back. This pack makes it one start and one stop, with a safety limit so a forgotten run cannot fill the disk or leave the camera pointed at the sky all night.
How it works
- One script, two commands — the pack is a script blueprint. Call it with
command: startorcommand: stop(two dashboard buttons are the usual way). A second start while a run is going does nothing. - Park — on start, it turns auto-tracking off, sets zoom to your sky value, moves tilt to the sky helper (or picks a sky preset if your camera exposes presets as a select), moves pan to the sweep start, then presses the autofocus button and waits for focus (default 6 seconds).
- Sweep and capture — a loop pans in steps between
sweep_startandsweep_end(default 30 frames per leg), then back. Each step writescamera.snapshotto a dated folder, for example/media/timelapse/2026-10-17_1830/frame_00001.jpg. The interval helper sets the seconds between frames. - Stop — the stop command, turning the running helper off by hand, or the safety stop (default 90 minutes) all end the loop the same way: the running flag clears, the watch preset comes back (if you set one), and auto-tracking turns back on.
- Stitch — a persistent notification tells you the folder. The pack’s
stitch_timelapse.shturns that folder into an mp4 with ffmpeg on any computer.
No stills from a real property ship with the pack. Test with a bench camera or a cloudy sky.
Hardware notes
- Camera. An outdoor PTZ whose Home Assistant integration exposes pan, tilt, and zoom as
numberentities, an auto-trackingswitch, and ideally an autofocusbutton(Reolink TrackMix / E1 Outdoor class). Every camera input except the camera itself is optional, so a camera without zoom or autofocus still works. - Presets instead of numbers. If your camera exposes presets as a
select, set a sky preset and a watch preset in the blueprint. Cameras that move only through theonvif.ptzaction can use the ONVIF example in the pack to park on a preset before the start. - Storage. Frames go to
/media/timelapseby default. On Home Assistant OS,/mediais allowed. For any other folder (for example a NAS share), add it toallowlist_external_dirs. - Stitching. Any computer with ffmpeg. On Home Assistant OS, copy the folder off the
/mediashare or use the SSH add-on.
Snippet
Two dashboard buttons call the one script (script.storm_timelapse is the name the pack examples use):
type: horizontal-stack
cards:
- type: button
name: Start timelapse
icon: mdi:weather-lightning
tap_action:
action: perform-action
perform_action: script.storm_timelapse
data:
command: start
- type: button
name: Stop
icon: mdi:stop
tap_action:
action: perform-action
perform_action: script.storm_timelapse
data:
command: stop
Each frame is a plain snapshot into the run folder:
- action: camera.snapshot
target:
entity_id: "{{ camera }}"
data:
filename: "{{ run_folder }}/frame_{{ '%05d' % repeat.index }}.jpg"
Helpers to add
The pack includes a Home Assistant package with these (or make them in the Helpers UI):
input_booleantimelapse running (so a second start is a no-op, and turning it off stops the run)input_numbersky tiltinput_numbersweep start / sweep end (pan)input_numberinterval seconds (1–60, default 6)
Match the min and max of the tilt and pan helpers to what your camera’s number entities accept.
Setup outline
- Confirm the camera’s pan, tilt, zoom, tracking, and focus entities in Developer Tools → States. Move each number by hand once and note the values that frame the sky.
- Add the helpers (pack package or Helpers UI). Set sky tilt, sweep start, and sweep end to the values you noted, and the interval to 5–8 seconds.
- Import the script blueprint and create the script. Fill the camera inputs you have, the four helpers, the frame folder, and optional sky and watch presets. Save it as
script.storm_timelapseif you want to use the pack examples as they are. - Add the start and stop buttons to a dashboard.
- Test: press start → tracking turns off, the camera parks and refocuses, frames appear in a dated folder. Press stop → the loop ends, tracking comes back, and a notification names the folder.
- Stitch: copy the folder to a computer with ffmpeg and run
./stitch_timelapse.sh /path/to/folder 24.
Troubleshooting
- Soft frames. Autofocus was still hunting. Raise the focus wait, or zoom out a little so the camera has more contrast to lock on.
- Integration has no zoom/tilt numbers. Some camera brands expose PTZ only as services (
onvif, manufacturer). Leave the pan and tilt inputs empty and use the ONVIF example in the pack, or a preset select. - No frames saved. The folder is not allowed. Use
/media/...on Home Assistant OS, or add the folder toallowlist_external_dirsand restart. - Disk fills up. An interval of 2 s on a 4K camera is a lot. Start at 5–8 s; prune the dated folder after you stitch.
- Run ended early. The safety stop hit. Raise the safety stop minutes for long storms.
- Tracking does not resume. Stop must run even if you abort. Bind it to a dashboard button, or turn the running helper off by hand; both take the same restore path.
- Stitch fails with “No such file”. The script expects
frame_*.jpgin the folder you pass. Point it at the dated run folder, not its parent.
Privacy
Do not publish timelapse frames, EXIF, or a map of where the camera sits. This page is the control pattern only.