Replies: 11 comments 78 replies
-
Additionally, this makes the issue of displaying the correct text overlay on paired images (problematic in the current implementation) easy to handle. The script contains the id's of the images that are on the slide. Just collect the info from the db for the displayed image(s) and build the overlay info... |
Beta Was this translation helpful? Give feedback.
-
Jeff, this system makes a lot of sense. I've managed to get helgeerbe's picture frame running on my laptop so I will check out how that system works then maybe add some more specific ideas. I think getting a savable list (probably as sqlite db) makes a lot of sense rather than constructing it from scratch each time the program runs, especially as we are already doing that for the geo location description. We would need to address questions like: how to copy with files being deleted, moved or directories being renamed as well as pairs where one image fell within a selection criterion and the other one outside. Though none of those are too tricky to solve. Splitting the code to build the Another thing that has cropped up that might (or might not!) be worth thinking about at this stage is enabling animated (probably only GIF, not 'live photos' as taken on phones which are basically just 1.5s mp4 videos) |
Beta Was this translation helpful? Give feedback.
-
Jeff, some more thought on helgeerb's hit helgeerbe/picframe#5 |
Beta Was this translation helpful? Give feedback.
-
In case there's any interest, I knocked up a first pass at storing basic image info in a SQLite db. The source can be found here. To test it, tweak the defined That should load the data for all files found in the defined folder structure into a SQLite db ( Further runs (with no changes to the file system) are nearly instantaneous. Currently, the code is very methodical, and does things in a step-by-step fashion. While I'm sure there are more clever ways to approach this, the current method is easy to follow and seems quite performant. Anyway, it's really just an experiment and not production code by any stretch. But, I think it should give some idea of what might be possible here, and provide some metric on the performance of such a cache system... |
Beta Was this translation helpful? Give feedback.
-
Jeff, that looks really good, thanks - I will have a more thorough look later but having the path split out and in anther table is sensible. I've now brought the version at github.com/helgeerbe/picture_frame nearly up to the same functionality as PictureFrame. I've used a very simple txt file storage which would be easy to swap over to sqlite as per your code or something similar. The two issues we probably have to think about (neither insoluble but probably possible to do well v. badly) a) the location descriptions from nominatim/OSM need to be obtained at an absolute maximum rate of 1 request per second, so this would either need to be filled in as each image is shown or else as a paced background job. The info isn't needed for any selection etc so could be done when the images show. b) getting the show to run from a db SELECT would be nice but I can't see how to do that and allow the cursor to move back so we probably have to run the show from a python list of index values to db tables and read each record as it's shown. It's still much better than doing the current way of getting the full os file list then filtering at each next_image. Thanks again. Paddy |
Beta Was this translation helpful? Give feedback.
-
@paddywwoof - A quick update on my SQLite caching experiments... First, I've broken the data storage down into a more normalized set of tables and a single view. ATM, those look like this...
So, the tables each contain minimal, raw data about each "thing" and the single view pulls all that data together into one place for easy access. With this setup, the view can easily be augmented with additional columns that are deemed helpful. For example, the above Related, I've read through the discussions associated with this recent PR (really interesting stuff BTW). I don't envy you (@paddywwoof) having to deal with all the recent submissions to the code-base as well as your own, on-going rewrite. That's a tough balancing act... Anyway, related to some of those discussions, I wanted to pass along some additional performance metrics of my current SQLite cache.
Also, I'm confident that some additional speed can be squeezed out of the cache-build process. I'm currently experimenting with that. Anyway, I feel the above is likely performant enough that complicating the application with threaded updates, or a build-as-you-go cache, or other complex mechanisms might not be worth the trouble, though YMMV... I'm curious what others think? I'll try to post my code updates soon in case they're interesting to someone. |
Beta Was this translation helpful? Give feedback.
-
On Mon, Feb 1, 2021 at 11:49 PM paddywwoof ***@***.***> wrote:
Jeff, not only is that more elegant but it's actually faster. For a list
of 10,000 images of which 1,000 are portrait, running on an RPi3 it takes
16ms and the other two 18ms. So speed is academic really and we should just
choose your design as it looks nicer - like Harold Ableson said: programs
are essentially for people to read not computers to run.
Though there is cost of calling each function in python the len() is
pretty cheap as the list has it's length as an integer ready to be read.
The only thing I might change is to if len(prlist) > 0: using different
types that happen to evaluate to True or False reminds me too much of the
bad old days of completely opaque C and javascript!!
Another quibble: neither is Pythonic!
If one were Guido one would write it this way:
if inlist[i] != ('<pair>',):
newlist.append(inlist[i])
elif prlist:
elem = prlist.pop(0)
if prlist:
elem += prlist.pop(0)
newlist.append(elem)
where you just say if prlist - it's a little faster, but also, more
idiomatic Python.
Going back to lurk here. :-D
…
|
Beta Was this translation helpful? Give feedback.
-
First version of the system with ImageCache system. see comment on helgeerbe repo. And changes on mine |
Beta Was this translation helpful? Give feedback.
-
OK, I did a little research on starting startx/xinit in systemd as non root requires: Change
On my pi3 I will never get the images diplayed when starting with startx or xinit |
Beta Was this translation helpful? Give feedback.
-
Time for some eye candy. My actual Homeassistant integration. What's missing is the location_filter. @paddywwoof I pulled your development branch and merged it. So it should be easy to re-merge with my changes.
|
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
I've had a few discussions recently with @paddywwoof regarding an upcoming refactor of the PictureFrame2020 code base and the possible introduction of a SQLite-based caching / storage mechanism. I've been giving this some thought recently and wanted to record some of that here.
In my (admittedly limited) experience with PictureFrame2020, one of the biggest misses I see is the lack of any persistent storage of image information. Because nothing is stored, it needs to be recollected each time the software is started. Since the data collection is (potentially) slow, the code is complicated by the fact that it needs to sometimes contend with missing information.
For example, there's an option to pre-load or not all EXIF information (
--delay-exif
) due to the time it takes to load that information at startup. Then, other parts of the code are required to do different things depending on whether the EXIF info has been preloaded. The recent "portrait pairs" feature I introduced was complicated by this option.In my view, a persistent image cache would help to normalize some of these issues, as the code could just expect the info to exist at the time of image presentation and not need varying code paths to deal with missing info.
In that regard, I see SQLite as a perfect mechanism to support such a cache. It's light-weight, incredibly fast, and requires no installation. And, once it's in place, it's just so useful as the underpinnings of future features and enhancements.
For a first, simple use, I see it working something like this:
id
andpaired_id
). Here, the image that appears aspaired_id
would simply be removed from the original script so it only appears once.To better explain that, let's say we have 10 images in our slideshow - and we're simply going to show them "in order". The script would be a list of id's such as (horizontal for brevity):
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
Now, during the "script preparation" phase, we'd make a pass through the collection and attempt to "pair images together" as necessary (to display portrait images in pairs, for example). That could create a script that looks like this:
id=1, paired_id=3
id=2, paired_id=null
id=4, paired_id=7
id=5, paired_id=null
id=6, paired_id=null
id=8, paired_id=9
id=10, paired_id=null
After this pairing pass, the script only contains instructions for 7 slides (3 of which are now pairs).
So, to recap...
Here, all the magic (whatever we deem that to be) happens in the script preparation. The slideshow just faithfully follows a pre-prepared script...
Granted, this is an intentionally simplistic view of the current system, but I hope to spark some discussion.
Beta Was this translation helpful? Give feedback.
All reactions