2023-10-14 19:40:39 -04:00
|
|
|
import cv2
|
2023-10-13 02:35:04 -04:00
|
|
|
import datetime
|
|
|
|
import math
|
|
|
|
import os
|
|
|
|
import random
|
|
|
|
import subprocess
|
2023-10-14 19:40:39 -04:00
|
|
|
#from moviepy.editor import VideoFileClip
|
2023-10-13 02:35:04 -04:00
|
|
|
|
|
|
|
#The channel bug that displays while the channel is playing episodes
|
|
|
|
buglocation = "/media/zella/anime/aaeachannelbug.png"
|
|
|
|
#the shows you would like this channel to play in individual folders under this folder
|
|
|
|
shows = "/media/zella/anime/shows"
|
|
|
|
#the "commercials" to fill up extra time in the hour. no folders, just videos in this folder.
|
|
|
|
commercials = "/media/zella/anime/commercials"
|
|
|
|
#the "station id" video that calls out what the channel is. have fun with it.
|
|
|
|
stationID = "/media/zella/anime/stationid/AAEAStationID.mp4"
|
|
|
|
|
|
|
|
secondsInHour = 3600
|
|
|
|
episodeBlockTime = 1560
|
|
|
|
minimumTime = 30
|
|
|
|
|
|
|
|
def get_next_show_episode(showNumber):
|
2023-10-14 19:40:39 -04:00
|
|
|
if len(lineupStack[showNumber]) == 0:
|
2023-10-13 02:35:04 -04:00
|
|
|
return None
|
|
|
|
else:
|
|
|
|
return lineupStack[showNumber].pop()
|
|
|
|
|
|
|
|
def get_next_commercial():
|
2023-10-14 19:40:39 -04:00
|
|
|
if len(commercialStack) == 0:
|
2023-10-13 02:35:04 -04:00
|
|
|
for file in os.listdir(commercials):
|
|
|
|
commercialStack.append(os.path.join(commercials,file))
|
|
|
|
random.shuffle(commercialStack)
|
|
|
|
print("\nCommercial Stack reshuffled.\n" + "\nCommercial returned from stack at size: " + str(len(commercialStack)) + "\n")
|
|
|
|
return commercialStack.pop()
|
|
|
|
else:
|
|
|
|
print("\nCommercial returned from stack at size: " + str(len(commercialStack)) + "\n")
|
|
|
|
return commercialStack.pop()
|
|
|
|
|
|
|
|
#requires moviepy module. rounded up to nearest whole second, for simplicity.
|
2023-10-14 19:40:39 -04:00
|
|
|
#def get_video_length_in_seconds(videoFile):
|
|
|
|
# clip = VideoFileClip(videoFile)
|
|
|
|
# return math.ceil(clip.duration)
|
|
|
|
|
|
|
|
def get_video_length_in_seconds(video_path):
|
|
|
|
cap = cv2.VideoCapture(video_path)
|
|
|
|
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
|
|
|
frame_rate = cap.get(cv2.CAP_PROP_FPS)
|
|
|
|
video_length = total_frames / frame_rate
|
|
|
|
return math.ceil(video_length)
|
2023-10-13 02:35:04 -04:00
|
|
|
|
|
|
|
def get_remaining_seconds_in_hour():
|
|
|
|
now = datetime.datetime.now()
|
|
|
|
seconds_left_in_hour = 3600 - now.minute * 60 - now.second
|
|
|
|
return seconds_left_in_hour
|
|
|
|
|
|
|
|
#Main Thread starts here
|
|
|
|
|
|
|
|
if os.path.exists("playlist.m3u"):
|
|
|
|
os.remove("playlist.m3u")
|
|
|
|
else:
|
|
|
|
print("\n playlist file does not exist.\n")
|
|
|
|
|
|
|
|
#open file in append mode
|
|
|
|
playlist = open('playlist.m3u',"a")
|
|
|
|
|
|
|
|
#a list of stacks of episode paths
|
|
|
|
lineupStack = []
|
|
|
|
|
|
|
|
#A list of commercials
|
|
|
|
commercialStack = []
|
|
|
|
|
|
|
|
#A list of showNumbers, for use later in shuffling episodes in a round robin manner randomly
|
|
|
|
showNumberList = []
|
|
|
|
|
|
|
|
#initialize show lists
|
|
|
|
showNumber = 0
|
|
|
|
for direc in os.listdir(shows):
|
|
|
|
folder = os.path.join(shows,direc)
|
|
|
|
if os.path.isdir(folder):
|
|
|
|
print("\nOpening show " + str(showNumber) + " folder: " + folder + "\n")
|
|
|
|
showEpisodes = []
|
|
|
|
for file in os.listdir(folder):
|
2023-10-14 19:40:39 -04:00
|
|
|
print(os.path.join(folder,file))
|
|
|
|
showEpisodes.append(os.path.join(folder,file))
|
2023-10-13 02:35:04 -04:00
|
|
|
lineupStack.append(showEpisodes)
|
|
|
|
print("\n Added " + str(len(lineupStack[showNumber])) + " episodes from " + folder + "\n")
|
|
|
|
showNumberList.append(showNumber)
|
|
|
|
showNumber += 1
|
|
|
|
|
2023-10-14 19:40:39 -04:00
|
|
|
#reverse each show stack in the lineupStack list so we start from episode 1
|
|
|
|
for show in lineupStack:
|
|
|
|
show.reverse()
|
2023-10-13 02:35:04 -04:00
|
|
|
|
|
|
|
|
|
|
|
#build season lineup station playlist using schedule:
|
|
|
|
#schedule:
|
|
|
|
#for boot hour
|
|
|
|
#get remaining seconds in hour
|
|
|
|
#if more than 30, stationid, play episode and fill rest with commercials and stationid
|
|
|
|
#if less, stationid and fill with commercials
|
|
|
|
#if more than 55, skip and build normal hour
|
|
|
|
|
|
|
|
#3600 seconds in an hour
|
|
|
|
#timeLeft = 3600
|
|
|
|
|
|
|
|
#In each hour:
|
|
|
|
#-Station ID video plays
|
|
|
|
#-episode (~25 minutes)
|
|
|
|
#-random commercial block (2 minutes)
|
|
|
|
#-Station ID video plays
|
|
|
|
#-random commercial block (2 minutes)
|
|
|
|
#-episode (~25 minutes)
|
|
|
|
#-random commercial block (2 minutes)
|
|
|
|
#-Station ID video plays
|
|
|
|
#-random commercial block (2 minutes)
|
|
|
|
#repeat until out of episodes
|
|
|
|
|
|
|
|
print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
|
|
|
|
print(" Building Playlist ")
|
|
|
|
print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
|
|
|
|
|
|
|
|
|
|
|
|
episodesEmptyFlag = False
|
|
|
|
firstLoop = True
|
|
|
|
while not episodesEmptyFlag:
|
|
|
|
if firstLoop:
|
|
|
|
timeLeft = get_remaining_seconds_in_hour()
|
2023-10-14 19:40:39 -04:00
|
|
|
firstLoop = False
|
2023-10-13 02:35:04 -04:00
|
|
|
else:
|
|
|
|
timeLeft = secondsInHour
|
|
|
|
random.shuffle(showNumberList)
|
|
|
|
showNumberListCount = 0
|
2023-10-14 19:40:39 -04:00
|
|
|
while timeLeft > minimumTime:
|
2023-10-13 02:35:04 -04:00
|
|
|
if timeLeft >= episodeBlockTime:
|
|
|
|
print("Enough time for an episode block")
|
|
|
|
#add station id
|
|
|
|
timeLeft -= get_video_length_in_seconds(stationID)
|
2023-10-14 19:40:39 -04:00
|
|
|
playlist.write(stationID + "\n")
|
2023-10-13 02:35:04 -04:00
|
|
|
|
|
|
|
#add commercial. Maybe add a while loop here to add multiple commercials if one is too short
|
|
|
|
nextAd = get_next_commercial()
|
|
|
|
timeLeft -= get_video_length_in_seconds(nextAd)
|
2023-10-14 19:40:39 -04:00
|
|
|
playlist.write(nextAd + "\n")
|
2023-10-13 02:35:04 -04:00
|
|
|
|
|
|
|
#add tv episode
|
|
|
|
nextEpisode = ""
|
|
|
|
while showNumberListCount < len(showNumberList):
|
|
|
|
nextEpisode = get_next_show_episode(showNumberList[showNumberListCount])
|
|
|
|
if nextEpisode is None:
|
|
|
|
showNumberListCount += 1
|
|
|
|
continue
|
|
|
|
else:
|
|
|
|
showNumberListCount += 1
|
|
|
|
timeLeft -= get_video_length_in_seconds(nextEpisode)
|
2023-10-14 19:40:39 -04:00
|
|
|
playlist.write(nextEpisode + "\n")
|
|
|
|
print("\nEpisode " + nextEpisode + " added to playlist. " + str(len(lineupStack[showNumberList[showNumberListCount - 1]])) + " episodes left in stack\n")
|
2023-10-13 02:35:04 -04:00
|
|
|
|
|
|
|
break
|
|
|
|
if nextEpisode is None:
|
2023-10-14 19:40:39 -04:00
|
|
|
print("Episodes exhausted! Completing Playlist!\n")
|
2023-10-13 02:35:04 -04:00
|
|
|
episodesEmptyFlag = True
|
|
|
|
break
|
2023-10-14 19:40:39 -04:00
|
|
|
|
|
|
|
#add commercial.
|
|
|
|
nextAd = get_next_commercial()
|
|
|
|
timeLeft -= get_video_length_in_seconds(nextAd)
|
|
|
|
playlist.write(nextAd + "\n")
|
|
|
|
|
|
|
|
#add commercial.
|
|
|
|
nextAd = get_next_commercial()
|
|
|
|
timeLeft -= get_video_length_in_seconds(nextAd)
|
|
|
|
playlist.write(nextAd + "\n")
|
|
|
|
|
2023-10-13 02:35:04 -04:00
|
|
|
else:
|
2023-10-14 19:40:39 -04:00
|
|
|
#no time for furtur episodes this hour
|
|
|
|
print("Not enough time for another episode this hour. Padding")
|
|
|
|
|
|
|
|
#add station id
|
|
|
|
timeLeft -= get_video_length_in_seconds(stationID)
|
|
|
|
playlist.write(stationID + "\n")
|
|
|
|
|
|
|
|
#add commercial.
|
|
|
|
nextAd = get_next_commercial()
|
|
|
|
timeLeft -= get_video_length_in_seconds(nextAd)
|
|
|
|
playlist.write(nextAd + "\n")
|
|
|
|
|
|
|
|
#add commercial.
|
|
|
|
nextAd = get_next_commercial()
|
|
|
|
timeLeft -= get_video_length_in_seconds(nextAd)
|
|
|
|
playlist.write(nextAd + "\n")
|
2023-10-13 02:35:04 -04:00
|
|
|
|
2023-10-14 19:40:39 -04:00
|
|
|
print("playlist file creation complete")
|