Skip to content

illinigirl/FrameShuffle

Repository files navigation

FrameShuffle

Rotate your own art and photos on a Samsung Frame TV — point it at a folder, pick a shuffle interval, done. A small local web UI lets you browse your collection, filter by folder / tag / color, and push any image to the TV with a click.

No cloud, no account, no subscription. Everything runs on your own machine (a Raspberry Pi is perfect) and talks to the TV directly over your LAN.

The FrameShuffle web UI: shuffle controls, folder/color filters, and the gallery grid (sample art shown)

Why this exists: the Samsung art API got noticeably flakier on the 2024 ("Pontus M") Frame models — uploads that never confirm, deletes that silently no-op, WebSockets that hang for an hour. FrameShuffle bakes in the workarounds that took a long time to find. See Hard-won lessons at the bottom.


Features

  • Shuffle your art folder on a timer (default 30 min, change it live).
  • Choose your art — a web grid of thumbnails; click one to show it now.
  • Filter by folder, by free-form tags, or by auto-detected color theme.
  • Auto-converts HEIC / PNG / DNG to JPEG and resizes/letterboxes to the Frame's native 3840×2160.
  • Self-cleaning — deletes the previous image each rotation so the TV never fills up with uploads.
  • Robust — every TV operation runs under a watchdog; a hung or unreachable TV can't wedge the service.

Requirements

  • A Samsung Frame TV with the Art API (2021+ models; built/tested against a 2024 QN65LS03D).
  • Python 3.9+ on a machine on the same network (Raspberry Pi, NAS, old laptop, etc.).
  • A folder of images.

Install

git clone https://github.com/illinigirl/FrameShuffle.git
cd FrameShuffle
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txt

That's it — there's no config file to edit. You set your TV and art folder in the web UI on first run (next section).

Prefer a config file? For a headless/pre-seeded install, copy config.example.py to config.py and fill in the values. Anything you later change in the UI (saved to settings.json) takes precedence.

Art folder layout

Anything works. Subfolders automatically become filterable categories:

art/
├── Impressionism/      ← category "Impressionism"
│   ├── Monet - Water Lilies.jpg
│   └── ...
├── Family Photos/      ← category "Family Photos"
└── a-loose-image.jpg   ← category "root"

Filenames like Artist - Title (Year).jpg are parsed for nicer captions, but any filename is fine.

Using a NAS or external drive

Your art doesn't have to live on the FrameShuffle machine. Anything the OS mounts as a folder works — a NAS share or a USB/external drive. Mount it the normal way, then point the art folder at the mount point:

Source Art folder path
NAS on a Raspberry Pi /mnt/nas/Frame TV
NAS on a Mac /Volumes/Public/Frame TV
USB drive on a Pi /media/pi/MYDRIVE/art
External drive on a Mac /Volumes/MyDrive/art

You don't have to type it: in ⚙ Settings, click Browse… and navigate to the folder (it surfaces /Volumes, /media, and /mnt so mounted drives are easy to find). Letting the OS handle the mount means it manages the network login and reconnection — FrameShuffle just reads the folder.


First run

python3 shuffle.py

Then open the web UI:

http://<machine-ip>:8080

A setup banner will prompt you to open ⚙ Settings, where you:

  1. Scan for your TV (or type its IP) — the scanner finds Samsung TVs on your network and lists them; click yours to fill in the IP.
  2. Enter your art folder path (it'll confirm the folder exists).
  3. Set a rotation interval, then Save.

The first time FrameShuffle connects, the TV may show an "Allow / Deny" prompt for a device named Display — choose Allow (the TV remembers it). Now toggle Shuffle on and your art starts rotating.

Tip: the repo includes a sample-art/ folder — point the art folder there first to confirm uploads and rotation work, then switch to your real collection.


Using it

The web UI is the whole control panel:

  • Shuffle toggle — start/stop automatic rotation.
  • every N min — change the interval on the fly.
  • Next › — jump to the next image immediately.
  • Art mode / TV mode — put the TV into art mode or back to normal.
  • Filters — click folder / tag / color chips to preview a subset in the grid, then Set as shuffle filter to make the rotation use only those.
  • Click any thumbnail — show that exact image on the TV right now.

Command-line options:

python3 shuffle.py              # rotation loop + web UI (default)
python3 shuffle.py --no-web     # loop only
python3 shuffle.py --once       # show one image and exit
python3 shuffle.py --interval 20  # set interval to 20 min, then run

Optional: color-theme filtering

To enable the color chips, build a color index once (re-run anytime you add art — it's incremental):

python3 tools/generate_color_themes.py
python3 tools/generate_color_themes.py --stats   # see the counts

This writes art_colors.json next to your art. Tags work the same way via an art_tags.json file (a {"relative/path.jpg": ["tag1", "tag2"]} map) if you want to maintain one.


Running as a service (Linux)

A frameshuffle.service template is included for systemd (Raspberry Pi / home server). It auto-starts on boot and restarts on failure:

# edit the paths/user in frameshuffle.service first
sudo cp frameshuffle.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now frameshuffle
journalctl -u frameshuffle -f      # follow the logs

systemd is Linux-only. On macOS/Windows just run python3 shuffle.py (or wrap it with launchd / Task Scheduler).


How it fits together

File Role
frame_tv.py The Frame TV art-channel client — connect, upload, delete, select, art-mode. The hard part.
settings.py Source of truth for TV IP / art folder / interval (settings.json) + SSDP TV discovery.
art_library.py Scans your folder; folder/tag/color filtering; JPEG conversion.
shuffle.py The service: owns the TV connection, runs the rotation loop.
web.py The local web UI.
state.py Tiny request/status files shared between the loop and the UI.
tools/generate_color_themes.py Optional color index builder.

The shuffle loop is the only thing that talks to the TV. The web UI just writes small request files that the loop picks up — so there's never more than one connection to the (connection-sensitive) TV.


Hard-won lessons: the 2024 Frame TV

If you're building your own Frame automation, these are the firmware quirks that cost the most time. They're all handled in frame_tv.py.

  • Every upload creates a new content_id. There is no overwrite and no "change current image" — you upload a fresh copy each time, so you must delete the old one or the TV fills up. FrameShuffle deletes the previous image on every rotation and clears leftovers on startup.

  • delete_image_list is silently ignored if you pass a JSON string. The TV acknowledges both forms but only acts on a raw Python list:

    content_id_list=[{"content_id": cid}]   # works
    content_id_list=json.dumps([...])       # acknowledged, does nothing
  • Delete never sends a confirmation. Waiting for one hangs every time. Treat delete as fire-and-forget.

  • A quiet TV will block your socket forever. create_connection's timeout only covers the handshake; without an explicit sock.settimeout(...) on the live socket, a .send()/.recv() can hang for an hour. Every op here has a hard socket timeout, and uploads additionally run under a SIGALRM watchdog so the loop can always recover.

  • The art channel can wedge itself. Sustained select_image failures put the com.samsung.art-app channel into a d2d_service_message:error state where it rejects everything. The fix is to tear the connection down and reopen for the next attempt — not to retry inline (inline retries interact badly with the watchdog and cause the long hangs).

  • Don't open the art channel just to "listen." On the 2024 model, connecting to com.samsung.art-app can wake the TV out of an app (e.g. YouTube) into art mode. Only connect when you actually intend to change what's displayed. (FrameShuffle connects only to upload/select/delete.)


License

MIT — see LICENSE.

About

Rotate your own art & photos on a Samsung Frame TV — local web UI with shuffle, folder/color filtering, and battle-tested 2024-model quirk handling. No cloud, no account.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages