No description
- TypeScript 64.3%
- JavaScript 16.6%
- CSS 9.6%
- Twig 9.3%
- Dockerfile 0.2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| docs | ||
| invoice-templates | ||
| packages | ||
| server | ||
| src | ||
| .dockerignore | ||
| .gitignore | ||
| 20260611-kimai-export(1).csv | ||
| compose.yaml | ||
| Dockerfile | ||
| index.html | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.app.json | ||
| tsconfig.json | ||
| tsconfig.node.json | ||
| vite.config.ts | ||
dappyBirthday
A small web app and local server for building custom happy birthday videos from family song clips.
What it does
- Keeps uploaded source videos on the server and indexes reusable song-line ranges in a local SQLite database.
- Converts selected source videos into very small 480px trim proxies, so large phone videos are easier to trim in the browser.
- Saves tiny fixed-format preview snippets for each song-line range and stitches them into cached temporary composer preview videos.
- Extracts selected song-line ranges on demand at a reasonable 1280px maximum long edge for final export.
- Sends every new source video through a dedicated Upload Video page before opening the editor to mark start/end points, preview marked sections, and save the line metadata against that source video.
- Imports birthday videos directly from an Immich album through a dedicated Immich page, with server-side API-key storage, thumbnail previews, playback, imported Immich metadata, Imported status, and
DO NOT IMPORTmarkers. - Opens source-video trimming and saved-clip editing in the main Clips workspace instead of a side inspect drawer.
- Stores one common metadata and singer set for all lines marked from the same source video.
- Stores per-line tags, such as
funny,extra info, orstuff up, so characterful takes are visible while composing. - Shows synchronized full-width timelines with a shared playhead, colored song-line highlights, and per-line start/end handles.
- Tags clips by language, song line, structured singer objects, and per-section metadata.
- Saves metadata on individual clip sections: occasion, recorded date, location, tags, and notes.
- Supports English, French, and Bislama birthday-song clip libraries.
- Uses numbered song-line ranges:
Happy birthday to you (1),Happy birthday to you (2),Happy birthday,Dear <name>,Happy birthday to you (3), andHip hip hooray (n). - Supports one
Dear <name>line and repeatedHip hip hooraytakes, numbered 1, 2, 3, 4, and so on. - Randomly generates a full birthday song sequence from the selected language or lets you pick each part manually.
- Plays an in-browser preview.
- Exports a stitched
.webmvideo at landscape or portrait resolutions. - Saves reusable video configurations in local history.
Run with Docker
docker compose up --build
The app is served at:
- Web app and API:
http://localhost:3001 - Coder workspace URL:
https://3001--dev--food-safety-training--leighvandermerwe.coder.codex.fortescue.com/
Video and line metadata is stored in the Docker volume dappybirthday-data:
- SQLite database:
/data/snippets.sqlite - Source videos:
/data/source-videos/originals/ - Browser trim proxies:
/data/source-videos/proxies/ - Immich connection settings and per-asset import state:
/data/snippets.sqlite - Tiny composer preview snippets:
/data/preview-snippets/ - Cached stitched composer previews:
/data/tmp/previews/ - Temporary extracted preview/export segments:
/data/tmp/ - Legacy saved snippet files, if any:
/data/snippets/
Local development
npm install
npm run dev:all
This starts:
- API server:
http://localhost:3001 - Web app:
http://localhost:5174or the next available Vite port
Video and line metadata is stored locally under data/:
- SQLite database:
data/snippets.sqlite - Source videos:
data/source-videos/originals/ - Browser trim proxies:
data/source-videos/proxies/ - Immich connection settings and per-asset import state:
data/snippets.sqlite - Tiny composer preview snippets:
data/preview-snippets/ - Cached stitched composer previews:
data/tmp/previews/ - Temporary extracted preview/export segments:
data/tmp/ - Legacy saved snippet files, if any:
data/snippets/
The app uploads source videos only to the local server you run for this project. Song-line clips are saved as source-video time ranges, then extracted and stitched when you preview or export a birthday video.
Design documents
Shared packages
packages/person-selectoris the reusable React person selector package used by dappyBirthday.- It is wired as the workspace package
@dappybirthday/person-selector. - dappyBirthday adapts its local
Singerobjects into the packagePersontype insrc/App.tsx, while the package stays independent from Immich, CardDAV, and app storage APIs. packages/immich-adapteris the reusable Immich API adapter package for people, albums, assets, media fetches, and search.- It is wired as the workspace package
@dappybirthday/immich-adapter.