A Python client for managing art mode on Samsung Frame TVs. Upload images, configure display settings, and control slideshow playback remotely.
- Batch Upload with HEIC Conversion: Convert iPhone/iOS HEIC images to 4K JPG and upload
- Recursive Directory Scanning: Process images from nested subdirectories
- Smart Filtering: Exclude thumbnails and small files automatically
- Filename Trimming: Automatically trims filenames to <50 chars (preserves extension, handles collisions)
- Start Index / Pagination: Skip first N files with
--start-indexfor resuming interrupted uploads - Smart Purge: Delete stale art (uploaded >24h ago or untracked) while respecting minimum image count
- Connection Health Checks: Automatically stops uploads after consecutive failures to avoid wasting time on unstable connections
- Upload History Tracking: Local JSON tracker records upload timestamps for time-based purge decisions
- Matte Configuration: Apply black borders (or other matte styles) to uploaded images
- Art Mode Control: Enable art mode and start automatic slideshow
- TV Status: Check connection and art mode support
- Art Inventory: List all available art on TV
- Pushover Notifications: Get notified of upload results and errors
- Token-based Authentication: Secure WebSocket connection with persistent token storage
Add your Samsung Frame TV settings to config/local.yaml:
samsung_frame:
ip: "192.168.XX.YY" # Your TV's IP address
port: 8002 # WebSocket port (default: 8002)
token_file: lib/tokens/samsung_frame_token.txt
default_matte: shadowbox # Black border style
supported_formats: [jpg, jpeg, png]
max_image_size_mb: 10
# Add to pushover tokens for notifications
pushover:
tokens:
SamsungFrame: your-pushover-tokenInstall dependencies from the project root:
uv syncOn first run, any command that connects to the TV will display a pairing prompt:
# Option 1: Use status command to pair without uploading
uv run python SamsungFrame/manage_samsung.py status
# Option 2: Pair during first upload
uv run python SamsungFrame/batch_upload.py /path/to/imagesPairing Steps:
- Run any command that connects to TV (status, batch upload, list-art, etc.)
- Check your TV screen for the pairing prompt
- Accept the connection on your TV
- The authentication token will be automatically saved to
config samsung_frame.token_file - Subsequent operations will use the saved token without requiring TV approval
To re-pair: Delete the token file and run any connection command:
rm lib/tokens/samsung_frame_token.txt
uv run python SamsungFrame/manage_samsung.py statusAll commands should be run from the project root directory.
For iPhone/iOS users with HEIC photos, use the batch upload script which handles conversion automatically:
# Basic batch upload with HEIC conversion
uv run python SamsungFrame/batch_upload.py ~/Photos/Favorites
# Purge stale art (>24h old or untracked) after upload
uv run python SamsungFrame/batch_upload.py ~/Photos/Vacation --purge
# Custom matte
uv run python SamsungFrame/batch_upload.py ~/Photos --matte shadowbox_black
# Skip first 20 files (resume interrupted upload)
uv run python SamsungFrame/batch_upload.py ~/Photos --start-index 20
# Upload at most 50 files starting from index 10
uv run python SamsungFrame/batch_upload.py ~/Photos --start-index 10 --max-files 50What the batch upload script does:
- Recursive Discovery: Scans directory and all subdirectories for images
- Smart Filtering: Excludes files <1MB (configurable) and thumbnail patterns (_thumb, _thumbnail, _small)
- Start Index / Max Files: Optionally skip first N files and/or cap total uploads
- Phase 1 — Prepare: Converts HEIC to high-quality JPG at 4K (max 3840×2160), copies JPG/PNG, trims all filenames to <50 chars
- Quality Compression: Reduces JPG quality (95→90→85→80→75→70) if needed to meet 10MB TV limit
- Phase 2 — Upload: Uploads all prepared images with health checking (stops after 3 consecutive failures)
- Upload Tracking: Records upload timestamps locally for time-based purge
- Smart Purge: Optionally deletes art uploaded >24h ago or untracked (respects minimum image count)
- Enable Art Mode: Automatically enables slideshow after upload
Command Options:
source_dir- Directory to scan (required)--matte- Matte style (default: shadowbox_black)--purge- Delete stale art (>24h old or untracked) after upload--start-index N- Skip first N discovered files (applied before --max-files)--max-files N- Maximum number of files to upload (0 = all)
Note: Pushover notifications sent automatically. Files <1MB filtered as thumbnails.
Supported Formats: HEIC, JPG, JPEG, PNG
Check TV connection and display comprehensive information:
uv run python SamsungFrame/manage_samsung.py statusExample output:
Connecting to Samsung Frame TV at 192.168.x.x...
==================================================
TV STATUS
==================================================
Model: QN55LS03FADXZA
Name: 55" The Frame
Firmware: Unknown
Resolution: 3840x2160
Power State: on
OS: Tizen
Network Type: wireless
Frame TV Support: true
Available Art: 42 items
Art Mode: Supported and working
Note: Status command uses REST API only, so it won't trigger the pairing prompt. Run an upload command first to establish authentication.
List all art currently on the TV:
uv run python SamsungFrame/manage_samsung.py list-artSee what matte (border) styles your TV supports:
uv run python SamsungFrame/manage_samsung.py list-mattesCommon options include: shadowbox, none, modern, flexible, panoramic
Download thumbnail images for your uploaded photos:
# Download only user-uploaded photos
uv run python SamsungFrame/manage_samsung.py download-thumbnails ~/Downloads/samsung_thumbnails
# Download all art (including Samsung's pre-installed art)
uv run python SamsungFrame/manage_samsung.py download-thumbnails ~/Downloads/samsung_thumbnails --allChange the matte (border) style for all art already on the TV:
# Update all art to default black border
uv run python SamsungFrame/manage_samsung.py update-mattes
# Update with base style only
uv run python SamsungFrame/manage_samsung.py update-mattes --matte shadowbox
# Update with style and color (e.g., shadowbox with black color)
uv run python SamsungFrame/manage_samsung.py update-mattes --matte shadowbox_black
uv run python SamsungFrame/manage_samsung.py update-mattes --matte modern_warm
uv run python SamsungFrame/manage_samsung.py update-mattes --matte flexible_polarMatte Format: <base_style> or <base_style>_<color>
Valid colors: seafoam, black, neutral, antique, warm, polar, sand, sage, burgandy, navy, apricot, byzantine, lavender, redorange, skyblue, turqoise
This command:
- Retrieves all art currently on the TV
- Validates matte style and optional color
- Updates each art item to use the specified matte style
- Reports success/failure/skipped counts
Enable the TV's automatic slideshow feature (recommended for normal use):
# Start slideshow with default settings (15 min interval, shuffle on)
uv run python SamsungFrame/manage_samsung.py start-slideshow
# Custom interval (30 minutes between images)
uv run python SamsungFrame/manage_samsung.py start-slideshow --duration 30
# Sequential mode (no shuffle)
uv run python SamsungFrame/manage_samsung.py start-slideshow --no-shuffleThis command:
- Enables art mode on the TV
- Starts the TV's built-in slideshow for user-uploaded photos
- Configures the interval between image changes (in minutes)
- Optionally enables shuffle or sequential mode
- Returns after starting the slideshow (TV continues cycling independently)
Note: This uses the TV's native slideshow feature, which continues running even after the command exits. The TV will cycle through images automatically based on the configured interval.
Manually cycle through your photos with a specified period (useful for testing or presentations):
# Cycle through user photos every 15 seconds (default)
uv run python SamsungFrame/manage_samsung.py cycle-images
# Custom period (30 seconds)
uv run python SamsungFrame/manage_samsung.py cycle-images --period 30
# Cycle through all art (including Samsung's pre-installed art)
uv run python SamsungFrame/manage_samsung.py cycle-images --all --period 10This command:
- Enables art mode on the TV
- Retrieves all available art (or only user-uploaded photos)
- Cycles through each image with the specified period
- Continues indefinitely until you press Ctrl+C
- Logs each image change for monitoring
Note: This is different from the TV's built-in slideshow. The cycle-images command gives you precise control over timing (in seconds) and which images to display, but requires the script to keep running.
-
samsung_client.py: Core client class (SamsungFrameClient)- Connection management with retry logic
- Image validation and upload with health checking (consecutive failure detection)
- Art mode control
- Slideshow management
-
batch_upload.py: Batch upload with two-phase architecture- Phase 1: Prepare images (HEIC conversion, filename trimming, copy to temp dir)
- Phase 2: Upload via
upload_images_from_folder()with automatic health checks - Smart purge using local upload history tracking
-
upload_tracker.py: Local upload history (JSON-based)- Records content_id → timestamp for each upload
- Identifies stale art (>24h or untracked) for purge
- Stored at
config/samsung_upload_history.json(gitignored)
-
manage_samsung.py: CLI entry point- Argparse-based command interface for TV management
- Pushover notification integration
-
test_batch_upload.py: Comprehensive test suite- Tests for discovery, conversion, deletion, filename trimming, upload tracking, start-index
UploadResult: Single image upload result with success/error detailsImageUploadSummary: Batch upload summary with counts and error list
samsungtvws: Samsung TV WebSocket API library (using NickWaterton fork v3.0.5+ for improved upload reliability)Pillow: Image validation and processingpydantic: Data validation and modeling
Note: This project uses the NickWaterton fork of samsungtvws which includes critical fixes for image uploads, particularly for TVs with support_myshelf: FALSE. The official pypi package (v2.7.2) has known issues with large file uploads.
Use the list-mattes command to see what your TV supports. Common options:
shadowbox- Black border (default)none- No bordermodern,modernthin,modernwide- Modern border stylesflexible- Flexible borderpanoramic- Panoramic layouttriptych- Three-panel layoutmix- Mixed layoutsquares- Square grid layout
Run uv run python SamsungFrame/manage_samsung.py list-mattes to see your TV's exact options.
Symptoms: Failed to connect to TV at 192.168.x.x
Solutions:
- Verify TV is powered on (not fully off)
- Check TV is on same network as computer running script
- Verify IP address in
config/local.yaml(samsung_frame.ip) is correct - Check firewall isn't blocking port 8002
Symptoms: Connection works but commands fail with auth errors
Solutions:
- Delete token file:
rm lib/tokens/samsung_frame_token.txt - Run status command again and accept pairing prompt on TV
- Ensure token file has correct permissions (600)
Symptoms: Some or all images fail to upload
Common causes:
- Unsupported format: Only JPG and PNG supported
- File too large: Images must be < 10MB
- Corrupted file: File cannot be opened by PIL
- Network timeout: TV connection unstable
Check logs for specific error messages about failed images.
Symptoms: Art mode: Not supported or unavailable
Solutions:
- Verify you have a Samsung Frame TV (or other model with art mode)
- Ensure TV firmware is up to date
- Try restarting the TV
If you see permission errors, ensure token file has restrictive permissions:
chmod 600 lib/tokens/samsung_frame_token.txt# Run all SamsungFrame tests
uv run python -m pytest SamsungFrame/ -v
# Run specific test
uv run python -m pytest SamsungFrame/test_samsung_client.py::TestSamsungFrameClient::test_upload_image_success -v# Run all linters
make lint
# Auto-fix issues
make lint-fixBefore upload, each image is validated:
- File exists and is readable
- Extension matches supported formats
- File size is within limits
- PIL can successfully open and verify the image
Invalid images are skipped with logged errors.
Connection attempts use exponential backoff:
- Max 3 attempts
- Initial retry delay: 2 seconds
- Delay doubles on each retry (2s, 4s)
- Token file stored in
~/logs/with 600 permissions (owner read/write only) - Token automatically saved on first successful pairing
- No credentials stored in code or logs
The slideshow uses the TV's configured rotation interval (fastest available). The interval cannot be customized via the API - adjust it directly on the TV's art mode settings.
Cross-reference with ~/bin/_claude/shared-memory/skills/samsung.md for full protocol notes.
| Date | TV Model | Firmware | Images | Success | Runtime | Notes |
|---|---|---|---|---|---|---|
| 2026-04-23 | QN55LS03FADXZA (55" Frame) | unknown | 474 | 472 (99.6%) | 1h 38m | 2 WebSocket timeout failures; Art API toggled ×2; ms.channel.timeOut retry bug fixed same day |
Observed failure modes (all auto-recovered except where noted):
ms.channel.timeOuton initial connect → retry with backoff (requires fix inconnect())- Mid-upload WebSocket timeout → 10s cooldown, skip image, continue (image lost)
- Art API unresponsive mid-run →
KEY_POWERtoggle, reconnect, resume (no image loss) ms.channel.clientDisconnectresponse → treated as failure, next image normal
- NickWaterton samsung-tv-ws-api fork (v3.0.5+ used by this project)
- Original samsung-tv-ws-api (official upstream)
- Samsung Frame TV User Manual
- Pushover API Documentation