├── .gitignore ├── README.md ├── instagram_slide_and_video_show.bat ├── instagram_slide_and_video_show.py └── instagram_slide_and_video_show_gui.bat /.gitignore: -------------------------------------------------------------------------------- 1 | # Misc testing stuff 2 | misc/ 3 | 4 | # IFL photos and videos 5 | instagram_photos_and_videos/ 6 | 7 | # ini file 8 | instagram_slide_and_video_show.ini 9 | 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Raspberry Pi Instagram Slide and Video Show 2 | 3 | ## About 4 | 5 | I'm a volunteer at the [Idea Fab Labs](https://santacruz.ideafablabs.com/) maker/hacker/artspace here in Santa Cruz, 6 | and I was asked to set up a Raspberry Pi for our weekly open house and for IFL booths at events, so that all you 7 | had to do was plug it into a large monitor and it would start running a slideshow of 8 | [Idea Fab Labs' Instagram feed](https://www.instagram.com/ideafablabs/) of photos of projects, facilities, and events. 9 | 10 | I had written my original 11 | [Raspberry Pi Instagram Slideshow](https://github.com/tachyonlabs/raspberry_pi_instagram_slideshow) version in Python 12 | using the Tkinter GUI, but when I was asked to update it to include Instagram videos as well as photos, I rewrote it 13 | (still in Python) using the [Kivy](https://kivy.org/) Framework, and am running it on Raspberry Pi 2 Model Bs running 14 | Raspbian Jessie and Raspbian Stretch. 15 | 16 | If you'd like to do a similar installation with your own Instagram feed, the instructions below will walk you through 17 | getting the slide and video show set up on your Raspberry Pi. 18 | 19 | Because (at least as of September 2017) the Instagram API in [Sandbox Mode](https://www.instagram.com/developer/sandbox/) 20 | only gets the 20 most recent photos and videos from an Instagram account, and in the interest of both reducing 21 | bandwidth and being able to run the slide and video show even when your internet connection is down, once an hour the 22 | program checks Instagram to see if any new photos and videos have been posted to the account, and if so, downloads 23 | them to its `instagram_photos_and_videos` directory. (If you like you can also copy other jpg and mp4 files to the 24 | directory and they will also be included in the slide and video show -- for that matter I used the 25 | [InstaG Downloader Chrome Extension](https://chrome.google.com/webstore/detail/instag-downloader/jnkdcmgmnegofdddphijckfagibepdlb?hl=en) 26 | to download all the photos and videos from the Idea Fab Labs Instagram feed that were older than the 20 most recent, 27 | so they would be in the `instagram_photos_and_videos` directory too.) 28 | 29 | ## Release notes 30 | #### Version 1.2, April 9, 2020 31 | * Updated to work with Instagram's changes to the format of the photo and video URLs returned by their API. Because of 32 | the changes the program had no longer been extracting the \[filename].jpg or .mp4 part of the URLs correctly to save 33 | new media files to disk as, and then likewise was not displaying the new media files because the filenames they had 34 | been saved as didn't end in .jpg or .mp4 35 | 36 | #### Version 1.1, May 22, 2018 37 | * Now works with Python 3 in addition to Python 2. 38 | 39 | * Now includes a setting for whether or not audio is played along with videos. 40 | 41 | * In trying to track down the occasional hanging issue described below, I found that explicitly stopping videos (in 42 | addition to letting them just come to the end themselves) and switching from Python 2 to Python 3 seemed to fix the 43 | issue under Windows (with the Kivy platform you can run your Python code on Windows, Mac, other Linux versions, Android, 44 | and iOS in addition to on the Raspberry Pi), but unfortunately, on the Raspberry Pi, eventually it will still hang and 45 | need to be power-cycled. :-( I'm thinking that some kind of memory leak may be going on, with there eventually being 46 | not enough available memory to play the next video, and, again, hope to find and fix this problem for good at some 47 | point. 48 | 49 | #### Version 1.0, September 27, 2017 50 | * I'm still working on tracking down an issue where the slide and video show will occasionally hang seemingly randomly 51 | while loading a video. As the program is otherwise working, I decided to go ahead and put the initial version up on 52 | GitHub now, but I hope to find and fix the bug soon. 53 | 54 | ## Known issues 55 | 56 | * **"Error loading texture" error messages**: Every time the program loads a video, an "Error loading texture" message 57 | gets printed to the console or terminal window. On one hand I haven't found a way to get rid of them yet, but on the 58 | other hand, the videos are playing just fine regardless. 59 | 60 | ## Getting the slide and video show set up on your Raspberry Pi 61 | I know these instructions look really long, but that's because I'm trying to be thorough rather than because they're 62 | super-complicated. Anyway, follow these instructions to get the slide and video show set up and running on your Raspberry Pi: 63 | 64 | 1. **Command-line vs. GUI?** 65 | 66 | The slide and video show doesn't require the Raspberry Pi GUI desktop to run, and because of the limited resources 67 | of the Raspberry Pi vs. playing videos, I would recommend that when running it you have your Raspberry Pi boot to 68 | the command line rather than to the GUI desktop, but you can run it either way. 69 | 70 | 2. **Configure your Raspberry Pi to connect to your Wifi if you haven't done so already** 71 | 72 | To download Instagram photos and videos (or for that matter to continue following these instructions) your 73 | Raspberry Pi needs to be connected to the Internet. If you haven't already done so, do the following to select 74 | your Wifi network and enter the password: 75 | 76 | * Here's the [official Raspberry Pi documentation on setting Wifi up via the command line](https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md). 77 | 78 | * Or for Raspbian Wheezy and the LXDE GUI desktop, in the Raspberry Pi GUI Menu select `Preferences` and then 79 | `WIFI Configuration`. 80 | 81 | * Or for Raspbian Jessie or Raspbian Stretch, with the Pixel GUI desktop, click the Wifi icon at the top right of the taskbar. 82 | 83 | 3. **Configure the Raspberry Pi to allocate more memory to its GPU (graphics processing unit)** 84 | 85 | At one point when I was wrestling with Kivy and video I followed a suggestion to use the instructions on 86 | [this RPiconfig page](http://elinux.org/RPiconfig) to add the line 87 | ``` 88 | gpu_mem=128 89 | ``` 90 | to the `/boot/config.txt` file. For this particular application this may or may not actually make a difference, but you 91 | might want to experiment with that or different gpu_mem values. 92 | 93 | 4. **Python 3 or Python 2?** 94 | 95 | The Raspberry Pi Instagram Slide and Video Show Python code will work with either Python 3 or Python 2, but as 96 | described in the steps below, how you install Kivy and the required Python libraries, and how you run the program, 97 | will vary a little depending on which version of Python you want to use. Basically, for Python 2 you will be 98 | running `python` and `pip`, and for Python 3 `python3` and `pip3`. 99 | 100 | 5. **Install the Kivy framework on your Raspberry Pi** 101 | 102 | Follow the instructions at [https://kivy.org/docs/installation/installation-rpi.html](https://kivy.org/docs/installation/installation-rpi.html) to download/install/compile Kivy on your Raspberry Pi. 103 | 104 | **Note**: The instructions in the above link are for Python 2. If you want to run the Slide and Video Show with 105 | Python 3 instead, then wherever the instructions specify the `pip` program you should enter `pip3` instead, and 106 | wherever they specify the `Python` program you should enter `Python3` instead. 107 | 108 | **Warning**: Installing Kivy (including its dependencies) can seriously sometimes take hours to complete on a 109 | Raspberry Pi, so start it sometime when you can just let things run. 110 | 111 | On Raspberry Pi 2 Model Bs running Raspbian Jessie or Raspbian Stretch the Kivy installation went very smoothly 112 | (despite taking a long time). However, when I tried to download/install/compile Kivy on another Raspberry Pi 2 113 | Model B that was running Raspbian Wheezy, I got so many error messages that I wound up just upgrading that system 114 | to Jessie before proceeding. 115 | 116 | 6. **Install the Python requests library** 117 | 118 | The slide and video show uses the Python requests library to talk to the Instagram API -- install it by entering 119 | the following at the command line or into a terminal window if you want to use Python 2: 120 | ``` 121 | sudo pip install requests 122 | ``` 123 | Or if you want to use Python 3: 124 | ``` 125 | sudo pip3 install requests 126 | ``` 127 | 128 | 7. **Create a directory for the slide and video show, and copy the files from this repo into it** 129 | 130 | Create a directory `instagram_slide_and_video_show` in the `/home/pi/` directory, and copy the files `instagram_slide_and_video_show.py`, `instagram_slide_and_video_show.bat`, and `instagram_slide_and_video_show_gui.bat` from this repo into it. (Or if you prefer you can use a different slideshow directory name and/or location, adjusting its name/location in subsequent steps accordingly.) 131 | 132 | 8. **Edit `instagram_slide_and_video_show.bat` and `instagram_slide_and_video_show_gui.bat` to specify Python 2 or Python 3.** 133 | 134 | Use a text editor to edit `instagram_slide_and_video_show.bat` and `instagram_slide_and_video_show_gui.bat` so that 135 | depending on whether you're using Python 2 or 3, the line for the Python version you're using will be uncommented, 136 | and the line for the other version will be commented out. 137 | 138 | 9. **Make `instagram_slide_and_video_show.bat` and `instagram_slide_and_video_show_gui.bat` executable.** 139 | 140 | Make the files `instagram_slide_and_video_show.bat` and `instagram_slide_and_video_show_gui.bat` executable by 141 | entering the following at the command line or into a terminal window: 142 | ``` 143 | chmod 755 /home/pi/instagram_slide_and_video_show/instagram_slide_and_video_show.bat 144 | chmod 755 /home/pi/instagram_slide_and_video_show/instagram_slide_and_video_show_gui.bat 145 | ``` 146 | 147 | 10. **Get the Instagram access token for the account you want to use with the slide and video show, and enter it into the program code** 148 | 149 | There are other ways to download Instagram photos than their API, but I used their API. When I was using the Instagram API for another project last year, all you needed to do to download photos from an account was to register as a developer and get a client id, but now you have to go through a lot more steps to generate an access token for the account you want to access. To get the access token I followed the instructions on this [How to get Instagram API access token and fix your broken feed](https://github.com/adrianengine/jquery-spectragram/wiki/How-to-get-Instagram-API-access-token-and-fix-your-broken-feed) page, and as I do some Django development I used the Django development server (as `python manage.py runserver 0.0.0.0:8000` on my Windows system) in their "your favorite MAMP, LAMP, Node whatever you use to create a local server" step. 150 | 151 | When you get the access token you need, use a text editor or IDE to substitute it for "put your access token here" in the line 152 | ``` 153 | self.INSTAGRAM_ACCESS_TOKEN = "put your access token here" 154 | ``` 155 | in `instagram_slide_and_video_show.py`. 156 | 157 | 11. **Set the Raspberry Pi to run the slideshow automatically when it boots** 158 | 159 | * If your Raspberry Pi is set to boot to the command line: 160 | 161 | Follow the instructions on the official [Raspberry Pi rc.local page](https://www.raspberrypi.org/documentation/linux/usage/rc-local.md) to add the line 162 | ``` 163 | /home/pi/instagram_slide_and_video_show/instagram_slide_and_video_show.bat & 164 | ``` 165 | to your `etc/rc.local` file. 166 | 167 | * If your Raspberry Pi is set to boot to the GUI desktop: 168 | 169 | The issue here is that you want the program to run not only after the Raspberry Pi boots, but after the GUI loads. 170 | 171 | What worked for me was following the instructions in one of the posts in the [How to launch programs on LXDE startup](https://www.raspberrypi.org/forums/viewtopic.php?f=27&t=11256) topic in the raspberypi.org forums, doing 172 | 173 | * For Raspbian Wheezy with the LXDE GUI desktop: `sudo nano /etc/xdg/lxsession/LXDE-pi/autostart` 174 | 175 | * For Raspbian Jessie or Raspbian Stretch, with the Pixel GUI desktop: `sudo nano /home/pi/.config/lxsession/LXDE-pi/autostart` 176 | 177 | to edit the autostart file, adding the line 178 | ``` 179 | @/home/pi/instagram_slide_and_video_show/instagram_slide_and_video_show_gui.bat 180 | ``` 181 | to the end of the file, and saving it. 182 | 183 | 12. **Disable the Raspberry Pi screensaver** 184 | 185 | It's great to be have the Raspberry Pi set up so that all you have to do is plug it in and the slide and video show will start, without needing to have a keyboard and/or mouse connected, but pretty sad if it only lasts for ten or fifteen minutes until the screensaver blanks the screen. :-( 186 | 187 | * What worked for me with Raspbian Jessie and Raspbian Stretch set to boot to the command line was following the `consoleblank=0` instructions on the official [Raspberry Pi "Setting the Screen Saver/Screen Blanking"](https://www.raspberrypi.org/documentation/configuration/screensaver.md) page. 188 | 189 | * What worked for me with Raspbian Wheezy and the LXDE GUI desktop was following the "2 – Disabling the blank screen forever" instuctions in this [How to Disable the Blank Screen on Raspberry Pi (Raspbian)](http://www.geeks3d.com/hacklab/20160108/how-to-disable-the-blank-screen-on-raspberry-pi-raspbian/) HackLab post. 190 | 191 | * What worked for me with Raspbian Jessie and Raspbian Stretch, with the Pixel GUI desktop, was adding the line `xserver-command=X -s 0 dpms` to `/etc/lightdm/lightdm.conf` as described in this [Raspberry Pi Stack Exchange comment](https://raspberrypi.stackexchange.com/questions/752/how-do-i-prevent-the-screen-from-going-blank/51687#51687). 192 | 193 | ## Running the slide and video show on your Raspberry Pi 194 | 195 | Once you've followed all the above steps, reboot your Raspberry Pi, and once it finishes booting the slide and video 196 | show should start running automatically. 197 | 198 | Or if you didn't want to set it to run automatically, you can just run it from the command-line (if you're running the 199 | GUI desktop then this would be in a terminal window) by navigating to the `/home/pi/instagram_slide_and_video_show/` 200 | directory and entering the following if you want to use Python 2 201 | ``` 202 | python instagram_slide_and_video_show.py 203 | ``` 204 | or, for Python 3 205 | ``` 206 | python3 instagram_slide_and_video_show.py 207 | ``` 208 | at the prompt. 209 | 210 | The first time you run the program, it will create an `instagram_photos_and_videos` subdirectory, and you'll see messages about photos and videos being downloaded before it starts displaying them. 211 | 212 | If your Raspberry Pi isn't connected to the Internet, or if you haven't obtained an Instagram Access Token for the Instagram account you want to use, and entered it correctly as the `self.INSTAGRAM_ACCESS_TOKEN` value at the beginning of the code, you'll see error messages about that instead of photos and videos. 213 | 214 | If at any point you want to close the slideshow, just press `Esc`. 215 | 216 | Note: Photos and videos uploaded to Instagram can definitely vary in aspect ratio, and sometimes small Instagram photos in particular will have sort of built-in borders above and below, but if all of your photos and videos are displaying with large black borders around them, with none of them having any edges flush with the edges of the monitor or TV, you may want to try [adjusting your Raspberry Pi's overscan settings](http://www.opentechguides.com/how-to/article/raspberry-pi/28/raspi-display-setting.html) to improve the appearance. 217 | 218 | ### Slide and video show configuration options 219 | 220 | The first time the program runs, it creates an `instagram_slide_and_video_show.ini` file in the 221 | `instagram_slide_and_video` directory, which you can edit to configure the following program options: 222 | 223 | - Whether the program displays photos and videos in random order, in the order they are in the `instagram_photos_and_videos` directory, or in sorted lexicographic order (the default is random). 224 | - How long the program displays a photo before moving on to the next photo or video (the default is 15 seconds). 225 | - Whether videos are played with or without sound (the default is with sound). 226 | -------------------------------------------------------------------------------- /instagram_slide_and_video_show.bat: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd /home/pi/instagram_slide_and_video_show 3 | 4 | # the line below should be uncommented if you want to use Python 2, and commented out for Python 3 5 | # python /home/pi/instagram_slide_and_video_show/instagram_slide_and_video_show.py 6 | 7 | # the line below should be uncommented if you want to use Python 3, and commented out for Python 2 8 | python3 /home/pi/instagram_slide_and_video_show/instagram_slide_and_video_show.py 9 | -------------------------------------------------------------------------------- /instagram_slide_and_video_show.py: -------------------------------------------------------------------------------- 1 | # Raspberry Pi Instagram Slide and Video Show version 1.2, April 9, 2020 2 | # See https://github.com/tachyonlabs/raspberry_pi_slide_and_video_show 3 | 4 | import kivy 5 | kivy.require('1.10.0') # replace with your current Kivy version ! 6 | from kivy.app import App 7 | from kivy.core.window import Window 8 | from kivy.uix.floatlayout import FloatLayout 9 | from kivy.uix.image import Image 10 | from kivy.uix.video import Video 11 | from kivy.clock import Clock 12 | import requests 13 | import json 14 | import os 15 | import sys 16 | import random 17 | from datetime import datetime 18 | # Python 3 has ConfigParser renamed to configparser for PEP 8 compliance 19 | if sys.version_info[0] < 3: 20 | import ConfigParser 21 | else: 22 | import configparser as ConfigParser 23 | 24 | class SlideAndVideoShow(App): 25 | def __init__(self): 26 | super(SlideAndVideoShow, self).__init__() 27 | self.INSTAGRAM_ACCESS_TOKEN = "put your access token here" 28 | self.MOST_RECENT_PHOTOS_AND_VIDEOS_URL = "https://api.instagram.com/v1/users/self/media/recent/?access_token={}".format(self.INSTAGRAM_ACCESS_TOKEN) 29 | self.LOCAL_PHOTO_AND_VIDEO_DIRECTORY_PATH = "./instagram_photos_and_videos/" 30 | self.INI_FILE = "./instagram_slide_and_video_show.ini" 31 | self.title = "Instagram Slide and Video Show" 32 | self.HOUR_IN_SECONDS = 60 * 60 33 | # default configuration settings, used to create instagram_slide_and_video_show.ini if it doesn't already exist 34 | self.SECONDS_BEFORE_CHANGING_PHOTO = 15 35 | self.PHOTO_AND_VIDEO_DISPLAY_ORDER_DIRECTORY = "directory" 36 | self.PHOTO_AND_VIDEO_DISPLAY_ORDER_RANDOM = "random" 37 | self.PHOTO_AND_VIDEO_DISPLAY_ORDER_SORTED = "sorted" 38 | self.PHOTO_AND_VIDEO_DISPLAY_ORDER = self.PHOTO_AND_VIDEO_DISPLAY_ORDER_RANDOM 39 | self.SOUND_ON = 1 40 | self.SOUND_OFF = 0 41 | self.VIDEO_VOLUME_ON_OR_OFF = self.SOUND_ON 42 | # get stored configuration settings 43 | self.get_preferences_from_ini_file() 44 | # download any new photos or videos 45 | self.download_any_new_instagram_photos_or_videos() 46 | # get the filenames of all newly and/or previously-downloaded photos and videos 47 | self.photos_and_videos = self.get_photo_and_video_filenames() 48 | self.current_image_index = -1 49 | 50 | def get_preferences_from_ini_file(self): 51 | if os.path.isfile(self.INI_FILE): 52 | # if the .ini file exists, read in the configuration settings 53 | config = ConfigParser.RawConfigParser() 54 | config.read(self.INI_FILE) 55 | self.PHOTO_AND_VIDEO_DISPLAY_ORDER = config.get("DisplaySettings", "photo_and_video_display_order") 56 | self.SECONDS_BEFORE_CHANGING_PHOTO = int(config.get("DisplaySettings", "seconds_before_changing_photo")) 57 | self.VIDEO_VOLUME_ON_OR_OFF = int(config.get("DisplaySettings", "video_volume_on_or_off")) 58 | else: 59 | # or if it doesn't exist, create it with the default settings 60 | self.create_ini_file() 61 | 62 | def create_ini_file(self): 63 | # create the ini file with the default settings the first time you run the program 64 | config = ConfigParser.RawConfigParser(allow_no_value=True) 65 | ini_file = open(self.INI_FILE, 'w') 66 | config.add_section("DisplaySettings") 67 | config.set('DisplaySettings', '; Valid display order settings are directory, random, or sorted') 68 | config.set("DisplaySettings", "photo_and_video_display_order", self.PHOTO_AND_VIDEO_DISPLAY_ORDER) 69 | config.set("DisplaySettings", "seconds_before_changing_photo", self.SECONDS_BEFORE_CHANGING_PHOTO) 70 | config.set("DisplaySettings", "video_volume_on_or_off", self.VIDEO_VOLUME_ON_OR_OFF) 71 | config.write(ini_file) 72 | ini_file.close() 73 | 74 | def download_any_new_instagram_photos_or_videos(self, value=None): 75 | # create the instagram_photos_and_videos subdirectory if it doesn't already exist 76 | if not os.path.isdir(self.LOCAL_PHOTO_AND_VIDEO_DIRECTORY_PATH): 77 | os.mkdir(self.LOCAL_PHOTO_AND_VIDEO_DIRECTORY_PATH) 78 | 79 | print ("Checking for any new Instagram photos or videos at {} ...".format(datetime.now())) 80 | internet_connection = True 81 | 82 | # get URLs, captions, etc. on the 20 most recent Instagram photos and videos 83 | try: 84 | json_data = json.loads(requests.get(self.MOST_RECENT_PHOTOS_AND_VIDEOS_URL).text) 85 | except: 86 | internet_connection = False 87 | print ("Unable to reach Instagram ... check your Internet connection. Showing stored photos and videos.") 88 | 89 | if internet_connection: 90 | new_photos_and_videos_downloaded = False 91 | 92 | # and check to see whether or not they have already been downloaded 93 | try: 94 | for photo_or_video in json_data["data"]: 95 | if "videos" in photo_or_video: 96 | photo_or_video_url = photo_or_video["videos"]["standard_resolution"]["url"] 97 | jpg_or_mp4_end = photo_or_video_url.index("mp4") + 3 98 | else: 99 | photo_or_video_url = photo_or_video["images"]["standard_resolution"]["url"] 100 | jpg_or_mp4_end = photo_or_video_url.index("jpg") + 3 101 | 102 | # The URL will look like this ... 103 | # https://scontent.cdninstagram.com/v/t51.2885-15/sh0.08/e35/s640x640/91944348_533445680909267_5495124442234212437_n.jpg?_nc_ht=scontent.cdninstagram.com&_nc_ohc=dpIjuIOBYTIAX8q5WiJ&oh=310b3910a2adb4ded46041e00d3c9707&oe=5EB8023F 104 | # ... so for the filename to save the photo to disk as, extract the part that looks like this ... 105 | # 91944348_533445680909267_5495124442234212437_n.jpg 106 | photo_or_video_filename = photo_or_video_url[photo_or_video_url.rindex("/") + 1:jpg_or_mp4_end] 107 | if not os.path.isfile(self.LOCAL_PHOTO_AND_VIDEO_DIRECTORY_PATH + photo_or_video_filename): 108 | new_photos_and_videos_downloaded = True 109 | if photo_or_video["caption"]: 110 | print ('Downloading and saving "{}"'.format(photo_or_video["caption"]["text"].encode("utf8") if photo_or_video["caption"] else "...")) 111 | else: 112 | print('Downloading and saving "{}"'.format(photo_or_video_filename)) 113 | photo_or_video_file = requests.get(photo_or_video_url).content 114 | with open(self.LOCAL_PHOTO_AND_VIDEO_DIRECTORY_PATH + photo_or_video_filename, 'wb') as handler: 115 | handler.write(photo_or_video_file) 116 | except: 117 | print ("Instagram error:", json_data) 118 | 119 | if new_photos_and_videos_downloaded: 120 | # update the list of filenames in the instagram_photos_and_videos subdirectory 121 | self.get_photo_and_video_filenames() 122 | else: 123 | print ("No new photos or videos found.") 124 | 125 | # check for new photos and videos once an hour 126 | Clock.schedule_once(self.download_any_new_instagram_photos_or_videos, self.HOUR_IN_SECONDS) 127 | 128 | def on_position_change(self, instance, value): 129 | # I'm doing it this way because eos wasn't always firing at the end of a video, 130 | # plus position isn't updated often enough to get all the way to the duration value. 131 | # If the program hangs at the end of a video you may need to increase the .3 value 132 | # (which means .3 of a second) a little more. 133 | if value > self.video_duration - .3: 134 | self.video.state = "stop" 135 | self.next_photo_or_video() 136 | 137 | def on_duration_change(self, instance, value): 138 | self.video_duration = value 139 | 140 | def on_texture_change(self, instance, value): 141 | # I'm doing it this way because I couldn't get loaded or on_load to actually fire, 142 | # but texture has reliably only been there only after a video finishes loading. 143 | if self.video.texture: 144 | self.video.opacity = 1 145 | self.photo.opacity = 0 146 | 147 | def build(self): 148 | # This line is for running under Windows but crashes things on the Raspberry Pi 149 | # Window.fullscreen = "auto" 150 | Window.show_cursor = False 151 | self.photo = Image() 152 | self.photo.allow_stretch = True 153 | # Without this line the Raspberry Pi starts blacking out photos after a few images. 154 | self.photo.nocache = True 155 | self.video = Video(allow_stretch=True, options={'eos': 'stop', 'autoplay': True}) 156 | self.video.bind(position=self.on_position_change, duration=self.on_duration_change, texture=self.on_texture_change) 157 | self.video.opacity = 0 158 | self.video.allow_stretch = True 159 | self.video.nocache = True 160 | self.video.volume = self.VIDEO_VOLUME_ON_OR_OFF 161 | self.screen = FloatLayout() 162 | self.screen.add_widget(self.photo) 163 | self.screen.add_widget(self.video) 164 | Clock.schedule_once(self.next_photo_or_video, 1) 165 | return self.screen 166 | 167 | def next_photo_or_video(self, value=None): 168 | if self.PHOTO_AND_VIDEO_DISPLAY_ORDER in [self.PHOTO_AND_VIDEO_DISPLAY_ORDER_DIRECTORY, self.PHOTO_AND_VIDEO_DISPLAY_ORDER_SORTED]: 169 | self.current_image_index = (self.current_image_index + 1) % len(self.photos_and_videos) 170 | elif self.PHOTO_AND_VIDEO_DISPLAY_ORDER == self.PHOTO_AND_VIDEO_DISPLAY_ORDER_RANDOM: 171 | self.current_image_index = random.randint(0, len(self.photos_and_videos) - 1) 172 | 173 | next = self.LOCAL_PHOTO_AND_VIDEO_DIRECTORY_PATH + self.photos_and_videos[self.current_image_index] 174 | if next.endswith(".jpg"): 175 | self.photo.source = next 176 | self.video.opacity = 0 177 | self.photo.opacity = 1 178 | Clock.schedule_once(self.next_photo_or_video, self.SECONDS_BEFORE_CHANGING_PHOTO) 179 | else: 180 | self.video.source = next 181 | self.video.state = "play" 182 | 183 | def get_photo_and_video_filenames(self): 184 | # get all the jpg and mp4 filenames in the instagram_photos_and_videos subdirectory 185 | photo_and_video_filenames = [file for file in os.listdir(self.LOCAL_PHOTO_AND_VIDEO_DIRECTORY_PATH) if file.endswith(".jpg") or file.endswith(".mp4")] 186 | if self.PHOTO_AND_VIDEO_DISPLAY_ORDER == self.PHOTO_AND_VIDEO_DISPLAY_ORDER_SORTED: 187 | photo_and_video_filenames.sort() 188 | 189 | if not photo_and_video_filenames: 190 | # If there are no stored photos and/or videos, and the program was not able to download any, 191 | # you need to fix your Internet connection and/or Instagram Access Token. 192 | print ("No stored photos or videos found. Make sure that you're") 193 | print ("(1) connected to the Internet, and") 194 | print ("(2) that you've obtained an Instagram Access Token for the Instagram account you want to use, and entered it correctly as the self.INSTAGRAM_ACCESS_TOKEN value at the beginning of the code,") 195 | print ("and then try again.") 196 | exit() 197 | 198 | return photo_and_video_filenames 199 | 200 | if __name__ == '__main__': 201 | SlideAndVideoShow().run() 202 | -------------------------------------------------------------------------------- /instagram_slide_and_video_show_gui.bat: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd /home/pi/instagram_slide_and_video_show 3 | 4 | # the line below should be uncommented if you want to use Python2, and commented out for Python 3 5 | # lxterminal -l -e "python /home/pi/instagram_slide_and_video_show/instagram_slide_and_video_show.py ; /bin/sh " 6 | 7 | # the line below should be uncommented if you want to use Python3, and commented out for Python 2 8 | lxterminal -l -e "python3 /home/pi/instagram_slide_and_video_show/instagram_slide_and_video_show.py ; /bin/sh " 9 | --------------------------------------------------------------------------------