This script will spit out 24 playlists (adjustable) with songs in random order, you can fill in if you want the songs that played the past few days (adjustable) in this script it is 4 but you can make it longer. It puts a random jingle from a specific directory on top of the list and the rest of the tracks is taken from a music map, make sure you have enough songs to pick from or adjust the not played counter to less. I made this script to be able to have a small form of clockwork rotation on my automated vdj.
It makes use of the history folder and the playlist in it, it leaves out songs that are played today one day ago or more...
If you want to make your own adjustments to this script let chatgpt analyze it and change it to what works good in your situation.
summary;
- it analyses the maps for jingles and music and history
- it puts a jingle on top
- it fills the playlist in random order with tracks that have not been played for x days
- it gives one or more playlists according to what you want
script:
Hopefuly it helps someone, save it as .py file and execute it with the windows task scheduler and execute it daily so you have fresh playlists every day. In order to make it work good you need to refresh your browser before you will load them or else vdj will go and use the old ones, that is done by this code
browser_gotofolder "C:\ & browser_refresh
greetz
It makes use of the history folder and the playlist in it, it leaves out songs that are played today one day ago or more...
If you want to make your own adjustments to this script let chatgpt analyze it and change it to what works good in your situation.
summary;
- it analyses the maps for jingles and music and history
- it puts a jingle on top
- it fills the playlist in random order with tracks that have not been played for x days
- it gives one or more playlists according to what you want
script:
import os
import random
from datetime import datetime, timedelta
def read_m3u_list(m3u_file):
"""Read an M3U playlist and return a set of files."""
excluded_files = set()
if os.path.isfile(m3u_file):
with open(m3u_file, "r", encoding="utf-8") as file:
for line in file:
line = line.strip()
if line and not line.startswith("#"):
excluded_files.add(line)
return excluded_files
def read_history_files_by_name(history_folder, days_to_exclude=1):
"""Read M3U playlists from the History folder by filename date and return a set of excluded files."""
excluded_files = set()
if not os.path.isdir(history_folder):
print(f"The history folder does not exist: {history_folder}")
return excluded_files
cutoff_date = datetime.now() - timedelta(days=days_to_exclude)
for file in os.listdir(history_folder):
file_path = os.path.join(history_folder, file)
# Check for M3U files and parse date from filename
if file.endswith(".m3u") and os.path.isfile(file_path):
try:
file_date = datetime.strptime(file[:10], "%Y-%m-%d") # Extract date from filename
if file_date >= cutoff_date:
excluded_files.update(read_m3u_list(file_path))
except ValueError:
print(f"Skipping file with invalid date format: {file}")
return excluded_files
def generate_m3u_playlists(folder_path, special_folder, output_folder, history_folder, num_playlists=24, days_to_exclude=4):
# Supported audio file extensions
supported_extensions = {".mp3", ".wav", ".flac", ".aac", ".ogg", ".m4a"}
# Check if folders exist
if not os.path.isdir(folder_path):
print(f"The specified folder does not exist: {folder_path}")
return
if not os.path.isdir(special_folder):
print(f"The special folder does not exist: {special_folder}")
return
if not os.path.isdir(output_folder):
os.makedirs(output_folder)
if not os.path.isdir(history_folder):
print(f"The history folder does not exist: {history_folder}")
return
# Read files from the History folder to exclude by filename date
excluded_files = read_history_files_by_name(history_folder, days_to_exclude=days_to_exclude)
# Collect all audio files from the main folder
audio_files = [
os.path.join(folder_path, file)
for file in os.listdir(folder_path)
if os.path.splitext(file)[1].lower() in supported_extensions
and os.path.join(folder_path, file) not in excluded_files
]
# Collect all audio files from the special folder (do not analyze history for these)
special_files = [
os.path.join(special_folder, file)
for file in os.listdir(special_folder)
if os.path.splitext(file)[1].lower() in supported_extensions
]
if not special_files:
print("No special audio files found in the special folder.")
return
# Always use the same jingle as the special track (first file in the folder)
special_track = special_files[0] # Always pick the first file from the special folder
if not audio_files:
print("No audio files found in the specified folder.")
return
# Shuffle the audio files
random.shuffle(audio_files)
# Distribute files across playlists
chunk_size = len(audio_files) // num_playlists
for i in range(num_playlists):
# Distribute the remaining tracks across playlists
playlist_files = audio_files[i * chunk_size: (i + 1) * chunk_size]
if i == num_playlists - 1: # Add leftover tracks to the last playlist
playlist_files += audio_files[(i + 1) * chunk_size:]
# Add the special track at the top
playlist_files.insert(0, special_track)
# Generate the playlist name
playlist_name = os.path.join(output_folder, f"playlist_{i + 1}.m3u")
# Write the playlist to a file
with open(playlist_name, "w", encoding="utf-8") as m3u:
m3u.write("#EXTM3U\n") # M3U header
for file in playlist_files:
m3u.write(f"{file}\n")
print(f"Playlist generated: {playlist_name}")
# Parameters
folder_path = r"C:\Muziek\POP" # Folder with audio files
special_folder = r"C:\Muziek\r2 jingles" # Folder with special audio files
output_folder = r"C:\Muziek\Playlist VDJ" # Folder to save playlists
history_folder = r"C:\Users\xxxx\AppData\Local\VirtualDJ\History" # Folder with previous playlists
# Generate playlists
generate_m3u_playlists(folder_path, special_folder, output_folder, history_folder)
Hopefuly it helps someone, save it as .py file and execute it with the windows task scheduler and execute it daily so you have fresh playlists every day. In order to make it work good you need to refresh your browser before you will load them or else vdj will go and use the old ones, that is done by this code
browser_gotofolder "C:\ & browser_refresh
greetz
Posted Sun 19 Jan 25 @ 2:38 am
in order to get a weekly rotation on your scheduler, make schedules for day 1 till 7 and make bridge schedules for taking the scripts over the 00:00 point (i first tryed to do it without, but in some way, vdj began executing day 1 to 7 over and over again in periods of minutes). the bridge file would be only having a script executed at 23:59:30 of day1 saying:
wait 35000ms & eventscheduler_start 'day2' (don't ask me why but this stopped the thing i described)
so then you have the actual day1 schedule and the bridgeforday1 schedule and you do that for day2 and so on till you have 14 files and you have a rotation schedule for everyday of the week, and then ofcourse you add all the things to the day1 to 7 schedules, only remember to leave the first few seconds of the day open cause the bridge file takes it in 5 seconds of the day. (not quite a thing these days because it is no fm where all was at the second precise, internet streams always have a few seconds delay so some more do not bother i think)
wait 35000ms & eventscheduler_start 'day2' (don't ask me why but this stopped the thing i described)
so then you have the actual day1 schedule and the bridgeforday1 schedule and you do that for day2 and so on till you have 14 files and you have a rotation schedule for everyday of the week, and then ofcourse you add all the things to the day1 to 7 schedules, only remember to leave the first few seconds of the day open cause the bridge file takes it in 5 seconds of the day. (not quite a thing these days because it is no fm where all was at the second precise, internet streams always have a few seconds delay so some more do not bother i think)
Posted Thu 23 Jan 25 @ 9:53 am