Articles

Solved Improving a batch script to play random videos in a folder?

January 15, 2013 at 09:40:44
Specs: Windows 7

Hello, couple of months ago, a very helpful person by the name of Razor2.3 helped me with a batch that when executed, it will look into each folder of my shows, and from those shows randomly choose a video and then continue with the next folder and randomly pick a show and so forth.

The batch would output an m3u playlist file and all I would have to do is to click the batch X amount of times and generates X amount of m3u playlists and all I would have to do is play that in my Windows media player without having to manually pick each episode for each show. (btw, I am using windows 7 PC).

The final script was done and it looks like this:

SET extensionList=avi mp4 mkv
SET cnt=0
:Loop
SET /A cnt+=1
IF EXIST %cnt%.m3u GOTO Loop

>%cnt%.m3u ECHO.#EXTM3U
FOR /D %%a IN (c:\somePath\*) DO CALL :PickFile "%%a"
GOTO :EOF

:PickFile
SET searchList=
FOR %%b IN (%extensionList%) DO CALL SET searchList=%%searchList%% "%~1\*.%%b"
FOR /F %%b IN ('2^>NUL DIR /A-D-H-S %searchList% ^| FIND "File(s)"') DO SET limit=%%b
SET /A fileNum=(%random% %% limit) + 1
FOR /F "tokens=2 delims=:" %%b IN ('2^>NUL DIR /A-D-H-S/B %searchList% ^| FINDSTR /N ".*" ^| FINDSTR "^%fileNum%:"') DO ^
CALL :AddList %1 "%%b" >>%cnt%.m3u
GOTO :EOF

:AddList
@ECHO.#EXTINF:-1,%~n2
@ECHO.%~f1\%~2
@GOTO :EOF

After weeks of testing, I found out that more often than not, it seems to repeat some episodes of my shows from my last playlist. (I would generate this playlist X amount of times)

Is there a way to edit this so that I can make sure I don't see a repeated episode from the last playlist? Or to make it even more random? I hope that makes sense, I can clarify even more on the next post. Thank you~

BTW, the original post is here (http://www.computing.net/answers/programming/is-there-a-way-to-play-a-random-video-just-once-in-a-folder/28683.html#xtor=EPR-2)


See More: Improving a batch script to play random videos in a folder?

Report •


✔ Best Answer
January 21, 2013 at 17:24:52

Yeah, I think my post got all crossed up somehow, so heeding Razor's sound advice, I'll put what I thought would solve the problem of "repeat performances" (this is Razor's code, btw, with only the two mods I planted):
:Start
SET extensionList=avi mp4 mkv
SET cnt=0
:Loop
SET /A cnt+=1
IF EXIST %cnt%.m3u GOTO Loop

>%cnt%.m3u ECHO.#EXTM3U
FOR /D %%a IN (c:\somePath\*) DO CALL :PickFile "%%a"
GOTO :EOF

:PickFile
SET searchList=
FOR %%b IN (%extensionList%) DO CALL SET searchList=%%searchList%% "%~1\*.%%b"
:: modification one: count only files with archive attribute turned ON
set limit=0
FOR /F %%b IN ('2^>NUL DIR /A-D-H-SA %searchList% ^| FIND "File(s)"') DO SET limit=%%b
IF %limit% gtr 0 goto :randsel
ECHO No more unplayed files, reset all files?
choice
if %errorlevel% equ 2 goto :eof
cd \somePath
attrib /s +a *.*
:: ===== OPTIONAL: remove old playlists.
del /s *.m3u
goto :start

:randsel
SET /A fileNum=(%random% %% limit) + 1
:: modification 2: include only files with archive attribute turned ON
FOR /F "tokens=2 delims=:" %%b IN ('2^>NUL DIR /A-D-H-SA/B %searchList% ^| FINDSTR /N ".*" ^| FINDSTR "^%fileNum%:"') DO ^
CALL :AddList %1 "%%b" >>%cnt%.m3u
GOTO :EOF

:AddList
@ECHO.#EXTINF:-1,%~n2
@ECHO.%~f1\%~2
:: modification three: "disable" or otherwise "switch off" this file from future inclusions
@ATTRIB -A %~f1\%2
@GOTO :EOF
::====== end

@a11: the other short batch was just a "reset" to turn all the files back on, it was just put there to confuse you! ;-)
Anyway, with any given set of items, any random generator will randomly duplicate values unless those values are somehow removed from the lineup - otherwise it's not "random" for that set. What you want is random plus unique, which means the set must be reduced somehow. It doesn't matter how, you could delete the files, rename the files, move the files to foreign directories, maintain a list, etc. etc. I chose to use the archive-bit, since it's fairly easy to implement using minimal modifications to Razor's working code. As far as I know, there is no random generator that is designed to never duplicate a value, because then it is no longer definable as truly random: it has an agenda, like God: "God does not play dice with the universe" (Albert Einsten)



#1
January 15, 2013 at 20:08:28

This goes back to my original concept: flag the files using "A" attribute to "turn them off":

FOR /F %%b IN ('2^>NUL DIR /A-D-H-S-A %searchList% ^| FIND "File(s)"') DO SET limit=%%b
SET /A fileNum=(%random% %% limit) + 1
FOR /F "tokens=2 delims=:" %%b IN ('2^>NUL DIR /A-D-H-S-A/B %searchList% ^| FINDSTR /N ".*" ^| FINDSTR "^%fileNum%:"') DO ^
CALL :AddList %1 "%%b" >>%cnt%.m3u
GOTO :EOF

:AddList
@ECHO.#EXTINF:-1,%~n2
@ECHO.%~f1\%~2
@ATTRIB -A "%~1\%~2"
@GOTO :EOF
::======= end
i might have some things wrong (Razor's code is usually above my head), but this give you the gist. You could also use H or S attributes instead of A (which is somewhat more volatile), with some modifications to the criteria in the DIR: -H-S but that would only work if there's no H or S files in the dir. OR, you could move them to another directory, but that's probably more trouble.
Status can be checked: dir /s /b /a-a
to show all the ones that have been played.


Report •

#2
January 20, 2013 at 13:50:12

Hello nbrane, when I add your script and run it, I get a Divide by zero error at SET /A fileNum=(%random% %% limit) + 1

When I look at it through cmd prompt, I see the random replaced by a long number string. Am I doing something wrong?


Report •

#3
January 20, 2013 at 20:06:26

Sorry, my bad completely. This line is wrong (dash preceding the "A"):
FOR /F %%b IN ('2^>NUL DIR /A-D-H-S-A %searchList% ^| FIND "File(s)"') DO SET limit=%%b

(remove the dash in front of A) change it to:
FOR /F %%b IN ('2^>NUL DIR /A-D-H-SA %searchList% ^| FIND "File(s)"') DO SET limit=%%b

You want to find the files with "A" ON, not OFF as my screwup had it.

This batch resets all files to "ON" (archive attribute enabled):
::===== reset.bat
@echo off & setlocal
SET extensionList=avi mp4 mkv
for %%a in (extensionlist) do attrib /s +a *.%%a
::==== end batch


Report •

Related Solutions

#4
January 21, 2013 at 05:20:43

You might want to paste the whole script, nbrane. Also, your "fix it" script doesn't work on files in folders, which the play list generating script does.

How To Ask Questions The Smart Way


Report •

#5
January 21, 2013 at 07:41:23

Thank you for the quick response. I tried to add the new correction with A-D-H-SA with the modified :
:===== reset.bat
@echo off & setlocal
SET extensionList=avi mp4 mkv
for %%a in (extensionlist) do attrib /s +a *.%%a
::==== end batch

I get no errors this time but the following *.m3u contains no files. When I viewed them the only thing that is in the *.m3u file is #EXTM3U.

This is what I tried to use edited.bat:

SET /A cnt+=1
IF EXIST %cnt%.m3u GOTO Loop


>%cnt%.m3u ECHO.#EXTM3U
FOR /D %%a IN (c:\testing\*) DO CALL :PickFile "%%a"
GOTO :EOF

:PickFile
SET searchList=
FOR /F %%b IN ('2^>NUL DIR /A-D-H-SA %searchList% ^| FIND "File(s)"')

DO SET limit=%%b
SET /A fileNum=(%random% %% limit) + 1
FOR /F "tokens=2 delims=:" %%b IN ('2^>NUL DIR /A-D-H-S-A/B

%searchList% ^| FINDSTR /N ".*" ^| FINDSTR "^%fileNum%:"') DO ^
CALL :AddList %1 "%%b" >>%cnt%.m3u
GOTO :EOF

::===== reset.bat
@echo off & setlocal
SET extensionList=avi mp4 mkv
for %%a in (extensionlist) do attrib /s +a *.%%a
::==== end batch


Report •

#6
January 21, 2013 at 12:34:41

To experiment with the randomness of Razor2.3's script, I made a folder with 10 videos labeled 1 to 10 and I ran the script 30 times.
1. 5 11. 7 21. 2
2. 9 12. 1 22. 5
3. 5 13. 3 23. 8
4. 9 14. 1 24. 2
5. 5 15. 3 25. 8
6. 9 16. 6 26. 10
7. 2 17. 3 27. 5
8. 5 18. 3 28. 8
9. 2 19. 9 29. 10
10.5 20. 3 30. 4

For each sets of 10, some seem to alternate instead of being truly random. Yes I know I'm geeking it out but I'm so fascinated with this script and I tried to replace the '2's and 'n2' with 3 and ran it 30 times as well:

1. 3 11. 2 21. 4
2. 1 12. 5 22. 1
3. 3 13. 8 23. 4
4. 6 14. 2 24. 1
5. 1 15. 8 25. 3
6. 3 16. 2 26. 7
7. 6 17. 5 27. 3
8. 9 18. 8 28. 6
9. 3 19. 5 29. 1
10. 9 20. 8 30. 3

Here it seems like they alternate every 3rd... I'm trying to understand it myself so I can try to figure it out without bugging you guys to death but it's confusing me hehe.


Report •

#7
January 21, 2013 at 12:58:33

I'm pretty sure CMD just uses the bog standard rand(), and that implementation is pretty well documented.

EDIT: Yep, it is.

How To Ask Questions The Smart Way


Report •

#8
January 21, 2013 at 14:02:16

Fascinating.. so would using 'for /l %i in (1,1,300) do @(pause&echo %RANDOM%)' in your script improve this?

This is getting interesting hehe.


Report •

#9
January 21, 2013 at 14:25:21

You know after reading those 2 threads, I learned a ton of things. What I was doing this whole time for the past 2 months was creating a huge playlist within 1 second or less than 1 second apart of each other. And from reading the 2nd thread, I learned that it is more than likely that each generated number was using the same seed and/or the same timestamp which was resulting in less than random numbers.

To further prove this, I ran the original script again but this time at 5 seconds apart and ran it 30 times again. This is what I came up with:

1. 2 11. 8 21. 8
2. 4 12. 4 22. 1
3. 4 13. 7 23. 3
4. 1 14. 1 24. 2
5. 3 15. 9 25. 8
6. 9 16. 5 26. 8
7. 2 17. 8 27. 7
8. 8 18. 4 28. 7
9. 7 19. 10 29. 3
10. 4 20. 1 30. 9

To compare this, I went to random.org to generate the same numbers 30 times 10 sets each and I got almost the same variation.

In conclusion, I should wait even more time to disperse the numbers instead of trying to generate each playlist so quickly. This should almost guarantee the randomness of my playlists.

Thanks again, Razor2.3 and nbrane for the hints, suggestions, and the script itself. I think I'm going to re-study C++ again~ Cheers ^_^


Report •

#10
January 21, 2013 at 14:36:47

aoneone: Fascinating.. so would using 'for /l %i in (1,1,300) do @(pause&echo %RANDOM%)' in your script improve this?
That'd only reduce your entropy. (entropy = perceived randomness)

EDIT: Fixed link. CN does not like the linked site.

How To Ask Questions The Smart Way


Report •

#11
January 21, 2013 at 17:24:52
✔ Best Answer

Yeah, I think my post got all crossed up somehow, so heeding Razor's sound advice, I'll put what I thought would solve the problem of "repeat performances" (this is Razor's code, btw, with only the two mods I planted):
:Start
SET extensionList=avi mp4 mkv
SET cnt=0
:Loop
SET /A cnt+=1
IF EXIST %cnt%.m3u GOTO Loop

>%cnt%.m3u ECHO.#EXTM3U
FOR /D %%a IN (c:\somePath\*) DO CALL :PickFile "%%a"
GOTO :EOF

:PickFile
SET searchList=
FOR %%b IN (%extensionList%) DO CALL SET searchList=%%searchList%% "%~1\*.%%b"
:: modification one: count only files with archive attribute turned ON
set limit=0
FOR /F %%b IN ('2^>NUL DIR /A-D-H-SA %searchList% ^| FIND "File(s)"') DO SET limit=%%b
IF %limit% gtr 0 goto :randsel
ECHO No more unplayed files, reset all files?
choice
if %errorlevel% equ 2 goto :eof
cd \somePath
attrib /s +a *.*
:: ===== OPTIONAL: remove old playlists.
del /s *.m3u
goto :start

:randsel
SET /A fileNum=(%random% %% limit) + 1
:: modification 2: include only files with archive attribute turned ON
FOR /F "tokens=2 delims=:" %%b IN ('2^>NUL DIR /A-D-H-SA/B %searchList% ^| FINDSTR /N ".*" ^| FINDSTR "^%fileNum%:"') DO ^
CALL :AddList %1 "%%b" >>%cnt%.m3u
GOTO :EOF

:AddList
@ECHO.#EXTINF:-1,%~n2
@ECHO.%~f1\%~2
:: modification three: "disable" or otherwise "switch off" this file from future inclusions
@ATTRIB -A %~f1\%2
@GOTO :EOF
::====== end

@a11: the other short batch was just a "reset" to turn all the files back on, it was just put there to confuse you! ;-)
Anyway, with any given set of items, any random generator will randomly duplicate values unless those values are somehow removed from the lineup - otherwise it's not "random" for that set. What you want is random plus unique, which means the set must be reduced somehow. It doesn't matter how, you could delete the files, rename the files, move the files to foreign directories, maintain a list, etc. etc. I chose to use the archive-bit, since it's fairly easy to implement using minimal modifications to Razor's working code. As far as I know, there is no random generator that is designed to never duplicate a value, because then it is no longer definable as truly random: it has an agenda, like God: "God does not play dice with the universe" (Albert Einsten)


Report •

#12
January 21, 2013 at 18:13:57

Nbrane this is amazing~ I ran your modified script 10 times and this time it made sure not to repeat any of the 10 shows I was testing.

However, from the 11th show and on, there were nothing in the playlist.

Is there a way to tell it to restart over again after everything has been played once in that folder? Or would I have to make a 2nd batch file to turn all attributes back on?

I tried to put the reset code you posted earlier but I'm still having trouble... ~

Very fascinating.^_^


Report •

#13
January 21, 2013 at 19:44:02

In the interest of the KISS principle, I suggest the following:
attrib /s -a c:\somePath\*

How To Ask Questions The Smart Way


Report •

#14
January 21, 2013 at 19:58:40

Well, as they get "scratched off", eventually there will be none, then you need to "reset". I tried to build the reset function into the main batch (in resp #11). See if that might work...

@Razor: yeah, I noticed i didn't need the extra stuff.


Report •

#15
January 21, 2013 at 20:30:40

Thanks for the quick response nbrane! ^_^

I tried the new build from #11 and couple of things happen:

I get the prompt for No more unplayed files, reset all files? [Y,N]

If I press Y or N, it will prompt me the same question forever regardless if I press yes or no, and the first output contains nothing except for #EXTM3U.

If I close the window, and try the 2nd time, it outputs the 2nd playlist, but if I press Y or N, the 2nd playlist will disappear, it seems to be deleted. I checked before it got deleted and still contains nothing except for #EXTM3U.

UPDATE:

nbrane, I found something very strange, can you explain this to me?

When I run your original modified script here:
SET extensionList=avi mp4 mkv mpg
SET cnt=0
:Loop
SET /A cnt+=1
IF EXIST %cnt%.m3u GOTO Loop

>%cnt%.m3u ECHO.#EXTM3U
FOR /D %%a IN (c:\testing\*) DO CALL :PickFile "%%a"
GOTO :EOF

:PickFile
SET searchList=
FOR %%b IN (%extensionList%) DO CALL SET searchList=%%searchList%% "%~1\*.%%b"

:: modification one: count only files with archive attribute turned ON
FOR /F %%b IN ('2^>NUL DIR /A-D-H-SA %searchList% ^| FIND "File(s)"') DO SET limit=%%b
SET /A fileNum=(%random% %% limit) + 1

:: modification 2: include only files with archive attribute turned ON
FOR /F "tokens=2 delims=:" %%b IN ('2^>NUL DIR /A-D-H-SA/B %searchList% ^| FINDSTR /N ".*" ^| FINDSTR "^%fileNum%:"') DO ^
CALL :AddList %1 "%%b" >>%cnt%.m3u
GOTO :EOF

:AddList
@ECHO.#EXTINF:-1,%~n2
@ECHO.%~f1\%~2

:: modification three: "disable" or otherwise "switch off" this file from future inclusions
@ATTRIB -A %~f1\%2
@GOTO :EOF
::====== end

and run it 10 times, it outputs 10 video files all randomly once.

Then when I run the #11 build, and this time press Y for [Y,N] it deletes all the playlists, so then I run the modified one I pasted above again, it plays all 10 files all randomly and without repeating!

I don't know what happened during that #11 build, does it basically turn all the attrib back on again?

2nd update:

So this time, I tried to test it out on my external drive, which contains 27 shows with episodes ranging from 24 episodes to over 100+. When I run the modified script posted above, it runs beautifully, all different episodes each playlist, but when I run the #11 build, and I press Y for the [Y,N] prompt, it seems to remove the last 2 shows of the list. Not that I'm complaining, because I can just run the modified build mentioned earlier and that does the trick.

It's just I'm thinking that after the 24th playlist, I should run the #11 build so that the show that contains only 24 episodes gets reset back and then I just run the modified one from above?

I hope that didn't sound too confusing LOL.

nbrane this is coming out beautifully I'm loving it more and more~ ^_^


Report •

#16
January 21, 2013 at 21:16:25

Ah, uh, again, my bad. %errolevel% won't work inside code-block. Let me adjust that in resp #11 with a "goto" and a label to keep %errorlevel% outside code-block. (!errorlevel! will work inside code-block with delayedexpansion, but i don't remember what status of delayedexpansion is, so...) I think that's the only problem: due to my mistake, yes, it resets all the files. %errorlevel% is always zero, so it resets all the files to "unplayed", regardless of your choice of y/n. The deletion of the m3u files is optional. You can disable or remove that line if you don't want it. For whatever reasons, you may want to keep them but i saw no reason so i put that part in. #11 "build" will hopefully get you "home", without having to run multiple batch's.
(ps: and, yes, that was confusing. That's why I want to fix the main problem. KISS is our friend, bandaids and rubber-bands and scotch-tape are our downfall.)

Report •

#17
January 21, 2013 at 21:44:00

Amazing nbrane, just pure genius~ ^_^ After testing again, it looks really solid!

I tested out a small version of what I was trying to explain earlier. Let's say for the 1st folder contained 10 videos, and 2nd folder 5 videos.

On the 6th batch run, it will prompt me the reset [Y,N] because now the 2nd folder has no more videos to play.

On my larger scale harddrive, one of my folders has 24 episodes. So after the 25th playlist, I will be prompted and then start all over. Basically it's whatever lowest episode # I have as the largest playlist count I can make.

I have to be aware that when this happens, any other of my shows with episodes greater than 24 now have a chance to repeat themselves because now the cycle has been reset no?

I assume the best way to prevent this from happening, is to combine other small episode shows so that the amount of episodes for each show stay relatively the same around 60 to 100 episodes for each show folder to ensure great variations! That way, when let's say after the 60th playlist (IF I ever get that high), resets back to 0, I can be sure that the probability for any shows greater than 60 now has a lesser chance of repeating again... I hope that made better sense LOL ^_^

Anyways, you and Razor2.3 are just amazing! Thank you two for helping me so much during the past couple of days. I've learned many things here than I could have ever learned during my early semesters of programming hehe.

I will set the #11 response as the best answer and again thanks again nbrane and Razor2.3! ~Cheers


Report •


Ask Question