A Chromecast Slideshow using Python

I bought a Google Chromecast device a few days ago. I like the “screen saver” function that’s built in when the device isn’t in use. It pulls photographic images from someplace ( presumably from a Chromecast web page ) and displays them in succession.

I thought it would be nice to be able to arrange my own slideshow using Chrome on my Windows computer. When one installs the “Cast” extension to Chrome, any tab in the browser can be transmitted to the Chromecast device for viewing on the television. Although I implemented it on Windows, the code is intended to be reusable on OS/X, Linux, or other OS’s that support Casting the contents of a browser tab.

I would need that tab to utilize a web page that would display a set of images in rotation. I wanted to create a script that would read a directory of images and would then generate an HTML file with some embedded JavaScript to cycle through those images. The script would then function as a web-server, facilitating the requests for images at regular intervals.

All of the mail source files and referenced image files below can be found in the following archive:

http://www.mailsend-online.com/castpy.zip

Here’s the Github repository for the code:

https://github.com/jimlawless/castpy

I wrote the script in Python 2.7. I knew that it would be relatively straightforward to implement the HTML-formatting portion of the script in Python and the built-in web-server would lend itself to serving up the content.

Let’s first take a look at the HTML template file named “template.htm” :

<html><head><title></title></head>

<style type="text/css">
img {
 display: block; 
 margin-left: 
 auto; margin-right: 
 auto; max-width: 100%; 
 max-height: 100%; 
}
</style>

<body onload="nextOne(); setInterval('nextOne();',$$1);">

<script type="text/javascript">
 var imgList=[ 
 $$2
 ];
 var ctr=0;
 function nextOne() {
 ctr++;
 ctr%=imgList.length;
 document.getElementById("theImg").src=
 imgList[ctr];
 }

</script>

<img id="theImg">

</body></html>

Please note the pseudo-variables $$1 and $$2 in the above source. Those identifiers will be replaced with other content by the Python script. $$1 will be replaced with the desired time delay in milliseconds. $$2 will be replaced with a JavaScript array containing string-literals that specify the names of each image file.

When the above script loads, it will set the lone IMG tag’s SRC property to the name of the first image in the list. After the specified delay, the SRC attribute will change to the next image name in the list. When all images are exhausted, the process begins at the start of the list.

Image files must be placed in a directory named “img” immediately underneath the current directory. I have provided two images in the .zip archive mentioned earlier in the “img” directory: “one.jpg” and “two.jpg”.

Here is the Python code to generate the file “index.html” in the current directory based on “template.htm”.

#!/usr/bin/python
# Generate a simple web slideshow
# for use with a Chromecast.
#
# Copyright (c) 2014 by Jim Lawless
# See MIT/X11 license at
# http://www.mailsend-online.com/license2014.php
#

import os
import SimpleHTTPServer
import SocketServer
import string

delay_millis="10000"
images=os.listdir('img')
html=''

    # Build an HTML snippet that contains
    # a JavaScript list of string-literals.
for img in images:
    html=html+'\"img/' + img + '\"'
        # Place a comma on the end
        # unless this is the last item in
        # the list
    if img != images[-1]:
        html=html+','

with open('template.htm',"r") as tplfile:
     payload=tplfile.read()

    # Replace $$1 and $$2 with the delay
    # in milliseconds and generated list
    # of images.  Write the output to
    # index.html
payload=string.replace(payload,"$$1",delay_millis)
payload=string.replace(payload,"$$2",html)
with open("index.html","w") as indexfile:
   indexfile.write(payload)

    # Now, start serving up pages
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = SocketServer.TCPServer(("", 80), Handler)
print "HTTP server running..."
httpd.serve_forever()

When executed in the current directory with the file “template.htm” present and the “img” directory containing the two previously-mentioned image files:

python cast.py

The generated file “index.html” would look something like this:

<html><head><title></title></head>

<style type="text/css">
img {
 display: block; 
 margin-left: 
 auto; margin-right: 
 auto; max-width: 100%; 
 max-height: 100%; 
}
</style>

<body onload="nextOne(); setInterval('nextOne();',10000);">

<script type="text/javascript">
 var imgList=[ 
 "img/one.jpg","img/two.jpg"
 ];
 var ctr=0;
 function nextOne() {
 ctr++;
 ctr%=imgList.length;
 document.getElementById("theImg").src=
 imgList[ctr];
 }

</script>

<img id="theImg">

</body></html>

Note that the $$1 pseudo-variable from “template.htm” has been replaced with the value of Python script’s variable named delay_millis. The $$2 pseudo-variable has been replaced with the value in the Python script’s variable named html.

After the index.html file is created, the build-in Python web-server is started.

To view the slideshow, bring up the Chrome browser and visit the address: http://localhost

You should see one of the two JPEG files. Ten seconds later, you should see the other one. If you supplied your own image files, you should see them every 10 seconds. After you click the “Cast” icon in Chrome, you should be able to choose your Chromecast device as a receiver of the tab’s contents. Your TV should now be displaying your slideshow.

You can change the viewing frequency by changing the delay_millis variable in the Python script.

I tried to center the images with some CSS, but I wasn’t able to vertically-center them. You are encouraged to edit the template.htm file to accommodate your needs.

Other changes that you might choose to make could include ordering the list of images based on filename, timestamp, or some other characteristic. You might add sound and other HTML elements. The Python script and HTML/JS template are meant to be a starting-point. Have fun!

Advertisements

About Jim Lawless

I've been programming computers for about 36 years ... 30 of that professionally. I've been a teacher, I've worked as a consultant, and have written articles here and there for publications like Dr. Dobbs Journal, The C/C++ Users Journal, Nuts and Volts, and others.
This entry was posted in Programming, TV and tagged , . Bookmark the permalink.

7 Responses to A Chromecast Slideshow using Python

  1. Bob says:

    This sounds great! So how does a guy with 0 years of programming, with 0 of those years being professionally get this to work?

    Thanks! Bob

    • Jim Lawless says:

      I wish I had a quick answer for you, Bob. Ideally, this script would work best as an installable application. I don’t have time to put one together in the foreseeable future, but I’ll try to give the situation some thought.

  2. Hugo says:

    Thanks for this! It’s working for me on OS X, although I had to change the port number from 80 to something higher to 1024 to avoid this:

    “`
    Traceback (most recent call last):
    File “cast.py”, line 43, in
    httpd = SocketServer.TCPServer((“”, 80), Handler)
    File “/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py”, line 420, in __init__
    self.server_bind()
    File “/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py”, line 434, in server_bind
    self.socket.bind(self.server_address)
    File “/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py”, line 224, in meth
    return getattr(self._sock,name)(*args)
    socket.error: [Errno 13] Permission denied

    Do you have the code on GitHub or somewhere? I’d like to fork and extend it.

    Thanks!

  3. Sam says:

    Hi Jim. I’ve come across a situation in which this slideshow would be excellent for several of my school’s televisions. Unfortunately, the castpy project no longer exists on GitHub… Is there any chance of it returning?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s