Frameo Miniatures
A fast, efficient CLI tool to prepare and optimize photo collections for Frameo digital photo frames.
Overview
Frameo Miniatures resizes, compresses, and organizes your photos to fit perfectly on Frameo digital frames. Modern cameras produce huge files that are inefficient for photo frames with limited resolution and storage. This tool:
- Resizes images to fit your frame's resolution while preserving aspect ratio
- Converts to space-efficient WebP format (or JPEG)
- Preserves EXIF metadata (capture dates, orientation)
- Auto-rotates images based on EXIF orientation data
- Mirrors your directory structure
- Handles FAT32 filename constraints
- Processes files in parallel for maximum speed
Features
- ✅ Supports JPG, JPEG, and HEIC formats
- ✅ Streaming file discovery (starts processing immediately)
- ✅ Configurable ignore patterns (
.frameoignore)
- ✅ Progress bar with ETA
- ✅ Dry-run mode for testing
- ✅ Pruning of outdated files
- ✅ Skip existing files for fast incremental updates
- ✅ Multi-core processing
Installation
From Source
git clone https://github.com/tgagor/frameo-miniatures.git
cd frameo-miniatures
make build
sudo make install
Using Go
go install github.com/tgagor/frameo-miniatures@latest
Quick Start
Basic usage:
frameo-miniatures -i ~/Photos -o miniatures
This will:
- Scan
~/Photos for images
- Resize them to fit 1280x800 (default)
- Convert to WebP format
- Save to
miniatures preserving directory structure
Usage
frameo-miniatures [flags]
Flags
| Flag |
Short |
Default |
Description |
--input |
-i |
. |
Source directory path |
--output |
-o |
./output |
Destination directory path |
--resolution |
-r |
1280x800 |
Target frame resolution (bounding box) |
--format |
-f |
webp |
Output format (webp, jpg) |
--quality |
-q |
80 |
Compression quality (0-100) |
--workers |
-j |
0 |
Number of concurrent workers (0 = auto) |
--ignore-file |
|
|
Path to custom .frameoignore file |
--prune |
|
false |
Remove orphaned files from output (no source or ignored) |
--skip-existing |
|
false |
Skip processing if output file already exists |
--dry-run |
|
false |
Simulate without writing files |
--version |
|
|
Show version information |
Examples
Process photos for a 1920x1080 frame:
frameo-miniatures -i ~/Photos -o miniatures -r 1920x1080
Use JPEG instead of WebP:
frameo-miniatures -i ~/Photos -o miniatures -f jpg -q 85
Dry run to see what would happen:
frameo-miniatures -i ~/Photos -o miniatures --dry-run
Prune orphaned files from output:
frameo-miniatures -i ~/Photos -o miniatures --prune
This removes miniatures that no longer have corresponding source files or match ignore patterns.
Use custom ignore file:
frameo-miniatures -i ~/Photos -o miniatures --ignore-file .my-ignore-rules
Skip existing files (incremental update):
frameo-miniatures -i ~/Photos -o miniatures --skip-existing
Incremental update with cleanup:
frameo-miniatures -i ~/Photos -o miniatures --skip-existing --prune
This efficiently updates only new/changed files and removes orphaned miniatures.
Ignore Patterns
You can exclude files and directories using a .frameoignore file. The syntax is similar to .gitignore.
Search Order
The tool looks for .frameoignore in the following order (unless --ignore-file is specified):
--ignore-file path (if provided)
~/.config/frameoignore
- Input directory
- Current directory
Example .frameoignore
# Ignore all files in specific directories
*/2005.07/One party/*
2002.03/A trip/*
# Ignore by pattern
*.tmp
*.bak
*_draft*
# Ignore specific directories
temp/
mobile/
Pattern Syntax
* matches any characters except /
** matches any characters including /
! negates a pattern
- Lines starting with
# are comments
How It Works
- Discovery: Walks the input directory recursively, finding valid image files
- Filtering: Applies
.frameoignore rules to skip unwanted files
- Processing: For each image:
- Decodes the image (JPG/HEIC)
- Reads EXIF metadata
- Auto-rotates based on EXIF orientation
- Resizes to fit within target resolution (preserving aspect ratio)
- Normalizes filename for FAT32 compatibility
- Encodes to WebP (or JPEG)
- Preserves capture date/time
- Pruning (optional): Removes orphaned miniatures from output directory
- Deletes files with no corresponding source
- Removes files matching ignore patterns
The tool uses a producer-consumer pattern with parallel processing:
- Producer: Walks directories and streams files to a queue
- Consumers: Multiple workers process images concurrently
- Default: Uses all CPU cores for maximum speed
On a typical system, you can expect:
- ~10-50 images/second (depending on size and format)
- Immediate start (streaming discovery)
- Linear scaling with CPU cores
Technical Details
Input:
- JPEG (
.jpg, .jpeg)
- HEIC (
.heic)
Output:
- WebP (default, best compression)
- JPEG
Image Processing
- Resizing: Catmull-Rom resampling for high quality
- Aspect Ratio: Always preserved
- Orientation: Auto-corrected from EXIF
- Metadata: EXIF dates copied to output files
File System
- Filename Normalization: Removes invalid FAT32 characters (
\ / : * ? " < > |)
- Directory Structure: Mirrored from input to output
- Extension: Changed to match output format (e.g.,
.jpg → .webp)
Troubleshooting
Files not being ignored
Make sure your .frameoignore patterns are correct:
- Use
*/dirname/* for directories with a parent
- Use
dirname/* for top-level directories
- Check the log output to see which ignore file was loaded
HEIC support issues
HEIC decoding requires CGO and libheif. If you encounter issues:
- Ensure libheif is installed on your system
- Build with CGO enabled:
CGO_ENABLED=1 go build
- Reduce
--workers if system is overloaded
- Use
--dry-run to test without writing files
- Check disk I/O (especially on network drives)
License
GPLv3