2023-08-25 11:36:58 -04:00
import argparse
import datetime
2023-08-25 14:51:12 -04:00
from glob import glob
2023-08-25 11:36:58 -04:00
import json
2023-08-25 14:51:12 -04:00
from listdict import ListDict
2023-08-25 11:36:58 -04:00
import os
# globals
mediadir = " /var/lib/ffplayout/tv-media "
playlistdir = " /var/lib/ffplayout/playlists "
channel = " newellijaytelevision "
verbose = False
from_date = datetime . date . today ( )
to_date = datetime . date . today ( )
2023-08-25 12:35:45 -04:00
playlist_duration = 6 * 60 * 60 # six hours, in seconds
2023-08-25 14:51:12 -04:00
mediadirs = ListDict ( )
2023-08-25 11:36:58 -04:00
def main ( ) :
parse_config ( )
2023-08-25 14:51:12 -04:00
get_media_dirs ( mediadir )
2023-08-25 11:49:39 -04:00
for single_date in daterange ( from_date , to_date ) :
if verbose :
print ( " Processing date " , single_date )
2023-08-25 12:49:59 -04:00
daylist = build_day ( single_date )
daylist_path = playlistdir + " / " + channel + " / " + single_date . strftime ( " % Y " ) + " / " + single_date . strftime ( " % m " ) + " / " + single_date . strftime ( " %d " ) + " / "
if not os . path . isdir ( daylist_path ) :
os . makedirs ( daylist_path )
daylist_file = single_date . strftime ( " % Y " ) + " - " + single_date . strftime ( " % m " ) + " - " + single_date . strftime ( " %d " ) + " .json "
with open ( daylist_path + daylist_file , " w " ) as file :
file . write ( daylist )
if verbose :
print ( ' wrote playlist file ' , daylist_path + daylist_file )
2023-08-25 11:36:58 -04:00
def parse_config ( ) :
2023-08-25 12:35:45 -04:00
global mediadir , playlistdir , channel , verbose , from_date , to_date , playlist_duration
2023-08-25 11:36:58 -04:00
parser = argparse . ArgumentParser (
prog = " mt_clockwheel " ,
description = " a simple clockwheel playlist generator for ffplayout " ,
epilog = " brought to you by your friends at Mountain Town Technology and Community Media Network "
)
parser . add_argument ( ' -d ' , ' --directory ' , dest = ' mediadir ' , help = ' root directory for media library ' )
parser . add_argument ( ' -p ' , ' --playlists ' , dest = ' playlistdir ' , help = ' root directory for playlists ' )
parser . add_argument ( ' -c ' , ' --channel ' , dest = ' channel ' , help = ' channel name to generate playlists for ' )
parser . add_argument ( ' -v ' , ' --verbose ' , action = ' store_true ' , help = ' provide verbose output logging ' )
parser . add_argument ( ' -f ' , ' --from ' , dest = ' from_date ' , help = ' first date to generate playlist for ' )
parser . add_argument ( ' -t ' , ' --to ' , dest = ' to_date ' , help = ' last date to generate playlist for ' )
2023-08-25 12:35:45 -04:00
parser . add_argument ( ' -l ' , ' --length ' , dest = ' playlist_duration ' , help = ' duration (in seconds) for each playlist - if a factor of 24 * 60 * 60 then playlist will be duplicated to fill 24 hours ' )
2023-08-25 11:36:58 -04:00
args = parser . parse_args ( )
if args . verbose :
verbose = True
if args . mediadir :
mediadir = args . mediadir
if args . playlistdir :
playlistdir = args . playlistdir
if args . channel :
channel = args . channel
if args . from_date :
2023-08-25 11:49:39 -04:00
from_date = datetime . datetime . strptime ( args . from_date , " % Y- % m- %d " ) . date ( )
2023-08-25 11:36:58 -04:00
if args . to_date :
2023-08-25 11:49:39 -04:00
to_date = datetime . datetime . strptime ( args . to_date , " % Y- % m- %d " ) . date ( )
2023-08-25 12:35:45 -04:00
if args . playlist_duration :
playlist_duration = args . playlist_duration
2023-08-25 11:36:58 -04:00
if verbose :
print ( " Arguments parsed, config: " )
print ( " mediadir: " , mediadir )
print ( " playlistdir: " , playlistdir )
print ( " channel: " , channel )
print ( " from_date: " , from_date )
print ( " to_date: " , to_date )
2023-08-25 14:51:12 -04:00
def get_media_dirs ( rootdir ) :
for file in os . listdir ( rootdir ) :
if file == " Commercials " :
pass
elif file == " Television " :
get_media_dirs ( os . path . join ( rootdir , file ) )
else :
d = os . path . join ( rootdir , file )
if os . path . isdir ( d ) :
if verbose :
print ( " adding " + d + " to media dirs " )
mediadirs . add_item ( d )
2023-08-25 11:49:39 -04:00
def build_day ( this_date ) :
2023-08-25 12:35:45 -04:00
d = { } # empty dict that will become our JSON output
d [ " channel " ] = channel
d [ " date " ] = this_date . strftime ( " % Y- % m- %d " )
d [ " program " ] = [ ] # empty list to populate with programs
total_time = 0
2023-08-25 14:51:12 -04:00
get_commercial = False
2023-08-25 12:35:45 -04:00
while total_time < playlist_duration :
2023-08-25 14:51:12 -04:00
entry , length = get_playlist_entry ( get_commercial )
2023-08-25 12:35:45 -04:00
d [ " program " ] . append ( entry )
total_time + = length
2023-08-25 14:51:12 -04:00
if length > 0 :
get_commercial = not get_commercial
2023-08-25 12:35:45 -04:00
if verbose :
print ( ' added program: ' , json . dumps ( entry ) , length )
# TODO: see if playlist_duration is a factor of 24 * 60 * 60 and, if so, duplicate it to fill 24 hours
2023-08-25 12:49:59 -04:00
playlist = json . dumps ( d )
2023-08-25 12:35:45 -04:00
if verbose :
2023-08-25 12:49:59 -04:00
print ( " playlist json: " , playlist )
return playlist
2023-08-25 12:35:45 -04:00
2023-08-25 14:51:12 -04:00
def get_playlist_entry ( get_commercial ) :
exts = [ ' *.mp4 ' , ' *.webm ' , ' *.mov ' ]
entry_dir = mediadir + ' /Commercials ' if get_commercial else mediadirs . choose_random_item ( )
media_files = ListDict ( )
found_media = [ f for ext in exts
for f in glob ( os . path . join ( entry_dir , ' ** ' , ext ) , recursive = True ) ]
for d in found_media :
media_files . add_item ( d )
this_file = media_files . choose_random_item ( ) if media_files . length ( ) > 0 else " "
if this_file == " " :
return " " , 0 # get out of this oopsie situation and try again
# TODO: ffprobe file for duration
2023-08-25 12:35:45 -04:00
entry = {
" in " : 0 ,
" out " : 300 ,
" duration " : 300 ,
2023-08-25 14:51:12 -04:00
" source " : this_file
2023-08-25 12:35:45 -04:00
}
2023-08-25 14:51:12 -04:00
if get_commercial :
entry [ " category " ] = " advertisement "
2023-08-25 12:35:45 -04:00
length = entry [ " duration " ]
return entry , length
2023-08-25 11:49:39 -04:00
# generator function to yield single dates from a date range
def daterange ( start_date , end_date ) :
for n in range ( int ( ( end_date - start_date ) . days ) + 1 ) : # adding 1 to make the range inclusive
yield start_date + datetime . timedelta ( n )
2023-08-25 11:36:58 -04:00
if __name__ == " __main__ " :
main ( )