Building a messenger-controlled wall-mounted GIF display

Wed, Jan 11, 2017

For a long time I wanted to setup a Raspberry Pi in our flat’s living room. I wanted it to show a looping playlist of GIFs and then maybe extend it to other functionality that is cool to have in a shared flat. This christmas I finally got around to building this thing and it has been so much fun!

I started developing in Jupyter Notebook and below you can read the results of that. After some time the thing had gotten pretty complex and so I started working in a conventional editor. I still want to post what I did in Jupyter in the beginning though, because I think it can be pretty interesting as a simple example of a Python Telegram bot.

In the meantime I have added much more robust video playback, more options for adding animations and also a web radio that allows selecting stations through the chat bot and sends background information as well as images about the music that it is playing to the group. You can see the code for this on the project’s Github page.

But let’s get back to the simple version I started with.

Build a Telegram Bot

For this project I am using a wall-mounted Raspberry Pi 3 model B in a simple transparent case from Amazon with a Kuman 3.5” touch-enabled display. The Pi runs a Raspian Jessie image provided by the display manufacturer.

The display bot will be controlled through a chatbot that lives in a Telegram group shared with my flatmates. First, I need to create the Telegram bot. For this, install the Python Telegram Bot library and the peewee database ORM with

These two function will later be registered with the Telegram bot API.

Config persistence

We need a way to keep track of all the videos we will download and maybe other stuff later on. While what I did is not the most elegant solution, it works for now: We use a global dictionary that loads from and saves to a JSON-serialized file on disk.

Receive clips from Telegram

Next ist the receiver for our app. It will look at incoming messages and determine, whether they contain links. Iterating over the link elements contained in the message, we check that the link is valid by sending an HTTP HEAD request and checking the HTTP headers to see whether the link points at one of the supported animation file types,

Special case: if url ends in gif, the gif is downloaded and converted to a local mp4 (see code for that below).

Videoplayer

The video player itself consists of two function: The first, get_next returns the next video file to play, which is a random one, unless we have just added a new video, in which case it will be this. The second one play_video starts mplayer, an external video player, with the return value of the first function, waits until it has finished playing and then starts over. Forever!

Main function

Here, all loose ends tie up: A Telegram Updater connects to the Telegram Bot API for us. The three handlers are added - one to give instructions after the bot is first started, one to handle any incoming message and one for errors and finally the endless video-playing loop is started.

def main():
# Load configuration and video database
load()
# Create the EventHandler and pass it your bot's token.
updater = Updater(TELEGRAM_API_TOKEN)
# Get the dispatcher to register handlers
dp = updater.dispatcher
# on different commands - answer in Telegram
dp.add_handler(CommandHandler("start", start))
# on noncommand i.e message - echo the message on Telegram
dp.add_handler(MessageHandler(None, receive))
# log all errors
dp.add_error_handler(error)
# Start the Bot
updater.start_polling()
# Start the player
play_video()
# Run the bot until the you presses Ctrl-C or the process receives SIGINT,
# SIGTERM or SIGABRT. This should be used most of the time, since
# start_polling() is non-blocking and will stop the bot gracefully.
# updater.idle()