A Python utility that automatically uploads photos from your local directory (recursively) to Nixplay digital photo frames. The tool supports batch processing, image resizing, and text overlay with date and location information.
Caution
This script removes existing photos from the target playlist before uploading. Setting delete_my_uploads to true also clears the My uploads album at run start.
-
Prerequisites
- Python 3.8 or higher
- A Nixplay account
- Local directory containing photos to upload
- Chrome or Chromium for Selenium (if none is found on your system, the script can download Chrome for Testing into a cache directory)
-
Set Up Project Directory
- Create a new directory for the project
- Copy the following files into it:
nix-upload.pyrequirements.txtsample_config.json
- Make a copy of
sample_config.jsonand name itconfig.json:# Windows copy sample_config.json config.json # macOS/Linux cp sample_config.json config.json
-
Create a Virtual Environment and Install Dependencies
python3 -m venv .venv source .venv/bin/activate python -m pip install --upgrade pip pip install -r requirements.txt -
Configure the Application
- Edit
config.jsonwith your credentials and preferences - Required parameters:
username: Your Nixplay account emailpassword: Your Nixplay account passwordphotos_directory: Absolute or relative path to the root folder containing photos (searched recursively)
- Edit
-
Run
python nix-upload.py
You can also specify a custom configuration file using the
--config(or-c) option:python nix-upload.py --config my-custom-config.json
The script uses a config.json file for configuration. Here are all available parameters:
username: Your Nixplay account usernamepassword: Your Nixplay account passwordphotos_directory: Path to the directory containing your photos (no default; must be set inconfig.json)
base_url: Nixplay website URL (default: "https://app.nixplay.com")playlist_name: Name of the Nixplay playlist to upload to (default: "nix-upload")delete_my_uploads: Whether to delete your "My uploads" album when the run starts (default: true).sample_config.jsonsets this to false so new users avoid wiping that album by mistake.max_photos: Maximum number of photos to upload (default: 500)max_file_size_mb: Maximum file size for each photo in MB (default: 3)batch_size: Number of photos to upload in each batch (default: 100)image_width: Target width for resized images (default: 1280)image_height: Target height for resized images (default: 800)log_level: Logging level (default: "INFO")headless: Run browser in headless mode (default: true). IfDISPLAYis unset, headless is forced even when set to false.caption: Whether to add text overlay with date and location (default: true)reverse_geocode: Whencaptionis true and GPS is present, call OpenStreetMap Nominatim to resolve place names (default: true). Set to false to caption location as coordinates only and avoid network calls.cache_directory: Directory for the reverse-geocode CSV cache (default:"cache", expanded to an absolute path). Cache file:<cache_directory>/reverse_geocode.csvdate_format: Format for date display on photos (default: "%Y-%m-%d %H:%M")caption_position: Position of text overlay ("top" or "bottom", default: "bottom")font_size: Font size for text overlay in points (default: 50)font_path: Path to custom font file (default: null, uses system font)- Windows examples:
"C:/Windows/Fonts/arial.ttf""C:/Windows/Fonts/calibri.ttf""C:/Windows/Fonts/helvetica.ttf"
- macOS examples:
"/Library/Fonts/Arial.ttf""/Library/Fonts/Helvetica.ttc""/System/Library/Fonts/Helvetica.ttc"
- Linux examples:
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf""/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf"
- Windows examples:
debug_directory: Directory for storing log files and debug snapshots (default: "debug")
Common date format options for the date_format parameter:
"%b %Y"- Month and year (Jan 2024)"%B %Y"- Full month name and year (January 2024)"%b %d, %Y"- Month, day, and year (Jan 15, 2024)"%Y-%m"- Year and month (2024-01)"%m/%Y"- Month and year (01/2024)
{
"username": "USERNAME",
"password": "PASSWORD",
"photos_directory": "PATH/TO/ROOT/OF/YOUR/PHOTOS/DIR",
"base_url": "https://app.nixplay.com",
"playlist_name": "nix-upload",
"delete_my_uploads": false,
"max_photos": 500,
"max_file_size_mb": 3,
"batch_size": 100,
"image_width": 1280,
"image_height": 800,
"log_level": "INFO",
"headless": true,
"caption": true,
"reverse_geocode": true,
"cache_directory": "cache",
"caption_position": "bottom",
"date_format": "%b %Y",
"font_size": 50,
"font_path": "C:/Windows/Fonts/arial.ttf",
"debug_directory": "debug"
}- open a command shell in the "nix-upload" directory on your computer
- Run "python nix-upload.py"
- Optionally specify a custom config file: "python nix-upload.py --config my-config.json"
The script clears the target playlist before uploading (so previous photos in that playlist are removed). If delete_my_uploads is true, it also clears the separate My uploads album at the start of the run.
Caution
Setting delete_my_uploads to true deletes content in the My uploads album. Clearing the playlist happens regardless when the run proceeds to upload.
- I dont know why this warning shows, but it seems to be a benign message "Attempting to use a delegate that only supports static-sized tensors with a graph that has dynamic-sized tensors (tensor#-1 is a dynamic-sized tensor)."
- In your config.json file, set "max_photos" to not more than 1900, and "batch_size" to not more than 100, for best performance
Apache License 2.0
Use at your own Risk