Sample Header Ad - 728x90

Looking for slideshow utility with custom/configurable randomisation

0 votes
1 answer
55 views
I'm looking for a way to provide custom/configurable randomisation to a slideshow tool like impressive or feh (something lightweight I can run automatically at startup). Basically I need to weight certain directories according to how many photos there are in each. Like, if there are two directories and one contains 90 photos and the other contains only 10, the time spent in each directory should depend not only on how many photos there are in total but also on how many directories there are, so somewhere between 10-50% of the time you might be looking at one from the 10 and the remaining 50-90% of the time you might be looking at one from the 90, according to some custom logic/math, rather than simply having a 10/90 split. Essentially I want to set a lower limit on the bias toward any given directory but still maintain some semblance of the relative proportions of each. I might be able to do this in some jury-rigged way, but maybe someone knows of a way to do it out of the box. Is there anything like this or that might accomplish something similar? Thanks! Edit: Following the great advice below I set up the following randomisation function, adding bias toward directories with more photos by adding a coefficient which multiplies against the standing probability to determine how much of it is freed. Then, rather than redistribute probabilities according to fixed amounts, I chose to do so according to the existing 'stakes' on the rest of it. The resulting dynamics are such that those with biases toward losing less tend preferentially to receive the freed probability and are better able to maintain their supply, simply for having more and thus attracting more of what is freed elsewhere, but not in such a way that would never yield to the other directories, which every once in a while come due in accordance with their own, comparatively weaker biases. (The result of the bias calculation is proportional to the percent contribution of a directory to the total number of photos, but normalised around the value for an equal share that would be obtained when all directories contribute equally, such that those above this threshold are represented somewhat less than they would be otherwise, and those below somewhat more.) To the more crucial point, as to how to leverage this functionality with respect to the image/slideshow utility: It interacts with the directory containing the photos being actively used (feh, the only one I could figure out how to get to work (so not fbi) and update its view of the directory as files change (so not impressive)). There is an option to have a sequence of photos active at once, back from when I thought I'd be able to use impressive and get transitions working, but that doesn't seem likely anymore. All the directory and photo selection and the redistribution of probability happens in this python script, once for every image change in the slideshow (and is self-correcting to the system clock, with the hope feh doesn't lose or gain time somehow, so that the two won't eventually desync). I was hoping there might be a formal way to do this somehow, but I'm not sure there is. Anyway, it seems like it works. If anyone sees this and takes offence at the sight of my python or shell scripting don't hesitate to set me right, if you feel like it. I have one more component I need to work out which is to have it execute automatically after startup and establishing a network connection, but that's not so relevant to the question I was asking. But at any rate here is everything so far:
# Slideshow

import os
from datetime import datetime, timedelta
from random import random
import shutil
import time

src_dir = './photos/src'
active_dir = './photos/active'
active_photo_interval = 24

valid_exts = ['.' + e for e in ['jpg', 'jpeg', 'png']]

photos = [[f.path for f in os.scandir(d.path) if f.is_file and os.path.splitext(f.path)[-1] in valid_exts] for d in os.scandir(src_dir) if d.is_dir()]
photos = [p for p in photos if len(p)]
total_members = len(photos)
total_photos = sum(len(p) for p in photos)

members = [
    {
        'prob': [
            i/len(photos)
            , (i + 1)/len(photos)
        ]
        , 'bias': 1 - (len(photos[i])/total_photos - (len(photos[i])/total_photos - 1/total_members)*((total_members - 1)/total_members)**total_members)
        , 'photos': [
            {
                'prob': [
                    k/len(photos[i])
                    , (k + 1)/len(photos[i])
                ]
                , 'path': photos[i][k]
            } for k in range(0, len(photos[i]))
        ]
    } for i in range(0, len(photos))
]


def get_image():
    mrand = random()
    midx = next(i for i,m in enumerate(members) if m['prob']  1:
        freed_prob = (member'prob'  - member['prob']) * member['bias']
        total_standing_prob = sum(m'prob'  - m['prob'] for i,m in enumerate(members) if i != midx)
        for i,m in enumerate(members):
            standing_prob = m'prob'  - m['prob']
            prob_stake = standing_prob/total_standing_prob
            m['prob'] = 0 if i == 0 else members[i - 1]['prob'][1] 
            m'prob'  = 1 if i + 1 == len(members) else m['prob'] + standing_prob + (freed_prob * prob_stake if i != midx else -freed_prob)


    photos = member['photos']
    prand = random()
    pidx = next(i for i,p in enumerate(photos) if p['prob']  1:
        freed_prob = photo'prob'  - photo['prob']
        share_freed_prob = freed_prob/(len(photos) - 1)
        for i,p in enumerate(photos):
            standing_prob = p'prob'  - p['prob']
            p['prob'] = 0 if i == 0 else photos[i - 1]['prob'][1] 
            p'prob'  = 1 if i + 1 == len(photos) else p['prob'] + standing_prob + (share_freed_prob if i != pidx else -freed_prob)
    
    return photo['path']


active_photos_max = 1
active_photos = []
if os.path.isdir(active_dir):
    active_photos = [f.path for f in os.scandir(active_dir) if f.is_file]
else:
    os.mkdir(active_dir)

time_next = datetime.now()
while True:
    time_next = time_next + timedelta(seconds=active_photo_interval)
    active_photos.insert(0, get_image())
    shutil.copy(active_photos, active_dir)

    old_photos = [os.path.join(active_dir, p.split('/')[-1]) for p in active_photos[active_photos_max:]]
    for p in old_photos: os.remove(p)
    active_photos = active_photos[:active_photos_max]

    while datetime.now() < time_next:
        time.sleep(1)
#!/usr/bin/env bash

# Main

SYNC_INTERVAL=$(( 24 * 60 * 60 ))

while true
do
    python ./slideshow.py &
    sleep $SYNC_INTERVAL
    kill $!
    bash ./sync.sh
done
#!/usr/bin/env bash

# Entry/startup

. ./set_vars.sh

bash ./sync.sh
bash ./main.sh &
sleep 2
feh -R 24 -D 24 -Z -F -Y $ACTIVE_DIR
Asked by fjdksflds (1 rep)
Dec 20, 2024, 02:26 PM
Last activity: Dec 23, 2024, 05:39 AM