Skip to content

About

Align daily portrait photos on facial landmarks (MediaPipe) and render a centered face timelapse video

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Note

Hi :)

I've been taking a photo of myself every day since 2024, but I found it very tedious to manually clip all the photos into a timelapse video, so I wrote some code to automate that back then. Since I have not really found anything better, I decided to share it here. Hope it helps!

If you have any questions or feedback, feel free to open an issue or reach out.

Face Timelapse Generator

Turn a folder of daily portrait photos into a smooth timelapse video where your face stays perfectly centered and level. Faces are detected and aligned with Google's MediaPipe Face Landmarker, so the eyes sit at a fixed position in every frame regardless of head tilt, distance, or framing.

Note: This repository contains only the code. It ships with no photos — you supply your own (see Usage below).

How it works

  1. Rename by date — reads each photo's EXIF capture timestamp and renames it to YYYY-MM-DD_HH-MM-SS.jpg so frames are processed in chronological order.
  2. Align faces — FaceAligner finds the eye landmarks and rotates, scales, and crops each image so the eyes land on a fixed coordinate in a 1080×1920 frame.
  3. Build the video — compiles the aligned frames into a 20 fps MP4 with OpenCV. Already-processed frames are cached, so re-runs are fast.
  4. Add music (optional) — pass --music to mix in an audio track; see Adding music below.

Project layout

Programm/                 ← this repository
├── main.py               orchestrator: rename → align → render → (optional) mix music
├── face_aligner.py       FaceAligner (MediaPipe eye-landmark alignment)
├── audio_mixer.py        optional music muxing (moviepy), used with --music
├── face_landmarker.task  pre-trained MediaPipe model (bundled)
├── requirements.txt
├── run.sh                convenience wrapper (venv + cleanup + run)
└── CLAUDE.md             notes for the Claude Code agent

<parent folder>/          ← your data lives here, one level up (git-ignored)
├── original_Photos/      put your raw photos here
├── centered_Photos/      aligned frames (generated)
└── final_video/          output MP4 (generated)

main.py derives all paths from its own location — the data folders are expected in the parent of Programm/. Nothing is hardcoded, so you can place the Programm/ folder wherever you like.

Setup

Requires Python 3.12 (MediaPipe/OpenCV wheels are not yet available for 3.13+).

git clone <your-repo-url>
cd <repo>            # the cloned "Programm" folder
python3.12 -m venv venv
./venv/bin/python -m pip install -r requirements.txt

Usage

  1. Create an original_Photos/ folder in the parent directory of this repo and drop your daily photos in it (.jpg, .jpeg, or .png).

  2. Run the pipeline:

    ./run.sh
    # or: source venv/bin/activate && python main.py
  3. Find the result at ../final_video/timelapse_centered_v1.mp4.

Photos without a detectable face are skipped with a warning. Re-running only processes new photos.

Adding music

Music is opt-in — pass --music with a path to an audio file and it gets mixed into the final video. Omit it and the output is silent, exactly as before.

./run.sh --music ../music/track.mp3
./run.sh --music ../music/track.mp3 --music-mode trim
./run.sh --music ../music/track.mp3 --music-mode match-length
./run.sh --music ../music/track.mp3 --fade 3
  • --music-mode loop (default) — loops the track to fill the whole video, fading out over the last --fade seconds (default 2s).
  • --music-mode trim — plays the track once and cuts it (with a fade-out) at the end of the video; if the track is shorter than the video, the rest plays silent.
  • --music-mode match-length — instead of adjusting the audio, the video's frame rate is chosen so its duration matches the track exactly.

Music is muxed in with moviepy, which re-encodes the output as H.264/AAC — this also makes the file more broadly compatible than the raw mp4v output from the silent path. The first time you use --music, moviepy may download a small static ffmpeg binary; no manual setup needed.

Dependencies

Declared in requirements.txt:

  • mediapipe — facial-landmark detection
  • opencv-python (cv2) — image transforms and video encoding
  • numpy — alignment math
  • ExifRead — reads capture dates from photo EXIF
  • Pillow, moviepy — pulled in as transitive/optional deps

License

MIT

About

Align daily portrait photos on facial landmarks (MediaPipe) and render a centered face timelapse video

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages