The Samsung Frame: Best When Scripted
Jon Sully
3 Minutes
A quick rundown of how I setup my Samsung Frame to display photography much easier than usual
Important
Just a note at the outset: this entire premise relies 100% on the work that Nick Waterton put together in the free, open-source project (fork) samsung-tv-ws-api, a Python library that essentially wraps all the Frame endpoints up into easy, accessible Python methods.
Let me be frank with you; if you have the cash flow to purchase a Samsung Frame (a frivolously expensive and niche product) and use the code in this blog post or Nick’s library in general, please consider sending him $50 for his work. This would not be possible without his efforts and it’s in all of our best interests that Nick continues to support these kinds of neat projects.
Nick’s PayPal link for donations: https://paypal.me/NWaterton
Context
I’ll keep it short! I’m a hobby photographer. I take lots of pictures and, every now and then, one turns out pretty nice! I bought the Samsung Frame to display my photography on its beautiful matte screen with its real-to-life “art mode” feature.
Uploading your own images to the Samsung Frame via either the TV itself (USB import) or via the phone app is dreadful. Slow, painful, often failing, and a total disaster to do 10 times, much less 1300.
Uploading Images
Here’s the script I used to do the actual image uploading. It goes without saying that you’ll need Python installed on your machine and a virtual environment setup with the samsung-tv-ws-api dependency installed. If you don’t know what that means or how to set that up, ChatGPT can walk you through it!
Note
This script doesn’t do anything for resizing images or resolution or anything. I use Adobe Lightroom for all of my image management and have an export preset that sizes them correctly, so I already know that all of the images in my output directory are 3840 pixels on the long edge. You might need something else in your workflow. ChatGPT can help you add image resizing directly to this script, if you’d like. That’s something Python can definitely do.
Here’s the goods:
# SEE SOURCE FOR METHODS: https://github.com/NickWaterton/samsung-tv-ws-api/blob/9647fdb8556938b3369ac65f38f15108391c4267/samsungtvws/art.py import os import time from samsungtvws import SamsungTVWS IMAGE_DIRECTORY = "/Users/jon/Pictures/Lightroom Exports/Frame Exports" # MATTE TYPES (not all matte types work for all images) # 'none' 'modernthin' 'modern' 'modernwide' 'flexible' 'shadowbox' 'panoramic' 'triptych' 'mix' 'squares' # MATTE COLORS # 'black' 'neutral' 'antique' 'warm' 'polar' 'sand' 'seafoam' 'sage' 'burgandy' 'navy' 'apricot' 'byzantine' 'lavender' 'redorange' 'skyblue' 'turquoise' # (Jon) I tend to prefer 'warm' or 'apricot' def upload_image(image_path): try: # Connect to the TV tv = SamsungTVWS(host="192.168.1.100") art = tv.art() # Read the image with open(image_path, "rb") as f: image_data = f.read() print(f"Now Uploading {image_path}...") # Upload the image # Sending both `matte` and `portrait_matte` since the image may be landscape or portrait! response = art.upload( image_data, file_type="JPEG", matte="flexible_apricot", portrait_matte="flexible_apricot" ) print(f"Uploaded {image_path}: {response}") print(f"{time.ctime()}") except Exception as e: print(f"Error uploading {image_path}: {e}") def upload_images_in_directory(directory): # List all .jpg files and sort them alphabetically (so the list on the Frame is in the same order as the list on my machine) files = sorted( [filename for filename in os.listdir(directory) if filename.lower().endswith(".jpg")] ) # Loop through sorted filenames for filename in files: full_path = os.path.join(directory, filename) upload_image(full_path) # Sleep 2 seconds to let the Frame TV process the image; I found this helps a lot when uploading >25 in sequence time.sleep(2) # Call the function to upload all images upload_images_in_directory(IMAGE_DIRECTORY)
Hopefully all the comments there help make it clear what’s going on! You’ll need to replace the value of the IMAGE_DIRECTORY
variable as well as the hard-coded IP address, set to 192.168.1.100
in the example code.
I do have one other script that essentially just kicks the Frame into the preferred art settings I like:
# SEE SOURCE FOR METHODS: https://github.com/NickWaterton/samsung-tv-ws-api/blob/9647fdb8556938b3369ac65f38f15108391c4267/samsungtvws/art.py import os from samsungtvws import SamsungTVWS TV_IP = "192.168.1.100" tv = SamsungTVWS(host=TV_IP) art = tv.art() art.set_slideshow_status(15) # shuffle is default # This automatically kicks the TV into art mode if it's not currently
Which essentially just says “Go into Art mode, on a shuffle slideshow with 15 minute image-swap times”. It’s just a handy little utility script to run if I want to reset the Frame into the right setting for my living room and I’m already on my computer.
YMMV!
Comments? Thoughts?
John s
Hey Jon, thanks for writing this up. It’s super helpful. Can you confirm that the IP address we switch out is the IP of the frame tv? Thanks.
Jon Sully (Author)
Hey John! Yes, you’ll want to put in the IP address of the TV, but I can’t say what your particular IP address is. If you power on the TV, you should be able to find “IP Status” in the Wifi settings and that should tell you what IP address it’s using.
Ed
Awesome Jon! Thanks!
Adam C
Hi Jon, great writeup - I set up a similar system around the same time you did, leveraging Nick’s work and with a lot of back & forth with him. (I’m not a dev, am learning a lot through trial & error and ChatGPT, and yeah, I did send $$ his way!) My scripts have been running steadily for months now, and the system generally works. Once in a while though, the TV seems to exit Art Mode. It will either go to the Art Mode homepage (where you select the art you want to display) or sometimes I come to find it in a screensaver mode, which I think probably happens when it sits on a homepage too long. So since I only use my Frame as a picture frame, it occurred to me that maybe I could put something into the script that checks whether the TV is in art mode every time it updates the slideshow, and forces art mode if the TV happens to be in any other mode. Poking around in GPT, it is suggesting one way to do this, and it’s different from yours. Does simply having “art = tv.art()” change the TV to Art Mode? GPT is suggesting I try “tv.art().set_artmode(True)” and am curious what the difference is. Thanks!
Jon Sully (Author)
Hey Adam!
Happy to help 🙂
I can’t verify GPT’s suggestion but I can tell you that simply running tv.art()
does indeed kick the TV into Art mode. The only reason I save the returned value into that art
variable is because I do want to call a subsequent function (setting the slideshow timer). I could actually do that as a multi-chain function call, more similarly to what GPT suggested:
tv.art().set_slideshow_status(15)
But they’re equivalent.
Anyway, if you just add tv.art()
at the end of your script, that should cover you!
Adam C
Very exciting! I next time I can sit down and work on this, I will add that as a parameter that the user can specify whether to do this in the command line. If you’ve tested this from various pages (e.g. while playing live TV, while in screen saver, while on a settings page), let me know. Also, I would not want this to pull the TV out of the Art Mode Standby state. Do you know whether it would do that or whether I need to write a condition for that? Thanks!!