2026-09-06 15:14:21 +00:00
2026-09-06 15:14:21 +00:00
2026-09-06 15:14:21 +00:00
2026-09-06 15:14:21 +00:00
2026-09-06 15:14:21 +00:00
2026-09-06 15:14:21 +00:00
2026-09-06 15:14:21 +00:00
2026-09-06 15:14:21 +00:00
2026-09-06 15:14:21 +00:00
2026-09-06 15:14:21 +00:00

Moonraker Timelapse Docker Template

This service watches a Klipper/Moonraker printer, captures a JPEG whenever the reported toolhead Z position increases by a configured layer height, and renders the captured frames to an H.264 MP4 after a successful print. Snapshot directories and videos are named with the print filename and UTC start date/time, for example benchy_20260905-210500 and benchy_20260905-210500.mp4.

Quick start

  1. Copy .env.example to .env.

  2. Set MOONRAKER_URL and CAMERA_SNAPSHOT_URL to the endpoints used by your printer and Mainsail.

  3. Start the service:

    docker compose up --build -d
    
  4. Open the panel at http://localhost:8080.

  5. Find rendered videos under ./timelapses.

Storage is organized with videos in the root timelapse folder and snapshots in a matching print folder:

timelapses/
├── benchy_20260905-210500.mp4
└── benchy_20260905-210500/
   ├── frame-000000.jpg
   └── frame-000001.jpg

The panel is also available when running locally with ./run.sh at http://localhost:8080. Set WEB_PORT to use another port. It shows Moonraker connectivity, printer state, current Z height, the latest captured snapshot, and downloadable completed videos. The JSON endpoints are /api/status and /api/videos; the latest JPEG is available at /api/snapshot.

To build the image directly instead of using Compose:

./build.sh

The default image is moonraker-timelapse:latest. Override it when publishing or testing a specific version:

IMAGE_NAME=registry.example.com/you/timelapse IMAGE_TAG=0.1.0 ./build.sh

For local development without Docker, install Python 3 and ffmpeg, then run:

./run.sh

The script loads .env when present, defaults OUTPUT_DIR to ./timelapses, and uses 127.0.0.1:7125 as the local Moonraker default. Set MOONRAKER_URL and CAMERA_SNAPSHOT_URL in .env when the printer or camera is on another host.

The default camera URL is compatible with common MJPEG camera configurations using ?action=snapshot. For a camera that exposes a different still-image endpoint, set CAMERA_SNAPSHOT_URL accordingly.

Render settings

Render behavior can be configured in .env:

Variable Default Purpose
VIDEO_FPS 12 Playback frame rate.
VIDEO_DUPLICATE_END_FRAMES 0 Copies of the final snapshot appended to hold the end of the video.
VIDEO_CODEC libx264 FFmpeg video encoder.
VIDEO_PRESET medium Encoder speed/compression preset.
VIDEO_CRF 18 H.264 quality; lower values produce larger, higher-quality files.
VIDEO_PIXEL_FORMAT yuv420p Output pixel format for broad player compatibility.

For example, VIDEO_FPS=24 and VIDEO_DUPLICATE_END_FRAMES=48 creates a two-second hold on the final snapshot.

How layer detection works

The worker polls Moonraker's print_stats and gcode_move objects. When slicer layer metadata (print_stats.info.current_layer) is available, it captures once per reported layer. Otherwise it falls back to detecting Z increases using MIN_LAYER_HEIGHT_MM; the default poll interval is 0.5 seconds, but layer metadata is recommended because a slow poll can miss a short Z move.

Development smoke test

The Python worker uses only the standard library. Validate syntax locally with:

python3 -m py_compile app.py
docker compose config

The service intentionally treats Moonraker and camera failures as recoverable polling errors, so a printer or camera reboot does not stop the container.

S
Description
No description provided
Readme
34 KiB
Languages
Python 57.8%
HTML 35.3%
Shell 5.5%
Dockerfile 1.4%