Skip to content

Timelapse

Daniel Heinen edited this page May 9, 2026 · 1 revision

Timelapse

ankerctl can capture a timelapse video automatically for every print. Snapshots are taken from the printer's built-in camera (or an external feed), buffered to disk, and assembled into an MP4 with ffmpeg when the print finishes.

Requirements

  • ffmpeg available in PATH (Docker images ship with it; for Python installs, install separately)
  • A working PPPP camera connection (the navbar PPPP status dot must be green)
  • TIMELAPSE_ENABLED=true (env var or Setup → Timelapse)

Verify ffmpeg:

ffmpeg -version

Quick setup

Set in .env:

TIMELAPSE_ENABLED=true
TIMELAPSE_INTERVAL_SEC=30
TIMELAPSE_MAX_VIDEOS=10
TIMELAPSE_CAPTURES_DIR=/captures

Or use Setup → Timelapse in the web UI to set the same values per printer.

Restart ankerctl (or click Save in the UI — POST /api/settings/timelapse auto-reloads the service).

How it works

  1. Print starts (MqttQueue sees ct=1000 value=1):
    • TimelapseService.start_capture(filename) is called
    • A persistent frame directory is created under TIMELAPSE_CAPTURES_DIR/in_progress/<name>_<timestamp>/
    • A .meta sidecar file records the print metadata
  2. Every TIMELAPSE_INTERVAL_SEC seconds:
    • VideoQueue is asked for a JPEG snapshot
    • If TIMELAPSE_LIGHT=snapshot: light on → wait 1.5 s → snap → wait 1 s → light off
    • The frame is written to the persistent directory
  3. Print ends (ct=1000 value=0):
    • TimelapseService.finish_capture(final=True) is called
    • ffmpeg assembles all frames into an MP4
    • Old videos are pruned when TIMELAPSE_MAX_VIDEOS is exceeded (oldest first)
    • The .meta sidecar is deleted
  4. Resume window: if a new print with the same filename starts within 60 minutes of finish_capture(final=False), the frames are reused and the timelapse is appended.
  5. Container restart safety: persistent frames in in_progress/ survive container restarts. Orphaned directories older than 24 hours are cleaned up on startup.

FPS calculation

The output video targets ~30 seconds in length:

fps = max(1, min(30, ceil(frame_count / 30)))

So a print with 90 captured frames produces a 30-second video at 3 fps; a print with 1500 frames produces a 50-second video at 30 fps.

Light control

TIMELAPSE_LIGHT controls when the printer LED is on:

Value Behavior
snapshot Light on for each frame, off in between (per-frame)
session Light on at capture start, off at capture finish
(unset) Do not touch the light

snapshot mode produces consistent lighting per frame at the cost of constant LED activity. session is best when ambient light is sufficient and you only want a continuous on/off bracket.

Camera source

TIMELAPSE_CAMERA_SOURCE chooses which feed is captured:

Value Source
follow Use the Home page's selected camera
printer Always use the built-in printer camera
external Always use the configured external camera feed

Using printer or external lets you switch viewing on the Home page without disrupting an active timelapse capture.

Web UI

The Timelapse tab (visible only when TIMELAPSE_ENABLED=true) shows:

  • Player (left) — inline MP4 preview
  • List (right) — every assembled video with size and creation date
  • Download and Delete actions per video
  • Auto-refresh every 15 seconds

Pause / resume / stop controls for the currently running capture are also exposed in the same tab.

Per-printer settings

Each printer can have its own timelapse configuration. The active printer's settings are persisted to default.json under printers[i].timelapse.

Settings exposed per printer:

  • enabled
  • interval_sec
  • max_videos
  • light (snapshot / session / unset)
  • camera_source (follow / printer / external)

Storage layout

Inside TIMELAPSE_CAPTURES_DIR (default /captures):

captures/
├── in_progress/
│   └── my-print_20260509_120000/
│       ├── frame_0001.jpg
│       ├── frame_0002.jpg
│       └── ...
│       └── .meta
└── my-print_20260509_120030.mp4

The in_progress/ subdirectory is internal — videos appear in the parent directory once ffmpeg assembly finishes.

API endpoints

Method Path Description
GET /api/timelapses List videos with metadata
GET /api/timelapse/<filename> Download an MP4
DELETE /api/timelapse/<filename> Delete a video (path-traversal protected)
GET /api/settings/timelapse Get current config
POST /api/settings/timelapse Update config; auto-reloads service

See API Reference for headers and example payloads.

Tuning

Goal Setting
Smoother videos Lower TIMELAPSE_INTERVAL_SEC (e.g. 15) — more frames, more disk
Smaller files Raise TIMELAPSE_INTERVAL_SEC (e.g. 60)
More history Raise TIMELAPSE_MAX_VIDEOS (default 10)
Brighter shots TIMELAPSE_LIGHT=snapshot (per-frame) or session
Don't burn the LED leave TIMELAPSE_LIGHT unset
Avoid stream interruptions during snapshots APPRISE_SNAPSHOT_QUALITY=fhd (uses snapshot-only mode)

Troubleshooting

See Troubleshooting → Timelapse issues for common problems (no recording, empty videos, light not toggling).

Clone this wiki locally