Format code with Black
This commit is contained in:
parent
6624f8fb1a
commit
52694cd7ad
90
main.py
90
main.py
|
@ -16,15 +16,19 @@ import time
|
||||||
version = 2.0
|
version = 2.0
|
||||||
style = False
|
style = False
|
||||||
|
|
||||||
text = '| V A P O R W A V E || G E N E R A T O R |'
|
text = "| V A P O R W A V E || G E N E R A T O R |"
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description = text)
|
parser = argparse.ArgumentParser(description=text)
|
||||||
parser.add_argument("-M", "--music", help="generate v a p o r w a v e music", action="store_true")
|
parser.add_argument(
|
||||||
parser.add_argument("-P", "--picture", help="generate VHS Style image", action="store_true")
|
"-M", "--music", help="generate v a p o r w a v e music", action="store_true"
|
||||||
parser.add_argument("-V","--video", help="VHS Style Video", action="store_true")
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-P", "--picture", help="generate VHS Style image", action="store_true"
|
||||||
|
)
|
||||||
|
parser.add_argument("-V", "--video", help="VHS Style Video", action="store_true")
|
||||||
parser.add_argument("-v", "--version", help="show program version", action="store_true")
|
parser.add_argument("-v", "--version", help="show program version", action="store_true")
|
||||||
parser.add_argument("-i", "--input")
|
parser.add_argument("-i", "--input")
|
||||||
parser.add_argument("-o","--output", help="Output for specifying output video")
|
parser.add_argument("-o", "--output", help="Output for specifying output video")
|
||||||
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
@ -51,9 +55,17 @@ else:
|
||||||
exit
|
exit
|
||||||
|
|
||||||
MAX_DURATION = 600 # In-case the program finds a compilation
|
MAX_DURATION = 600 # In-case the program finds a compilation
|
||||||
youtube_urls = ('youtube.com', 'https://www.youtube.com/', 'http://www.youtube.com/', 'http://youtu.be/', 'https://youtu.be/', 'youtu.be')
|
youtube_urls = (
|
||||||
|
"youtube.com",
|
||||||
|
"https://www.youtube.com/",
|
||||||
|
"http://www.youtube.com/",
|
||||||
|
"http://youtu.be/",
|
||||||
|
"https://youtu.be/",
|
||||||
|
"youtu.be",
|
||||||
|
)
|
||||||
|
|
||||||
def download_file(query,request_id=1):
|
|
||||||
|
def download_file(query, request_id=1):
|
||||||
"""Returns audio to the vapor command handler
|
"""Returns audio to the vapor command handler
|
||||||
|
|
||||||
Searches YouTube for 'query', finds first match that has
|
Searches YouTube for 'query', finds first match that has
|
||||||
|
@ -63,16 +75,18 @@ def download_file(query,request_id=1):
|
||||||
Query can be YouTube link.
|
Query can be YouTube link.
|
||||||
"""
|
"""
|
||||||
ydl_opts = {
|
ydl_opts = {
|
||||||
'quiet': 'True',
|
"quiet": "True",
|
||||||
'format': 'bestaudio/best',
|
"format": "bestaudio/best",
|
||||||
'outtmpl': str(request_id) +'.%(ext)s',
|
"outtmpl": str(request_id) + ".%(ext)s",
|
||||||
'prefer_ffmpeg': 'True',
|
"prefer_ffmpeg": "True",
|
||||||
'noplaylist': 'True',
|
"noplaylist": "True",
|
||||||
'postprocessors': [{
|
"postprocessors": [
|
||||||
'key': 'FFmpegExtractAudio',
|
{
|
||||||
'preferredcodec': 'wav',
|
"key": "FFmpegExtractAudio",
|
||||||
'preferredquality': '192',
|
"preferredcodec": "wav",
|
||||||
}],
|
"preferredquality": "192",
|
||||||
|
}
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
original_path = str(request_id) + ".wav"
|
original_path = str(request_id) + ".wav"
|
||||||
|
@ -81,9 +95,13 @@ def download_file(query,request_id=1):
|
||||||
# check if query is youtube url
|
# check if query is youtube url
|
||||||
if not query.lower().startswith((youtube_urls)):
|
if not query.lower().startswith((youtube_urls)):
|
||||||
# search for youtube videos matching query
|
# search for youtube videos matching query
|
||||||
query_string = urllib.parse.urlencode({"search_query" : query})
|
query_string = urllib.parse.urlencode({"search_query": query})
|
||||||
html_content = urllib.request.urlopen("http://www.youtube.com/results?" + query_string)
|
html_content = urllib.request.urlopen(
|
||||||
search_results = re.findall(r'href=\"\/watch\?v=(.{11})', html_content.read().decode())
|
"http://www.youtube.com/results?" + query_string
|
||||||
|
)
|
||||||
|
search_results = re.findall(
|
||||||
|
r"href=\"\/watch\?v=(.{11})", html_content.read().decode()
|
||||||
|
)
|
||||||
info = False
|
info = False
|
||||||
|
|
||||||
# find video that fits max duration
|
# find video that fits max duration
|
||||||
|
@ -91,30 +109,30 @@ def download_file(query,request_id=1):
|
||||||
for url in search_results:
|
for url in search_results:
|
||||||
# check for video duration
|
# check for video duration
|
||||||
try:
|
try:
|
||||||
info = youtube_dl.YoutubeDL(ydl_opts).extract_info(url,download = False)
|
info = youtube_dl.YoutubeDL(ydl_opts).extract_info(url, download=False)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
raise ValueError('Could not get information about video.')
|
raise ValueError("Could not get information about video.")
|
||||||
full_title = info['title']
|
full_title = info["title"]
|
||||||
if (info['duration'] < MAX_DURATION and info['duration'] >= 5):
|
if info["duration"] < MAX_DURATION and info["duration"] >= 5:
|
||||||
# get first video that fits the limit duration
|
# get first video that fits the limit duration
|
||||||
logger.info("Got video: " + str(full_title))
|
logger.info("Got video: " + str(full_title))
|
||||||
file_title = info['title']
|
file_title = info["title"]
|
||||||
break
|
break
|
||||||
|
|
||||||
# if we ran out of urls, return error
|
# if we ran out of urls, return error
|
||||||
if (not info):
|
if not info:
|
||||||
raise ValueError('Could not find a video.')
|
raise ValueError("Could not find a video.")
|
||||||
|
|
||||||
# query was a youtube link
|
# query was a youtube link
|
||||||
else:
|
else:
|
||||||
logger.info("Query was a YouTube URL.")
|
logger.info("Query was a YouTube URL.")
|
||||||
url = query
|
url = query
|
||||||
info = youtube_dl.YoutubeDL(ydl_opts).extract_info(url,download = False)
|
info = youtube_dl.YoutubeDL(ydl_opts).extract_info(url, download=False)
|
||||||
file_title = info['title']
|
file_title = info["title"]
|
||||||
# check if video fits limit duration
|
# check if video fits limit duration
|
||||||
if (info['duration'] < 5 or info['duration'] > MAX_DURATION):
|
if info["duration"] < 5 or info["duration"] > MAX_DURATION:
|
||||||
raise ValueError('Video is too short. Need 5 seconds or more.')
|
raise ValueError("Video is too short. Need 5 seconds or more.")
|
||||||
|
|
||||||
# download video and extract audio
|
# download video and extract audio
|
||||||
logger.info("Downloading video...")
|
logger.info("Downloading video...")
|
||||||
|
@ -123,7 +141,7 @@ def download_file(query,request_id=1):
|
||||||
ydl.download([url])
|
ydl.download([url])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
raise ValueError('Could not download ' + str(full_title) + '.')
|
raise ValueError("Could not download " + str(full_title) + ".")
|
||||||
|
|
||||||
return original_path, file_title
|
return original_path, file_title
|
||||||
|
|
||||||
|
@ -137,9 +155,8 @@ def gen_vapor(filePath, title):
|
||||||
os.system("mkdir download/")
|
os.system("mkdir download/")
|
||||||
os.system("mkdir beats/")
|
os.system("mkdir beats/")
|
||||||
|
|
||||||
|
|
||||||
# Download the youtube query's first result. Might be wrong but YOLO
|
# Download the youtube query's first result. Might be wrong but YOLO
|
||||||
#YTDownloader.download_wav_to_samp2(query)
|
# YTDownloader.download_wav_to_samp2(query)
|
||||||
|
|
||||||
# For every song in download folder(just one for now)
|
# For every song in download folder(just one for now)
|
||||||
"""
|
"""
|
||||||
|
@ -167,7 +184,6 @@ if music:
|
||||||
name, title = download_file(query)
|
name, title = download_file(query)
|
||||||
gen_vapor(name, title)
|
gen_vapor(name, title)
|
||||||
elif picture:
|
elif picture:
|
||||||
generateVHSStyle(query,"out.jpg")
|
generateVHSStyle(query, "out.jpg")
|
||||||
elif video:
|
elif video:
|
||||||
VHS_Vid(query, outfile)
|
VHS_Vid(query, outfile)
|
||||||
|
|
|
@ -21,7 +21,7 @@ def generate_offsets(array_size, max_offset):
|
||||||
periodicity = random.random() * periodicity
|
periodicity = random.random() * periodicity
|
||||||
offsets = []
|
offsets = []
|
||||||
for i in range(array_size):
|
for i in range(array_size):
|
||||||
offsets.append(floor(max_offset*np.sin(periodicity*(i*np.pi/180))))
|
offsets.append(floor(max_offset * np.sin(periodicity * (i * np.pi / 180))))
|
||||||
return offsets
|
return offsets
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,11 +35,11 @@ def hueChange(img, offset):
|
||||||
g_data = []
|
g_data = []
|
||||||
b_data = []
|
b_data = []
|
||||||
|
|
||||||
offset = offset/100.
|
offset = offset / 100.0
|
||||||
for rd, gr, bl in zip(r.getdata(), g.getdata(), b.getdata()):
|
for rd, gr, bl in zip(r.getdata(), g.getdata(), b.getdata()):
|
||||||
h, s, v = colorsys.rgb_to_hsv(rd/255.0, bl/255.0, gr/255.0)
|
h, s, v = colorsys.rgb_to_hsv(rd / 255.0, bl / 255.0, gr / 255.0)
|
||||||
rgb = colorsys.hsv_to_rgb(h, s+offset, v)
|
rgb = colorsys.hsv_to_rgb(h, s + offset, v)
|
||||||
rd, bl, gr = [int(x*255.) for x in rgb]
|
rd, bl, gr = [int(x * 255.0) for x in rgb]
|
||||||
r_data.append(rd)
|
r_data.append(rd)
|
||||||
g_data.append(gr)
|
g_data.append(gr)
|
||||||
b_data.append(bl)
|
b_data.append(bl)
|
||||||
|
@ -47,12 +47,21 @@ def hueChange(img, offset):
|
||||||
r.putdata(r_data)
|
r.putdata(r_data)
|
||||||
g.putdata(g_data)
|
g.putdata(g_data)
|
||||||
b.putdata(b_data)
|
b.putdata(b_data)
|
||||||
return Image.merge('RGB',(r,g,b))
|
return Image.merge("RGB", (r, g, b))
|
||||||
|
|
||||||
|
|
||||||
def decision(probability):
|
def decision(probability):
|
||||||
return random.random() < probability
|
return random.random() < probability
|
||||||
|
|
||||||
def mod_image_repeat_rows(imgname, chance_of_row_repeat=0, max_row_repeats=0, min_row_repeats=0, save=True, out_name="image.jpg"):
|
|
||||||
|
def mod_image_repeat_rows(
|
||||||
|
imgname,
|
||||||
|
chance_of_row_repeat=0,
|
||||||
|
max_row_repeats=0,
|
||||||
|
min_row_repeats=0,
|
||||||
|
save=True,
|
||||||
|
out_name="image.jpg",
|
||||||
|
):
|
||||||
img = Image.open(imgname)
|
img = Image.open(imgname)
|
||||||
pixels = img.load()
|
pixels = img.load()
|
||||||
width, height = img.size
|
width, height = img.size
|
||||||
|
@ -102,53 +111,68 @@ def add_date(img_path, out_name="image.jpg", bottom_offset=0):
|
||||||
width, height = img.size
|
width, height = img.size
|
||||||
draw = ImageDraw.Draw(img)
|
draw = ImageDraw.Draw(img)
|
||||||
font = ImageFont.truetype("src/VCR_OSD_MONO_1.001.ttf", 64)
|
font = ImageFont.truetype("src/VCR_OSD_MONO_1.001.ttf", 64)
|
||||||
draw.text((corner_offset, (height-150-bottom_offset)), date_str_1, (255, 255, 255), font=font)
|
draw.text(
|
||||||
draw.text((corner_offset, (height-75)-bottom_offset), date_str_2, (255, 255, 255), font=font)
|
(corner_offset, (height - 150 - bottom_offset)),
|
||||||
|
date_str_1,
|
||||||
|
(255, 255, 255),
|
||||||
|
font=font,
|
||||||
|
)
|
||||||
|
draw.text(
|
||||||
|
(corner_offset, (height - 75) - bottom_offset),
|
||||||
|
date_str_2,
|
||||||
|
(255, 255, 255),
|
||||||
|
font=font,
|
||||||
|
)
|
||||||
draw.text((corner_offset, 25), "|| PAUSE", (255, 255, 255), font=font)
|
draw.text((corner_offset, 25), "|| PAUSE", (255, 255, 255), font=font)
|
||||||
img.save(out_name)
|
img.save(out_name)
|
||||||
|
|
||||||
|
|
||||||
def add_img_noise(imgpath, intensity=1, out_name="image.jpg"):
|
def add_img_noise(imgpath, intensity=1, out_name="image.jpg"):
|
||||||
img = imageio.imread(imgpath, pilmode='RGB')
|
img = imageio.imread(imgpath, pilmode="RGB")
|
||||||
noise1 = img + intensity * img.std() * np.random.random(img.shape)
|
noise1 = img + intensity * img.std() * np.random.random(img.shape)
|
||||||
imageio.imwrite(out_name, noise1)
|
imageio.imwrite(out_name, noise1)
|
||||||
|
|
||||||
|
|
||||||
def offset_hue(image, out_name="image.jpg"):
|
def offset_hue(image, out_name="image.jpg"):
|
||||||
if isinstance(image, str):
|
if isinstance(image, str):
|
||||||
image = Image.open(image)
|
image = Image.open(image)
|
||||||
image = hueChange(image, 25)
|
image = hueChange(image, 25)
|
||||||
image.save(out_name)
|
image.save(out_name)
|
||||||
|
|
||||||
|
|
||||||
def build_background(out_name, taskbar_offset):
|
def build_background(out_name, taskbar_offset):
|
||||||
#getImage(out_name="start.jpg")
|
# getImage(out_name="start.jpg")
|
||||||
offset_hue("start.jpg", out_name="saturated.jpg")
|
offset_hue("start.jpg", out_name="saturated.jpg")
|
||||||
mod_image_repeat_rows("saturated.jpg", 0.012, 50, 10, out_name="shifted.jpg")
|
mod_image_repeat_rows("saturated.jpg", 0.012, 50, 10, out_name="shifted.jpg")
|
||||||
add_img_noise("shifted.jpg", out_name="noisy.jpg")
|
add_img_noise("shifted.jpg", out_name="noisy.jpg")
|
||||||
add_date("noisy.jpg", out_name=out_name, bottom_offset=taskbar_offset)
|
add_date("noisy.jpg", out_name=out_name, bottom_offset=taskbar_offset)
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
build_background("bkg.jpg", 25)
|
build_background("bkg.jpg", 25)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def generateVHSStyle(infile, outfile, silence=False):
|
def generateVHSStyle(infile, outfile, silence=False):
|
||||||
if silence:
|
if silence:
|
||||||
cut_rows = bool(random.getrandbits(1))
|
cut_rows = bool(random.getrandbits(1))
|
||||||
offset = random.choice([0,5,10])
|
offset = random.choice([0, 5, 10])
|
||||||
offset_hue(infile,"saturated.jpg")
|
offset_hue(infile, "saturated.jpg")
|
||||||
if cut_rows:
|
if cut_rows:
|
||||||
mod_image_repeat_rows("saturated.jpg", 0.012, 50, 10, True, "shifted.jpg")
|
mod_image_repeat_rows("saturated.jpg", 0.012, 50, 10, True, "shifted.jpg")
|
||||||
else:
|
else:
|
||||||
mod_image_repeat_rows("saturated.jpg", 0, 0, 0, True, "shifted.jpg")
|
mod_image_repeat_rows("saturated.jpg", 0, 0, 0, True, "shifted.jpg")
|
||||||
add_date("shifted.jpg","noisy.jpg")
|
add_date("shifted.jpg", "noisy.jpg")
|
||||||
add_date("noisy.jpg",outfile, bottom_offset=offset)
|
add_date("noisy.jpg", outfile, bottom_offset=offset)
|
||||||
os.remove("shifted.jpg")
|
os.remove("shifted.jpg")
|
||||||
os.remove("saturated.jpg")
|
os.remove("saturated.jpg")
|
||||||
os.remove("noisy.jpg")
|
os.remove("noisy.jpg")
|
||||||
else:
|
else:
|
||||||
cut_rows = bool(random.getrandbits(1))
|
cut_rows = bool(random.getrandbits(1))
|
||||||
offset = random.choice([0,5,10,15,20,25])
|
offset = random.choice([0, 5, 10, 15, 20, 25])
|
||||||
logger.info("Saturating the image")
|
logger.info("Saturating the image")
|
||||||
offset_hue(infile,"saturated.jpg")
|
offset_hue(infile, "saturated.jpg")
|
||||||
if cut_rows:
|
if cut_rows:
|
||||||
logger.info("Shifting the image")
|
logger.info("Shifting the image")
|
||||||
mod_image_repeat_rows("saturated.jpg", 0.012, 50, 10, True, "shifted.jpg")
|
mod_image_repeat_rows("saturated.jpg", 0.012, 50, 10, True, "shifted.jpg")
|
||||||
|
@ -156,13 +180,14 @@ def generateVHSStyle(infile, outfile, silence=False):
|
||||||
logger.info("Not applying lines effect")
|
logger.info("Not applying lines effect")
|
||||||
mod_image_repeat_rows("saturated.jpg", 0, 0, 0, True, "shifted.jpg")
|
mod_image_repeat_rows("saturated.jpg", 0, 0, 0, True, "shifted.jpg")
|
||||||
logger.info("Adding noise")
|
logger.info("Adding noise")
|
||||||
add_date("shifted.jpg","noisy.jpg")
|
add_date("shifted.jpg", "noisy.jpg")
|
||||||
logger.info("Adding text")
|
logger.info("Adding text")
|
||||||
add_date("noisy.jpg",outfile, bottom_offset=offset)
|
add_date("noisy.jpg", outfile, bottom_offset=offset)
|
||||||
logger.info("Generated Image: out.jpg")
|
logger.info("Generated Image: out.jpg")
|
||||||
logger.info("Removing residual files")
|
logger.info("Removing residual files")
|
||||||
os.remove("shifted.jpg")
|
os.remove("shifted.jpg")
|
||||||
os.remove("saturated.jpg")
|
os.remove("saturated.jpg")
|
||||||
os.remove("noisy.jpg")
|
os.remove("noisy.jpg")
|
||||||
|
|
||||||
#generateVHSStyle("s.jpg","o.jpg")
|
|
||||||
|
# generateVHSStyle("s.jpg","o.jpg")
|
||||||
|
|
|
@ -8,16 +8,18 @@ import logzero
|
||||||
from logzero import logger
|
from logzero import logger
|
||||||
from logzero import setup_logger
|
from logzero import setup_logger
|
||||||
|
|
||||||
|
|
||||||
def SaveVid(path):
|
def SaveVid(path):
|
||||||
vidObj = cv2.VideoCapture(path)
|
vidObj = cv2.VideoCapture(path)
|
||||||
count = 0
|
count = 0
|
||||||
success = 1
|
success = 1
|
||||||
while success:
|
while success:
|
||||||
success, image = vidObj.read()
|
success, image = vidObj.read()
|
||||||
cv2.imwrite("frames/"+str(count)+".jpg", image)
|
cv2.imwrite("frames/" + str(count) + ".jpg", image)
|
||||||
#os.rename("frames/"+str(count)+".jpg", os.path.splitext("frames/"+str(count)+".jpg")[0])
|
# os.rename("frames/"+str(count)+".jpg", os.path.splitext("frames/"+str(count)+".jpg")[0])
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
|
|
||||||
def Style(pathToFrames):
|
def Style(pathToFrames):
|
||||||
files = [f for f in os.listdir(pathToFrames) if isfile(join(pathToFrames, f))]
|
files = [f for f in os.listdir(pathToFrames) if isfile(join(pathToFrames, f))]
|
||||||
count = 0
|
count = 0
|
||||||
|
@ -41,29 +43,42 @@ def Style(pathToFrames):
|
||||||
os.system(c)
|
os.system(c)
|
||||||
os.chdir(cwd)
|
os.chdir(cwd)
|
||||||
|
|
||||||
|
|
||||||
def generateVideo(outfile, path, infile):
|
def generateVideo(outfile, path, infile):
|
||||||
frame_array = []
|
frame_array = []
|
||||||
files = [int(f) for f in os.listdir(path) if isfile(join(path, f))]
|
files = [int(f) for f in os.listdir(path) if isfile(join(path, f))]
|
||||||
files.sort()
|
files.sort()
|
||||||
|
|
||||||
duration = subprocess.check_output(['ffprobe', '-i', infile, '-show_entries', 'format=duration', '-v', 'quiet', '-of', 'csv=%s' % ("p=0")])
|
duration = subprocess.check_output(
|
||||||
fps = len(files)/float(duration)
|
[
|
||||||
|
"ffprobe",
|
||||||
|
"-i",
|
||||||
|
infile,
|
||||||
|
"-show_entries",
|
||||||
|
"format=duration",
|
||||||
|
"-v",
|
||||||
|
"quiet",
|
||||||
|
"-of",
|
||||||
|
"csv=%s" % ("p=0"),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
fps = len(files) / float(duration)
|
||||||
print("FPS", fps)
|
print("FPS", fps)
|
||||||
|
|
||||||
for i in range(len(files)):
|
for i in range(len(files)):
|
||||||
filename=path + str(files[i])
|
filename = path + str(files[i])
|
||||||
img = cv2.imread(filename)
|
img = cv2.imread(filename)
|
||||||
height, width, layers = img.shape
|
height, width, layers = img.shape
|
||||||
size = (width,height)
|
size = (width, height)
|
||||||
frame_array.append(img)
|
frame_array.append(img)
|
||||||
out = cv2.VideoWriter(outfile,cv2.VideoWriter_fourcc(*'MP4V'), fps, size)
|
out = cv2.VideoWriter(outfile, cv2.VideoWriter_fourcc(*"MP4V"), fps, size)
|
||||||
for i in range(len(frame_array)):
|
for i in range(len(frame_array)):
|
||||||
out.write(frame_array[i])
|
out.write(frame_array[i])
|
||||||
out.release()
|
out.release()
|
||||||
|
|
||||||
|
|
||||||
def VHS_Vid(infile, outfile):
|
def VHS_Vid(infile, outfile):
|
||||||
path = './frames/'
|
path = "./frames/"
|
||||||
os.system("rm frames/*")
|
os.system("rm frames/*")
|
||||||
os.system("mkdir frames")
|
os.system("mkdir frames")
|
||||||
logger.info("Exctracting Frames")
|
logger.info("Exctracting Frames")
|
||||||
|
@ -84,4 +99,4 @@ def VHS_Vid(infile, outfile):
|
||||||
os.remove("output-audio.aac")
|
os.remove("output-audio.aac")
|
||||||
|
|
||||||
|
|
||||||
#VHS_Vid("video.mp4","video2.mp4")
|
# VHS_Vid("video.mp4","video2.mp4")
|
||||||
|
|
|
@ -11,6 +11,7 @@ from logzero import setup_logger
|
||||||
|
|
||||||
CONFIDENCE_THRESH = 0.02
|
CONFIDENCE_THRESH = 0.02
|
||||||
|
|
||||||
|
|
||||||
class VaporSong:
|
class VaporSong:
|
||||||
|
|
||||||
# Slows down Track
|
# Slows down Track
|
||||||
|
@ -23,62 +24,61 @@ class VaporSong:
|
||||||
# Adds Reverb
|
# Adds Reverb
|
||||||
|
|
||||||
def reverbize(src, dest):
|
def reverbize(src, dest):
|
||||||
cmd = "sox -G -D " + src + " " + dest + " reverb 100 fade 5 -0 7" # idk what this does tbh, https://stackoverflow.com/a/57767238/8386344
|
cmd = (
|
||||||
|
"sox -G -D " + src + " " + dest + " reverb 100 fade 5 -0 7"
|
||||||
|
) # idk what this does tbh, https://stackoverflow.com/a/57767238/8386344
|
||||||
os.system(cmd)
|
os.system(cmd)
|
||||||
return dest
|
return dest
|
||||||
|
|
||||||
|
|
||||||
# Crops "src" from "start" plus "start + dur" and return it in "dest"
|
# Crops "src" from "start" plus "start + dur" and return it in "dest"
|
||||||
def crop(src,dest,start,dur):
|
def crop(src, dest, start, dur):
|
||||||
cmd = "sox " + src + " " + dest + " trim " + " " + str(start) + " " + str(dur)
|
cmd = "sox " + src + " " + dest + " trim " + " " + str(start) + " " + str(dur)
|
||||||
os.system(cmd)
|
os.system(cmd)
|
||||||
|
|
||||||
|
|
||||||
# Randomly crops a part of the song of at most max_sec_len.
|
# Randomly crops a part of the song of at most max_sec_len.
|
||||||
def random_crop(src, max_sec_len, dest):
|
def random_crop(src, max_sec_len, dest):
|
||||||
out = subprocess.check_output(["soxi","-D",src]).rstrip()
|
out = subprocess.check_output(["soxi", "-D", src]).rstrip()
|
||||||
f_len = int(float(out))
|
f_len = int(float(out))
|
||||||
if (f_len <= max_sec_len):
|
if f_len <= max_sec_len:
|
||||||
os.system("cp " + src + " " + dest)
|
os.system("cp " + src + " " + dest)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
start_region = f_len - max_sec_len
|
start_region = f_len - max_sec_len
|
||||||
start = randint(0,start_region)
|
start = randint(0, start_region)
|
||||||
VaporSong.crop(src,dest,start,max_sec_len)
|
VaporSong.crop(src, dest, start, max_sec_len)
|
||||||
|
|
||||||
|
|
||||||
# Given a file, returns a list of [beats, confidence], executable based on audibo's test-beattracking.c
|
# Given a file, returns a list of [beats, confidence], executable based on audibo's test-beattracking.c
|
||||||
# TODO: Move away from executable and use aubio's Python module
|
# TODO: Move away from executable and use aubio's Python module
|
||||||
def fetchbeats(src):
|
def fetchbeats(src):
|
||||||
beat_matrix = []
|
beat_matrix = []
|
||||||
if platform == 'darwin':
|
if platform == "darwin":
|
||||||
beats = subprocess.check_output(["noah", "get-beats",src]).rstrip()
|
beats = subprocess.check_output(["noah", "get-beats", src]).rstrip()
|
||||||
else:
|
else:
|
||||||
beats = subprocess.check_output(["./get-beats",src]).rstrip()
|
beats = subprocess.check_output(["./get-beats", src]).rstrip()
|
||||||
beats_ary = beats.splitlines()
|
beats_ary = beats.splitlines()
|
||||||
for i in beats_ary:
|
for i in beats_ary:
|
||||||
record = i.split()
|
record = i.split()
|
||||||
record[0] = float(record[0])/1000.0
|
record[0] = float(record[0]) / 1000.0
|
||||||
record[1] = float(record[1])
|
record[1] = float(record[1])
|
||||||
beat_matrix.append(record)
|
beat_matrix.append(record)
|
||||||
return beat_matrix
|
return beat_matrix
|
||||||
|
|
||||||
# Splits an audio file into beats according to beat_matrix list
|
# Splits an audio file into beats according to beat_matrix list
|
||||||
|
|
||||||
def split_beat(src,beat_matrix):
|
def split_beat(src, beat_matrix):
|
||||||
split_files = []
|
split_files = []
|
||||||
for i in range(0,len(beat_matrix)-1):
|
for i in range(0, len(beat_matrix) - 1):
|
||||||
|
|
||||||
if(beat_matrix[i][1] > CONFIDENCE_THRESH):
|
if beat_matrix[i][1] > CONFIDENCE_THRESH:
|
||||||
dur = (beat_matrix[i+1][0] - beat_matrix[i][0])
|
dur = beat_matrix[i + 1][0] - beat_matrix[i][0]
|
||||||
out = src.split(".")[0]+str(i)+".wav"
|
out = src.split(".")[0] + str(i) + ".wav"
|
||||||
VaporSong.crop(src,out,beat_matrix[i][0],dur)
|
VaporSong.crop(src, out, beat_matrix[i][0], dur)
|
||||||
split_files.append(out)
|
split_files.append(out)
|
||||||
return split_files
|
return split_files
|
||||||
|
|
||||||
# Combines a list of sections
|
# Combines a list of sections
|
||||||
|
|
||||||
def combine(sections,dest):
|
def combine(sections, dest):
|
||||||
tocomb = []
|
tocomb = []
|
||||||
tocomb.append("sox")
|
tocomb.append("sox")
|
||||||
tocomb.append("-G")
|
tocomb.append("-G")
|
||||||
|
@ -86,9 +86,11 @@ class VaporSong:
|
||||||
for sample in section:
|
for sample in section:
|
||||||
tocomb.append(sample)
|
tocomb.append(sample)
|
||||||
tocomb.append(dest)
|
tocomb.append(dest)
|
||||||
tmpFileLimit = len(tocomb) + 256 # in case the program messes up, it does not actually frick up your system
|
tmpFileLimit = (
|
||||||
|
len(tocomb) + 256
|
||||||
|
) # in case the program messes up, it does not actually frick up your system
|
||||||
n = str(tmpFileLimit)
|
n = str(tmpFileLimit)
|
||||||
#logger.info("Setting file limit to ", n)
|
# logger.info("Setting file limit to ", n)
|
||||||
os.system("ulimit -n " + n)
|
os.system("ulimit -n " + n)
|
||||||
subprocess.check_output(tocomb)
|
subprocess.check_output(tocomb)
|
||||||
return dest
|
return dest
|
||||||
|
@ -97,25 +99,24 @@ class VaporSong:
|
||||||
|
|
||||||
def generate_sections(ary):
|
def generate_sections(ary):
|
||||||
sections = []
|
sections = []
|
||||||
beats = [4,6,8,9]
|
beats = [4, 6, 8, 9]
|
||||||
index = 0
|
index = 0
|
||||||
while(index != len(ary)):
|
while index != len(ary):
|
||||||
current_beat = beats[randint(0,len(beats)-1)]
|
current_beat = beats[randint(0, len(beats) - 1)]
|
||||||
new_section = []
|
new_section = []
|
||||||
while((current_beat != 0) and (index != len(ary))):
|
while (current_beat != 0) and (index != len(ary)):
|
||||||
new_section.append(ary[index])
|
new_section.append(ary[index])
|
||||||
current_beat -= 1
|
current_beat -= 1
|
||||||
index += 1
|
index += 1
|
||||||
sections.append(new_section)
|
sections.append(new_section)
|
||||||
return sections
|
return sections
|
||||||
|
|
||||||
|
|
||||||
# given a list of sections, selects some of them and duplicates them, perfect for that vaporwave looping effect
|
# given a list of sections, selects some of them and duplicates them, perfect for that vaporwave looping effect
|
||||||
def dup_sections(sections):
|
def dup_sections(sections):
|
||||||
new_section = []
|
new_section = []
|
||||||
for section in sections:
|
for section in sections:
|
||||||
new_section.append(section)
|
new_section.append(section)
|
||||||
if(randint(0,1) == 0):
|
if randint(0, 1) == 0:
|
||||||
new_section.append(section)
|
new_section.append(section)
|
||||||
return new_section
|
return new_section
|
||||||
|
|
||||||
|
@ -124,10 +125,10 @@ class VaporSong:
|
||||||
def make_passages(sections):
|
def make_passages(sections):
|
||||||
passages = []
|
passages = []
|
||||||
index = 0
|
index = 0
|
||||||
while(index != len(sections)):
|
while index != len(sections):
|
||||||
passage_len = randint(1,4)
|
passage_len = randint(1, 4)
|
||||||
passage = []
|
passage = []
|
||||||
while(index != len(sections) and passage_len > 0):
|
while index != len(sections) and passage_len > 0:
|
||||||
passage.append(sections[index])
|
passage.append(sections[index])
|
||||||
index += 1
|
index += 1
|
||||||
passage_len -= 1
|
passage_len -= 1
|
||||||
|
@ -138,12 +139,12 @@ class VaporSong:
|
||||||
|
|
||||||
def reorder_passages(passages):
|
def reorder_passages(passages):
|
||||||
new_passages = []
|
new_passages = []
|
||||||
passage_count = randint(5,12)
|
passage_count = randint(5, 12)
|
||||||
while(passage_count != 0):
|
while passage_count != 0:
|
||||||
passage = passages[randint(0,len(passages)-1)]
|
passage = passages[randint(0, len(passages) - 1)]
|
||||||
passage_count -= 1
|
passage_count -= 1
|
||||||
dup = randint(1,4)
|
dup = randint(1, 4)
|
||||||
while(dup != 0):
|
while dup != 0:
|
||||||
dup -= 1
|
dup -= 1
|
||||||
new_passages.append(passage)
|
new_passages.append(passage)
|
||||||
return new_passages
|
return new_passages
|
||||||
|
@ -162,13 +163,13 @@ class VaporSong:
|
||||||
def vaporize_song(fname, title):
|
def vaporize_song(fname, title):
|
||||||
logger.info("Slowing down the music")
|
logger.info("Slowing down the music")
|
||||||
VaporSong.slow_down(fname, 0.7, "beats/out.wav")
|
VaporSong.slow_down(fname, 0.7, "beats/out.wav")
|
||||||
#logger.info("Cropping")
|
# logger.info("Cropping")
|
||||||
#VaporSong.random_crop("beats/out.wav",150,"beats/outcrop.wav")
|
# VaporSong.random_crop("beats/out.wav",150,"beats/outcrop.wav")
|
||||||
logger.info("Doing Beat Analysis")
|
logger.info("Doing Beat Analysis")
|
||||||
bm = VaporSong.fetchbeats("beats/out.wav")
|
bm = VaporSong.fetchbeats("beats/out.wav")
|
||||||
logger.info("Split into beats")
|
logger.info("Split into beats")
|
||||||
splitd = VaporSong.split_beat("beats/out.wav",bm)
|
splitd = VaporSong.split_beat("beats/out.wav", bm)
|
||||||
#group beats to sections
|
# group beats to sections
|
||||||
logger.info("Divide into sections")
|
logger.info("Divide into sections")
|
||||||
sections = VaporSong.generate_sections(splitd)
|
sections = VaporSong.generate_sections(splitd)
|
||||||
logger.info("Duping Sections")
|
logger.info("Duping Sections")
|
||||||
|
@ -179,6 +180,9 @@ class VaporSong:
|
||||||
pasloop = VaporSong.reorder_passages(paslist)
|
pasloop = VaporSong.reorder_passages(paslist)
|
||||||
sectionflat = VaporSong.flatten(pasloop)
|
sectionflat = VaporSong.flatten(pasloop)
|
||||||
logger.info("Mastering & Reverbing")
|
logger.info("Mastering & Reverbing")
|
||||||
VaporSong.combine(sectionflat,"beats/out_norev.wav")
|
VaporSong.combine(sectionflat, "beats/out_norev.wav")
|
||||||
VaporSong.reverbize("beats/out_norev.wav","./" + (re.sub(r"\W+|_", " ", title)).replace(" ","_") + ".wav")
|
VaporSong.reverbize(
|
||||||
|
"beats/out_norev.wav",
|
||||||
|
"./" + (re.sub(r"\W+|_", " ", title)).replace(" ", "_") + ".wav",
|
||||||
|
)
|
||||||
logger.info("Generated V A P O R W A V E")
|
logger.info("Generated V A P O R W A V E")
|
||||||
|
|
Loading…
Reference in New Issue