Rewind-Replay is (planned to be) a no frills, self-hosted photos app that helps in organizing and more importantly searching your photos.
Currently this project is very much a work-in-progress.
- We don't want to use cloud providers for personal photo collection.
- Some of us really care about our media in folders that we have meticulously curated from a long time. With any tool, we want the ability to continue to manage pics in folders.
- The single source of truth is the photo itself (*). Hence, we want all metadata, including user tags, ML based face / objects labels etc., to go back to the photo, to the extent possible.
- In the same vein, we also want the tool to utlize the metadata already existing in the photos (updated by device / other tools).
- In other words, we don't want to be locked-down by any one particular tool (including this one!).
- Some kind of sensible, not too constrained search is needed, even though it may (will) not be as good as Google.
(*) For those who are not aware, a photo/video taken by a modern camera/phone not only stores the image/video content, but also metadata about the photo/video. For e.g. GPS coordinates, dimensions, orientation, duration for videos etc. There are also provisions to update metadata when they are discovered. For e.g. recognized faces, address based on reverse geo-coding etc.
- Item: The individual media item (photo / video / audio)
- Album: A group of related media items. For e.g. "2021-10-01 Trip to SVBF"
- Collection: A set of related albums. For e.g. "My family pics", "My small-business pics" etc.
- Indexing: The process of reading media and cataloging metadata to help with search. Also thumbnail generation.
- Support for existing folders and files: Read existing folder structure (specificed during collection creation) and index the files found (if any) under respective collections
- Support for new files:
- Immediate indexing - Watch one or more 'listen' folders for new files, and as new files become available, bring them into the respective collection and index them
- Delayed indexing - Schedule a daily 'cron' to watch the setup 'intake' folders, to bring in files to the collection that are 'x' days stale
- Rename albums (similar to renaming folders on a File Explorer program)
- Select files and move them to a different album
- Select files and trash them
- Backup helper: A helper utility that incrementally backs-up all the files into the 'registered' backup drives. See Backup helper section for more information
- Index media photos, videos and audio
- Extract key exif data (metadata), and store in SQLite db
- Thumbnail generation
- Compress video files into smaller webm files
- Indexer has the ability to run and gather metadata for multiple files at the same time. See
updateIndexerConcurrencybelow
- Mark as favorite / stars (there is no favorite in exif, but there is a 'rating' field)
- Optimize write of metadata to files by delaying the write. This enables grouping all the changes together and writing to file at one go
- Lookup GPS location
- First using geolocation api (that comes with exiftool)
- For US based addresses, use findNearestAdderss API (need a registered username)
- Display photos and videos on a responsive, progressive, scrollable grid
- Cluster photos on a map
- Slideshow
- Search photos based on their metadata, using SQLite FTS5
- Github like search features (key value pairs)
e.g.
album:trip camera:samsung type:video - When multiple conditions are prsent, by default they are "AND"ed.
e.g.
album:trip camera:samsung type:videowill translate as{album}: "trip"* AND {camera}: "samsung"* AND {type}: "video"* - This can be overwritten using the "logical" or "l" input. E.g.
l:or - The input from "logical" keyword applies to all conditions
e.g.
album:trip camera:samsung type:video l:orwill translate as{album}: "trip"* OR {camera}: "samsung"* OR {type}: "video"* - Any un-prefixed condition will be applied to/restricted to all search-enabled columns
- For advanced needs (including querying non restricted columns - for e.g.
file_date), use the "raw" input using SQLite FTS syntax. Thich will be used as-is in the filter. e.g.raw:"metadata match '{album}: (states* AND trip*)'"raw:"strftime('%W',file_date)=strftime('%W',date()) and strftime('%Y',file_date) != strftime('%Y',date())"(all 'past' photos of current week)
- "raw" can be clubbled with other filters, if needed
- Github like search features (key value pairs)
e.g.
We take thousands of photos and videos — and rarely see them again.
Traditional digital frames help, but they’re limited by SD cards and manual updates. Content becomes static and quickly outdated.
This system turns any web browser into a centrally managed digital photo frame.
- No SD cards.
- No file copying.
- No device lock-in.
If a device can open a browser — TV, tablet, old laptop, Android TV box — it can become a live photo frame.
All that you do is register the "frame"
Specify the
- IP address
- A search crieteria (refer to 'search photos' in UI features)
- A reset schedule (crontab format) - to auto-refresh the playlist for the frame
- Dailay Pause range - to auto pause the frame during that time period
The frame is setup, and available at http://<server-ip>/frame.html
Traditional frames are static and manual. This is dynamic, automated, and server-controlled.
Your memories don’t sit in storage — they stay alive.
A true "rewind-replay" feature!
This module helps take backup of the collections to external drives.
When the folders are renamed, backup utilities like rsync see them as file-deletions and file-additions. That's a waste of resources especially on large video files. A simple thing could be to just perform mv operation on the target backups as well.
That's exactly what this setup aims to help with.
- Register backup device(s) (with UUID of the device)
- All file opertions on a collection are noted in a table
- When it is time to backup to a specific device, all 'delta' operations are determined and applied to the set of files eligible for backup.
- The 'last_backup_id' is noted for each backup.
TODO - sync timestamps on +2 level folders
Near future
- Add/change "tags" (keywords)
- Display more info (filename, description, camera, date/time, people, location) on the file being viewed
- Ability to rename files
After near future
- Face recognition
- An acutal form to setup collections
- Form to update config and save it to persistant storage (file?)
- Monitor indexer progress
- Enable multiple collections
- Ability to upload photos from device
- Intelligent scrollbar (folder levels?)
- Object detection (computer vision)
- Authentication and Authorization
- Sharing photos/albums
-
Install necessary software
-
Install code (just clone this repo)
git clone https://github.com/mrbrahman/rewind-replay.git
Or, grab the latest release from the Releases page
-
Install node dependencies
cd rewind-replay/server npm install -
Special instructions for HEIC support (TBD for Linux)
For heic support, need to do some extra stuff at the moment. See lovell/sharp#4164 for more details
# https://sharp.pixelplumbing.com/api-output#heif brew install vips libheif libde265 x265 # https://sharp.pixelplumbing.com/install#building-from-source npm install --build-from-source node-addon-api node-gyp sharp
-
Start server
cd rewind-replay/server node server.mjs -
Setup Collection & Start Indexing
Until the UI is available to create collections and auto-start indexing, use REST API.
Example for creating collection with real-time watcher
cat > c.json <<EOF { "collection_name":"Test", "collection_path":"/home/mrbrahman/Projects/test-collection/", "album_type":"FOLDER_ALBUM", "intake_configs":[ { "path":"/home/mrbrahman/Projects/test-collection-new-files/", "method":"immediate", "config":{ "awaitWriteFinish":true, "ignoreInitial":true } } ], "apply_folder_pattern":"yyyy/yyyy-mm-dd", "default_collection":1 } EOF
Example for creating collection with scheduled cron indexing
cat > c.json <<EOF { "collection_name":"Test", "collection_path":"/home/mrbrahman/Projects/test-collection/", "album_type":"FOLDER_ALBUM", "intake_configs":[ { "path":"/home/mrbrahman/Projects/bulk-import/", "method":"scheduled", "config":{ "schedule":"0 2 * * *", "staleDays":2 } } ], "apply_folder_pattern":"yyyy/yyyy-mm-dd", "default_collection":1 } EOF
Example for creating collection with mixed watcher and cron paths
cat > c.json <<EOF { "collection_name":"Test", "collection_path":"/home/mrbrahman/Projects/test-collection/", "album_type":"FOLDER_ALBUM", "intake_configs":[ { "path":"/home/mrbrahman/Projects/camera-import/", "method":"immediate", "config":{ "awaitWriteFinish":true } }, { "path":"/network/shared-photos/", "method":"scheduled", "config":{ "schedule":"0 1 * * *", "staleDays":1 } } ], "apply_folder_pattern":"yyyy/yyyy-mm-dd", "default_collection":1 } EOF
curl -X POST -H 'Content-Type: application/json' -d @c.json "http://localhost:9000/api/createNewCollection" # Verify curl -X GET 'http://localhost:9000/api/getAllCollections' | jq '.'
Start indexing (this will kick off indexer process in the background and return immediately)
curl -X POST 'http://localhost:9000/api/startIndexingFirstTime?collection_id=1'Monitor progress
curl -X GET 'http://localhost:9000/api/getIndexerStatus' | jq '.'
# If you notice your system resources are not fully utilized, you can increase indexer concurrency # Suggest to increase by 1 at a time, until you see resources getting fully utilized $ curl -X PUT 'http://localhost:9000/api/updateIndexerConcurrency/2'
-
Visit your rewind-replay page http://localhost:9000
-
As indexing progresses, you should see photos appear
-
Enjoy!
- nodejs server
- SQLite 3 database
- Sqlite3 provided FTS5 for searches
- sharp for image operations
- exiftool-vendored for metadata read / write
- Use browser native features (HTML5) to play videos

