Package: 01memories
Digital Memories (01memories)Digital Memories is a Python-based digital photo frame application. It is capable of displaying photos and playing videos from local storage as well as WebDAV andrclonerepositories.Digital Memories has been designed to run slideshows from image and video repositories with several thousand files. No conversion is required. Files remain in your repositories and fully under your control.Files in slideshows can be dynamically arranged and filtered based on their metadata (EXIF and IPTC metadata supported). Slideshows can be run continuously or scheduled.Digital Memories supports reverse geocoding based on GPS data in the EXIF tag, using the geopy library and Photon geocoder (essentially OpenStreetMap).Digital Memories optionally integrates withHome AssistantviaMQTT. Integration allows the display to be motion activated after coupling of the Digital Memories device with a motion sensor.Digital Memories is being developed byBernd Kalbfuss (aka langweiler)and is published under theGeneral Public License version 3. The latest source code is available onGitHub.Instructions for building your own digital photo frame can be foundhere.DependenciesDigital Memories requiresPython 3to run. It has been developed with Python version 3.10 on Ubuntu Linux, but may run with earlier versions and on different operating systems.Digital Memories requires the following Python packages to be installed:exifreadffmpeg-pythongeopyIPTCInfo3Kivypaho-mqttpillowpyyamlrclone-pythonscheduleSQLAlchemywebdavclient3All packages are available onpypi.organd can be installed using the "pip install" (or "pip3 install") command. Where possible/available, packages should be installed using the distribution package manager (e.g  "apt" on Debian/Ubuntu).Digital Memories further requires the following (non-Python) libraries to be installed:libxslt1.1libmtdev1libsqlite3-0libsdl2-2.0-0ffmpegLibraries should be installed using the distribution package manager.Note that Digital Memories requires the X windows system and a desktop environment to be installed. Digital Memories will in principle also run under Wayland, but the display will not be turned off automatically since Wayland does fully implement the "xset" command.InstallationDigital Memories is still in early development. The easiest way to install the latest version is to clone the GitHub repository using thegitclient. After having installed thegitclient, installation of Digital Memories becomes as simple as:$gitclonegit@github.com:kalbfuss/01memories.gitThe command installs the Digital Memories sources in the sub-directory "pyframe" within the current working directory. Digital Memories can be updated to the latest version by changing into the "pyframe" directory and issuing the following command:$cdpyframe
$gitpulloriginmasterAt this stage of the project you should not expect the configuration syntax to be stable. Please, have a look at the documentation after each update and adjust the configuration as necessary.ConfigurationThe Digital Memories application is configured via a single YAML configuration file. The file is named "config.yaml" and must be stored in the current (working) directory. The following sections provide examples for configuration and the documentation of all parameters.A lot of effort has gone into configuration checks. The application should warn you in the event of invalid configurations immediately after startup. It is thus safe to explore the various configuration options. Under no circumstances is Digital Memories going to modify any of your image or video files.ExamplesSimple configurationIn this example, we want to continuously show all files stored in a local directory. For this purpose, we configure a single local repository ("Local storage"). Our files are stored under the relative path "./local/photos". We further define a single slideshow ("Favorites") containing all files from the repository.  Files are shown in a random sequence for a duration of 60 s.Per (application) default settings, the repository is indexed once after start of the application. The slideshow includes photos and videos. The slideshow starts playing after start of the application and the display is always on.repositories:# Local repository with our favorite photos and videos.Local storage:type:localroot:./local/photosslideshows:# Slideshow with our favorite photos and videos.Favorites:repositories:Local storagepause:60sequence:randomAdvanced configurationIn this example, we want to show our most recent photos stored in the cloud in the period from 8:00 to 10:00 and our favorite photos, which are stored locally, in the period from 18:00 to 20:00. Since we are not necessarily at home in the evening, we want the display to be motion activated during this time.Firstly, we define two (enabled) repositories: A local repository ("Local storage") with files stored under the relative path "./local/photos" and a WebDAV repository ("Cloud storage") with files stored in the cloud. The third repository ("Test repository") used for testing has been disabled. Per the repository default settings, the index of the local repository is updated at the start of the application and every 24 hours. The index of the cloud repository is updated daily at 23:00.Secondly, we define two slideshows: The first slideshow ("Favorites") includes files tagged as "favorites" from the local repository. Files are shown for a duration of 60 s. The second slideshow ("Recent") includes the 200 most recent files from the cloud repository, which are not tagged as "vacation" or "favorites". We further limit files to "images". Files are sorted by the creation date in ascending order. Per the slideshow defaults, images are shown for a duration of 180 s.The slideshow defaults further ensure that files tagged as "private" are always excluded. Files are labeled with their description from the file metadata (if available) and labels are shown for a duration of 60 s at the start and the end of each file. Since the display is installed in vertical orientation, we rotate the content by -90° and limit content to files in portrait orientation.Thirdly, we define a schedule to show the second slideshow ("Recent") in the time from 8:00 to 10:00 and the first slideshow ("Favorites") in the time from 18:00 to 20:00. In the first case, the display is always on. In the second case, the display is motion activated with a timeout interval of 300 s.Finally, since we run Home Assistant and need the MQTT remote control for the motion activation feature, we configure an MQTT client connection. For the motion activation feature to function properly, we further have to link the touch button with a motion sensor in Home Assistant (see [motion activation](#Motion activation)).repositories:# Local repository with our favorite photos and videos.Local storage:type:localroot:./local/photos# WebDAV repository with the latest photos from our smartphone.Cloud storage:type:webdavurl:https://mycloud.mydomain.orgroot:/remote.php/webdav/photosuser:pyframepassword:<password>index_update_at:"23:00"# Test repository, which has been disabled.Test repository:type:localroot:./local/testenabled:false# Repository defaultsindex_update_interval:24slideshows:# Slideshow with our favorite photos and videos.Favorites:repositories:Local storagepause:60tags:favorites# Slideshow with most recent photos from our smartphone.Recent:repositories:Cloud storageexcluded_tags:-vacation-favoritestypes:imagesmost_recent:200order:datedirection:descending# Slideshow defaultsalways_excluded_tags:privatelabel_content:descriptionlabel_mode:autolabel_duration:30orientation:portraitpause:180rotation:-90schedule:# Play the slideshow "Recent" in the period from 8:00 to 10:00.morning start:time:"08:00"slideshow:Recentdisplay_mode:staticplay_state:playingmorning stop:time:"10:00"play_state:stopped# Play the slideshow "Favorites" in the period from 18:00 to 20:00.# Activate the display by motion.evening start:time:"18:00"slideshow:Favoritesdisplay_mode:motiondisplay_timeout:300play_state:playingevening stop:time:"20:00"play_state:stoppedmqtt:host:mqtt.localuser:pyframepassword:<my password>device_name:My Digital Memories somwhere in the houseApplicationThe following parameters are used to configure the application.BasicParameterDescriptionwindow_sizeThe size of the window provided as[width, height]. A value of "full" enables full screen mode. The default is "full".display_modeThe following display modes are supported. The default is "static".-static: The display is always on if a slideshow is paused or playing and off if a slideshow is stopped.-motion: The display is turned on and the slideshow starts playing in the presence of motion (i.e.touchevents). The slideshow is paused and the display turned off in the absence of motion after the display timeout interval.display_timeoutThe time in seconds after which the slideshow is paused and screen turned off in the absence of motion. The default is 300 seconds.AdvancedParameters in this section will likely not have to be modified by the majority of users.ParameterDescriptionindexThe index database file. The path may be absolute or relative to the current working directory. The default is "./index.sqlite".cacheThe directory in which files can be cached (used by WebDAV and rclone repositories). The directory path may be absolute or relative to the current working directory. The directory can be shared by multiple repositories.Do notuse directory in which you store files as cache directory. The default is "./cache".enable_exception_handlerSet totruein order to enable the generic exception handler. The generic exception handler prevents the application from exiting unexpectedly. Exceptions are logged, but the execution continues. The default isfalse.enable_schedulerSet tofalsein order to disable the scheduler. The scheduler is disabled even in the presence of ascheduleconfiguration section. The default istrue.enable_mqttSet tofalsein order to disable the MQTT client. The client is disabled even in the presence of anmqttconfiguration section. The default istrueenable_loggingSet tofalsein order to disable logging. The default istrue.log_levelThe log level, which can be set todebug,info,warning, orerror. The default is "warning".log_dirThe directory to which log files are written. The directory path may be absolute or relative to the current working directory. The default is "./log".RepositoriesDigital Memories supports the configuration of one or multiple file repositories. Repositories are configured in therepositoriessection of the configuration file. The section is required and must contain at least a single, valid repository definition. Repository parameter defaults may be provided as global parameters.  The example below provides a typicalrepositoriesconfiguration section....repositories:# Local repository with our favorite photos and videos.Local storage:type:localroot:./local/photos# WebDAV repository with the latest photos from our smartphone.Cloud storage:type:webdavurl:https://mycloud.mydomain.orgroot:/remote.php/webdav/photosuser:pyframepassword:<password># Test repository, which has been disabled.Test repository:type:localroot:./local/testenabled:false# Repository defaultsindex_update_interval:24...The following parameters are used to configure repositories.GeneralParameterDescriptiontypeThe following repository types are supported. A values must be provided.-local: Repository with files on the local file system.Note:Even if referred to aslocal, files may be stored on a network share as long as the network is mounted and integrated into the file system hierarchy (e.g. "/mnt/photos").-rclone: Repository with files on an rclone remote. The remote must have been configured before using the "rclone config" command or directly in the rclone configuration file.-webdav: Repository with files on a WebDAV accessible site (e.g. ownCloud or NextCloud).index_update_intervalInterval in hours at which the metadata index for the repository is updated. If zero, the index is only updated once after start of the application. The default ist 0. Do not use in combination withindex_update_at.index_update_atThe time at which the metadata index for the repository is updated. The index is updated once per day. Do not use in combination withindex_update_interval.enabledSet tofalsein order to disable the repository. The default istrue.Local repositoriesOnly a single parameter is required for the definition of local repositories.ParameterDescriptionrootThe repository root directory. Root directories may be absolute or relative to the current working directory. Files in sub-folders will be included in the repository. A value must be provided.Rclone repositoriesLike for local repositories, only a single parameter is required for the definition of rclone repositories. However, the rclone remote must have been configured before. Digital Memories currently does not provide any functionality to configure rclone remotes.ParameterDescriptionrootThe rclone remote and root directory (e.g. "mycloud:/photos/"). Files in sub-folders will be included in the repository. A value must be provided.WebDAV repositoriesAs a minimum, the parametersurl,userandpasswordneed to be specified for the definition of a WebDAV repository.ParameterDescriptionurlThe URL of the WebDAV server. Use "https://" protocol prefix for secure connections. A value must be provided.userLogin name. A value must be provided.passwordLogin password. A value must be provided.rootThe root directory relative to the URL. For ownCloud WebDAV access, the root directoy typically starts with "/remote.php/webdav". The default is/.SlideshowsDigital Memories supports the configuration of one or multiple slideshows. Slideshows are configured in theslideshowssection of the configuration file. The section is required and must contain at least a single, valid slideshow definition. The first slideshow is the default slideshow. Slideshow parameter defaults may be provided as global parameters. The example below provides a typicalslideshowsconfiguration section....slideshows:# Slideshow with our favorite photos and videos.Favorites:repositories:Local storagepause:60tags:favorites# Slideshow with most recent photos from our smartphone.Recent:repositories:Cloud storageexcluded_tags:-vacation-favoritestypes:imagesmost_recent:200order:datedirection:descending# Slideshow defaultsalways_excluded_tags:privatelabel_content:descriptionlabel_mode:autolabel_duration:30orientation:portraitpause:180rotation:-90...The following parameters are used to configure slideshows.General parametersParameterDescriptionbg_colorThe background color used to fill empty areas, provided as[r, g, b]. The default is[1, 1, 1](white).label_contentThe following content based on file meta data is supported. The default is "full".-description:only image description-short:image description, location, and creation date-full:image description, location, creation date and tags, file name and repositorylabel_durationDuration in seconds for which labels are shown. The default is 60.label_font_sizeThe relative font size of labels, expressed as percentage of the shortest file dimension. The default is 0.08.label_modeThe following label modes are supported. The default is "off".-auto:Labels are shown at the beginning and end of a file for thelabel_duration.-off:Labels are never shown.-on:Labels are always shown.label_paddingThe relative padding of labels, expressed as percentage of the shortest file dimension. The default is 0.03.pauseThe delay in seconds until the next file is shown. The default is 300.resizeThe following resize modes are supported. The default is "fill".-fit:The slideshow content is zoomed to fit the screen as good as possible. Empty areas are filled with the background color.-fill:The slideshow content is zoomed and cropped to completely fill the screen. Note that images which do not have the same orientation as the screen are not zoomed and cropped, but only fit to the screen.rotationThe angle by which slideshow content is rotated clockwise. Useful for picture frames/screens, which are installed in non-standard orientation. The default is 0.Filter criteriaThe following parameters control the files included in a slideshow and the sequence in which they are shown. The default is to include all files from all repositories. Files are sorted by their name in ascending order.ParameterDescriptionrepositoriesThe repositories from which files shall be shown. The default is to show files from all repositories.orientationValid orientations areportraitorlandscape. The default is to include either orientation.typesSupported file types areimagesandvideos. May be a single value or list of values. The default is to include all file types.tagsFile tags, which shall be included. May be a single value or list of values. The default is to include all tagsanduntagged files. If set, untagged files are excluded.excluded_tagsFile tags, which shall be excluded. May be a single value or list of values. The default is not to exclude any tags.always_excluded_tagsSame asexcluded_tags, but not overwritten by anexcluded_tagsstatement. Use in the slideshow default configuration to exclude certain tags in all slideshows (e.g. private content).most_recentFiles in the slideshow are limited to themost_recentnumber of files based on the creation dateafterapplication of all other filter criteria.orderThe sort order in which files are shown. The default is "name".-date:Files are sorted by their creation date.-name:Files are sorted by their name.-random:Files are shown in a random sequence.-smart: A short sequence with random starting point, sorted by date in ascending order.directionValid sort directions areascendingordescending. The default is "ascending". Ignored if random order is configured.smart_limitThe (maximum) number of files in a smart sequence. If thesmart_timecriterion is not met, the sequence may be shorter. The default is 10.smart_timeThe maximum time allowed in-between subsequent files of a smart sequence in hours. If exceeded, the sequence is terminated early and a new sequence initiated. The default is 24.ScheduleDigital Memories supports the configuration of a schedule. The schedule allows to alter the application behavior at predefined points in time. The schedule is configured in the optionalschedulesection of the configuration file. The schedule may contain one or multiple events. The schedule is disabled if the configuration section is missing. The example below provides a typicalscheduleconfiguration section.schedule:# Play the slideshow "Recent" in the period from 8:00 to 10:00.morning start:time:"08:00"slideshow:Recentdisplay_mode:staticplay_state:playingmorning stop:time:"10:00"play_state:stopped# Play the slideshow "Favorites" in the period from 18:00 to 20:00.# Activate the display by motion.evening start:time:"18:00"slideshow:Favoritesdisplay_mode:motiondisplay_timeout:30play_state:playingevening stop:time:"20:00"play_state:stoppedThe following parameters are used to configure events in the schedule.ParameterDescriptiontimeThe time of the event. A value must be provided. Always specify in quotation marks.Note:Hours and minutes <10 must be preceded by a 0, i.e. "08:03" and never "8:3".slideshowSelected slideshow. If no slideshow is specified, the previous or default slideshow is assumed.play_stateValid play states arepaused,playingandstopped. The play state remains unchanged if no value is provided. The default is "stopped".display_modeThe following display modes are supported. The display mode remains unchanged if no value is provided. The default is "static".-static: The display is always on if a slideshow is paused or playing and off if a slideshow is stopped.-motion: The display is turned on and the slideshow starts playing in the presence of motion. The slideshow is paused and the display turned off in the absence of motion after the display timeout interval.display_timeoutThe time in seconds after which the slideshow is paused and screen turned off in the absence of motion. The display timeout remains unchanged if no value is provided. The default is 300.MQTTDigital Memories implements an MQTT client, which registers the device with an MQTT broker. The MQTT configuration is provided in the optionalmqttsection of the configuration file. MQTT support is disabled if the configuration section is missing. The example below provides a typicalmqttconfiguration section....mqtt:host:<hostname of MQTT broker>user:<login name>password:<my password>device_name:My Digital Memories somwhere in the house...The following parameters are used to configure the MQTT client.ParameterDescriptionhostHostname of the MQTT broker. A value must be specified.portConnection port of MQTT broker. The default is 8883 (standard for secure connections).tlsThe following values are supported. The default istrue.-true: A TLS-encrypted secure connection is used.-false: A non-encrypted connection is used.tls_insecureThe following values are supported. The default isfalse.-true: Insecure TLS connections with non-trusted certificates are permitted.-false: Only secure connections with trusted certificates are permitted.userLogin name. A value must be provided.passwordLogin password. A value must be provided.device_idThe Digital Memories device ID. The default is "pyframe".NoteThe device ID must be unique. A different value must be specified if multiple Pyframe instances connect to the same broker.device_nameThe human friendly device name. The default is  to use thedevice_id.RunningOnce Digital Memories has been configured, you can change into the Digital Memories directory and start the application with the following command:$python3pyframe.pyIn recent distributions you may have to use "python" instead of "python3". Unless configured otherwise, Digital Memories is going to create an index database "index.sqlite" and directory "./log" for log files in the Digital Memories directory. If WebDAV or rclone repositories are configured, Digital Memories will further create a directory "./cache" for temporary storage of downloaded files.For convenience you can install the following script, which will allow you to start the Digital Memories application from anywhere (even SSH sessions). The placeholders  and  evidently need to be replaced with the proper values prior to running the script./usr/local/bin/start-pyframe#!/bin/shUSER=<youruser>SRC=<yourpyframedirectory># May be python or python3 depending on your distributionPYTHON=/usr/bin/python3# Set authority file and active display in case we are starting this script from an SSH session.exportXAUTHORITY=/home/$USER/.XauthorityexportDISPLAY=:0# Change to pyframe source directorycd$SRC# Start pyframeif[$(/usr/bin/whoami)='root'];then/usr/sbin/runuser-ulangweiler--$PYTHONpyframe.pyelse$PYTHONpyframe.pyfiIf you intend to run Digital Memories assystemdservice, you can optionally create a second script for clean up after termination. In this example, we turn off the screen (works only under X11, not Wayland)./usr/local/bin/stop-pyframe#!/bin/shUSER=<youruser># Set authority file and active display in case we are starting this script from an SSH session.exportXAUTHORITY=/home/$USER/.XauthorityexportDISPLAY=:0# Turn backlight off./usr/bin/xsetdpmsforceoffBoth scripts should be owned byroot.rootand need to be executable (mode 750).If you want to start Digital Memories automatically during system boot, you can do so by configuring it in your desktop session manager. Alternatively, you can register asystemdservice via a unit file. Below is an example for a unit file, which uses the two scripts we created before./etc/systemd/system/pyframe.service[Unit]Description=Digital Memories photo frameWants=graphical.targetAfter=graphical.target[Service]Type=simpleExecStart=/usr/local/bin/start-pyframeExecStop=/usr/local/bin/stop-pyframeUser=rootGroup=rootRestart=always[Install]WantedBy=default.targetTheWantsandAfterstatements make sure that we are in graphical mode and that the service is only started after the graphical system has been launched. TheExecStopscript is optional as stated above. It is not required to stop the Digital Memories service. TheRestartstatement ensures that Digital Memories is restarted after unexpected exit. TheWantedBystatement allows to start the service automatically at boot time.Make sure the unit file belongs toroot.root, is readable by the owner and group and writable by the owner only (mode 640). Afterwards you can start the service and verify the successful start via the following commands:$sudosystemctlstartpyframe
$sudosystemctlstatuspyframeTo enable automatic start of the service during boot time issue the following command:$sudosystemctlenablepyframeMake sure to additionally configureautologinfor the user under which you intend to run Digital Memories. Steps for configuration depend on the graphical system and Linux distribution. UnderArmbianyou can use the "armbian-config" tool. OnRaspberry Pi OS, the "raspi-config" tool will do. For other systems/distributions consult the corresponding documentation.Home AssistantGeneral setupDigital Memories implements basic support for integration with theHome Assistanthome automation system. Integration is achieved through the built-in Home AssistantMQTT integration. As an additional pre-requisite, an MQTT broker must be installed (e.g.Eclipse Mosquitto).After the Digital Memories MQTT client has been correctly configured and a connection to the MQTT broker established, Digital Memories should automatically appear as a new device in Home Assistant. The device supports several push buttons and configuration selections, which allow you to control Digital Memories from remote. The device further provides afile sensor, whose value is identical to the UUID of the currently displayed file.In addition, thefile sensorprovides selected file metadata as sensor attributes.Motion activationFor motion activation of the display, thetouch buttonof the Digital Memories device needs to be coupled to a motion sensor via an automation. Every time motion is detected, thetouch buttonis pressed by the automation. Pressing the touch button activates the display and resets the display timeout counter.