Page 1 of 1

Author:  uncertain [ Sun Aug 02, 2009 11:07 am ]
Post subject:  Random

I have a script I made to play random media files I have stored in various locations. In determining which file to play, first I do an ls of all the directories and append the outputs to file.txt. Then, in order to select a random line from the file (which = one media file), I'm using this bit of code I found somewhere online:
UpperBound=$(cat $file.txt | wc -l)
RandomLine=$(( $LowerBound + ($UpperBound * $RANDOM) / ($RandomMax + 1) ))
filetoplay=$(sed -n "$RandomLine{p;q;}" "$file.txt")

The randomness of this setup is pretty questionable. Out of over 500 media files, I seem to be stuck with the same 30 or 40 over and over. Even when I play in batches using a while/do loop and counting cycles to a predetermined number, I can end up with duplicate plays of media files. I believe it's because the $RANDOM variable works between 0-32761, and that math up there isn't enough to sufficiently scale it down to a few hundred.

Some more searching has led me to the fact that $RANDOM can be limited, by using $RANDOM%NN, where NN is a limiting number of your choice. Since it runs from zero to (NN-1), you have to add one to the equation such that (( [ $RANDOM%NN ] +1 )). I'd like to do away completely with much of the previous setup, and cut that process down a lot by, for example, renaming the "UpperBound" variable "max" and using it to limit the $RANDOM output as shown above. The problem is that I keep getting errors or strange outputs when I try to insert a variable into that setup. For example, (( [ $RANDOM%$MAX ] +1 )) just gives a syntax error. Using it like (( [ $RANDOM%${MAX} ] +1 )) gives a count from 0 to 2, with each digit followed by the actual value for the $max variable.

Can someone point me in a direction (either this one or something totally new) that will allow me to limit the output of the $RANDOM variable with the use of a second variable?

Author:  thobbs [ Mon Aug 03, 2009 1:04 am ]
Post subject:  Re: Random

$RANDOM uses the process id as part of the seed, so if you are running the whole script repeatedly, the results may not be too random. The $Rand I use here is a bit better as far as absolute randomness goes. I'm not sure why your modular arithmetic failed, but the code given here produces the expected range.

Rand=`dd if=/dev/urandom count=1 2> /dev/null | cksum | cut -f1 -d" "`
UpperBound=`cat file.txt | wc -l`
let "Range = $UpperBound - $LowerBound + 1"
let "RandomLine = $LowerBound + ($Rand % $Range)"
filetoplay=`sed -n "$RandomLine{p;q;}" "file.txt"`

If you want to generate an entire playlist randomly with no repeated songs, that's a bit more work. You would need to check to see that a song is not already in the playlist before you add it. I hope this helps. Let us know if you want to expand it or would like more explanation.

Author:  uncertain [ Mon Aug 03, 2009 11:00 am ]
Post subject:  Re: Random

Thanks for the reply. I'm going to work that into my script right away. It may take some time to determine if it functions any better, but just looking at it, it seems as though it would. When I first found that bit of code online (I don't remember where, but credit is due to the original author), I had doubts as to whether it would perform well, and was surprised when it did. After the first few runs, I noticed I was already starting to see the same files popping up. That's the thing about random events, though.. even if it was the exact same one a few times in a row, how do you really know it's not random?

I have another post on here about making VLC play a random series of files.. That's the script I'm using this in. The first part of the script searches for the list in a particular location (the top level folder of the categorized media files I'm playing) and if it's not there, it creates it. You mentioned randomness without repeats.. I was going to work on another sed line (I think sed would be the way to go, though I could be wrong) that will, after the line has been chosen to feed to VLC, it would cut the line out of the list. That, of course, would change the number of items in the list, but should be reflected where "cat file.txt | wc -l" changes the upper boundary every time the script is run.


Author:  thobbs [ Thu Aug 06, 2009 1:26 am ]
Post subject:  Re: Random

Yes, credit for the random number generator should be given to James T. Dennis, found here:
Your plan for using sed to cut out the line sounds good -- nice solution!

Another relevant comic:

Author:  uncertain [ Fri Aug 07, 2009 5:12 pm ]
Post subject:  Re: Random

I've been using it in all my variations of the script pretty regularly for a few days now, and I can say I'm quite pleased with how it works compared to my older version. I notice that the higher the upperboundary is (i.e., the more files in a particular category) the less chance there is for repeats. For example, with 20 seasons of The Simpsons with 441 separate episodes, I've yet to notice a single repeat out of running it probably 8 or 9 times. But, with only six seasons of Sanford & Son at around 100 or so episodes, I've had the same episode get played twice in a row.

Thanks for the help. I'll come back and post up the whole script when I get the final sed line worked out that will eliminate repeats all together.

Author:  thobbs [ Thu Aug 13, 2009 10:44 pm ]
Post subject:  Re: Random

But, with only six seasons of Sanford & Son at around 100 or so episodes ...

That's way too much Sanford & Son, hah.
Thanks for the help. I'll come back and post up the whole script when I get the final sed line worked out that will eliminate repeats all together.

You're quite welcome for the help. Please do post the final script -- you never know who might be interested in it.

Author:  uncertain [ Wed Aug 19, 2009 11:09 am ]
Post subject:  Re: Random

The randomness you provided seems to work a lot better than my old version.

Here is the final product:
# Creates a list of all video files in all selected folders and then
# plays so many random episodes with VLC Media Player.
# Created by Uncertain

# Filenames and paths.
path2=/path/to/folder/two                  #If needed. Add more paths as necessary.
# Check for the list. If it exists, fine.
# If it doesn't exist, create it.
if [ -f $list ]
  echo "List found at $list"
    echo "Episodes list not found. Creating list arranged by season & episode..." &&find $path1 -name '*.avi' -o -name '*.mpg' -o -name '*.mp4' -o -type f -size +20M | sort >> $list && echo "Done. List created at: $list"                             #Copy that command and add more path variables as they're used.
# Set the number of episodes to play.
while  [ $cycles -ne $repeat ]
  echo $cycles
  cycles=$(( $cycles + 1 ))
# Read the list, select one random line.
Rand=`dd if=/dev/urandom count=1 2> /dev/null | cksum | cut -f1 -d" "`
UpperBound=`cat $list | wc -l`
let "Range = $UpperBound - $LowerBound + 1"
let "RandomLine = $LowerBound + ($Rand % $Range)"
episode=`sed -n "$RandomLine{p;q;}" $list`
# open the random episode in VLC, play it fullscreen, and exit.
vlc -vvv --fullscreen "$episode" vlc://quit
# Close the episode count loop...
# ...and then...

That's the skeleton version. It should just be a matter of setting your actual path(s) to the $path variable(s) as needed, deciding where to store the list, and let it rip...

When I was first writing it, I was running it in the terminal often to debug it, hence the periodic echoes of what's going on. These could easily be removed with no ill effects (I think I got all but a couple of them).

Page 1 of 1 All times are UTC - 6 hours
© 2000, 2002, 2005, 2007 phpBB Group •