Skip to content

rootedbox/webcam-timelapse

Repository files navigation

WebcamTimelapse

CI Latest release

Minimal native macOS app that records a webcam timelapse and saves it as an mp4.

Download

Grab the latest prebuilt .app from the Releases page — look for WebcamTimelapse-vX.Y.Z.zip.

The binary is ad-hoc signed (no Apple Developer ID), so macOS Gatekeeper will block it on first launch. To get past that:

  • Easy way: right-click WebcamTimelapse.appOpen → click Open in the warning dialog.
  • One-shot CLI fix:
    xattr -dr com.apple.quarantine /Applications/WebcamTimelapse.app

Each release also ships a .sha256 file alongside the zip if you want to verify the download.

What it does

  • Pick any connected camera (built-in or USB).
  • Live preview the selected camera as soon as it's chosen — no need to start recording first.
  • Capture one still frame every N seconds (default 5s; configurable 1–3600).
  • Encode captured frames into an H.264 mp4 played back at M fps (default 30; configurable 1–60).
  • On Stop, review the recorded clip inline (with playback controls) and choose Save or Discard.
  • Single-window app — no automatic tab bar, no New Window menu item.

Requirements

  • macOS 13 (Ventura) or later
  • Xcode 15 or later (project builds with Xcode 26)
  • Camera permission (granted on first run)

Build

xcodebuild -project WebcamTimelapse.xcodeproj \
  -scheme WebcamTimelapse \
  -configuration Debug \
  build

The built .app lives under the configured DerivedData path.

To run from Xcode: open WebcamTimelapse.xcodeproj, pick the WebcamTimelapse scheme, hit Run.

Tests

xcodebuild -project WebcamTimelapse.xcodeproj \
  -scheme WebcamTimelapse \
  -destination 'platform=macOS' \
  test

Covers:

  • TimelapseEncoder — synthetic pixel buffers in, readable mp4 out
  • FrameGrabber — timer cadence and stop semantics
  • Settings — round-trip persistence and clamping

Usage

  1. Launch the app and grant camera access when prompted.
  2. Select a camera from the picker — the live preview appears immediately.
  3. Set the capture interval (seconds between frames) and playback FPS.
  4. Click Start to begin recording. Frame counter and elapsed timer update live.
  5. Click Stop to finalize. The preview area swaps to a player showing the recorded clip.
  6. Click Save (⌘↩) to pick a destination via the save sheet, or Discard (⌘⌫) to throw it away. Either action returns to the live camera preview.

Architecture

  • WebcamTimelapseApp — SwiftUI App entry, single Window scene, owns AppState.
  • AppState — single source of truth: state enum (idle / requestingPermission / denied / recording / saving / reviewing(URL) / error), frame count, settings, last saved URL.
  • CameraDiscoveryAVCaptureDevice.DiscoverySession wrapper, publishes connected cameras.
  • CaptureSession — wraps AVCaptureSession + AVCaptureVideoDataOutput, exposes the latest CVPixelBuffer. Runs whenever a camera is selected.
  • FrameGrabberDispatchSourceTimer pulling the latest pixel buffer at the configured interval. Attached only while recording.
  • TimelapseEncoderAVAssetWriter + AVAssetWriterInputPixelBufferAdaptor, H.264 mp4.
  • ContentView / PreviewView / ClipReviewPlayer — SwiftUI shell, live AVCaptureVideoPreviewLayer, and AVPlayerView-based review player.

Design decisions

  • Sandbox is off — keeps save-anywhere behavior simple.
  • Frame grab uses AVCaptureVideoDataOutput (sampled latest pixel buffer), not AVCapturePhotoOutput — no shutter sound, no extra HW negotiation.
  • Capture session stays alive across recordings so the live preview never blinks out between takes.
  • After Stop, the temp mp4 lives in NSTemporaryDirectory until the user picks Save or Discard; both actions clean up after themselves.

About

Minimal native macOS app that records a webcam timelapse and saves it as an mp4

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages