Home AssistantCamerasPTZ

Driveway storm timelapse

Turn a PTZ security camera into a storm-chasing timelapse rig: park on a saved sky pose, refocus, and sweep while snapping frames — then put tracking back when you are done.

Difficulty · IntermediateSetup · 1–2 hoursHA · current stable
Get the pack · from $19Have us set it up

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

  1. One script, two commands — the pack is a script blueprint. Call it with command: start or command: stop (two dashboard buttons are the usual way). A second start while a run is going does nothing.
  2. 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).
  3. Sweep and capture — a loop pans in steps between sweep_start and sweep_end (default 30 frames per leg), then back. Each step writes camera.snapshot to a dated folder, for example /media/timelapse/2026-10-17_1830/frame_00001.jpg. The interval helper sets the seconds between frames.
  4. 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.
  5. Stitch — a persistent notification tells you the folder. The pack’s stitch_timelapse.sh turns 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 number entities, an auto-tracking switch, and ideally an autofocus button (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 the onvif.ptz action can use the ONVIF example in the pack to park on a preset before the start.
  • Storage. Frames go to /media/timelapse by default. On Home Assistant OS, /media is allowed. For any other folder (for example a NAS share), add it to allowlist_external_dirs.
  • Stitching. Any computer with ffmpeg. On Home Assistant OS, copy the folder off the /media share 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_boolean timelapse running (so a second start is a no-op, and turning it off stops the run)
  • input_number sky tilt
  • input_number sweep start / sweep end (pan)
  • input_number interval 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

  1. 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.
  2. 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.
  3. 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_timelapse if you want to use the pack examples as they are.
  4. Add the start and stop buttons to a dashboard.
  5. 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.
  6. 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 to allowlist_external_dirs and 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_*.jpg in 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.

Changelog

v1.0 · Oct 14, 2026: First publish.