aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md42
-rw-r--r--VaporSong.py182
-rw-r--r--assets/in-vhs.jpgbin0 -> 25779 bytes
-rw-r--r--assets/out-vhs.jpgbin0 -> 45078 bytes
-rw-r--r--main.py18
5 files changed, 48 insertions, 194 deletions
diff --git a/README.md b/README.md
index 5095da4..0fea756 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,9 @@
# vaporwave generator 旺育栄
+
A vaporwave music (+art, +video soon, I promise) generator bodged together using code from various sources. Runs on Python3
```
-usage: main.py [-h] [-M] [-V] [-i INPUT]
+usage: main.py [-h] [-M] [-P] [-V] [-i INPUT]
This program takes YouTube URL or title of a song and converts it into
vaporwave
@@ -10,13 +11,26 @@ vaporwave
optional arguments:
-h, --help show this help message and exit
-M, --music generate v a p o r w a v e music
+ -P, --picture generate VHS Style image
-V, --version show program version
-i INPUT, --input INPUT
- input url
+
```
If the program gives an error for sox, try running `ulimit -n 999'`
+## Demo
+
+### M U S I C
+
+Linking to Bandcamp soon
+
+### V H S I M A G E
+
+![]("assets/in-vhs.jpg")
+
+![]("assets/out-vhs.jpg")
+
## Installation
This was tested on macOS Catalina ( so should work on almost all macOS versions).
@@ -43,28 +57,38 @@ pip install -r requirements.txt
## Usage
-### YouTube URL
+### M U S I C
+
+#### YouTube URL
```
python3 main.py -M -i <YOUTUBE_URL>
```
-### Song Title
+#### Song Title
```
python3 main.py -M -i Song Title
```
+### V H S I M A G E S
+
+`python3 main.py -P -i "image.jpg"`
+
## Bugs
This project is a result of bodging and therefore has tons of bugs which need to be ironed out
## To-Do
-[ ] Move away from using os.system calls, and use Python modules instead ( Looking at you, Sox and aubio)
-[ ] Clean the Code
-[ ] Add Artwork Generator
-[ ] Add Video Generator
+[] Move away from using os.system calls, and use Python modules instead ( Looking at you, Sox and aubio)
+[] Clean the Code
+[] Add Artwork Generator
+[x] VHS Picture Styler ( Added in v1.5 )
+[] Add Video Generator
+[] Add Custom Date to VHS Styler
## Credits
@WJLiddy His repo `Macintech` forms the base code for the music generator
-@felipecustodio Using his repo `virtualdreamsbot` YouTube DL code ( Hopefully I will be able to integrate this project as a Telegram Bot) \ No newline at end of file
+@felipecustodio Using his repo `virtualdreamsbot` YouTube DL code ( Hopefully I will be able to integrate this project as a Telegram Bot)
+
+@Ragex04 His repo `VHS_BingImages` forms the base code for the VHS Image Styler \ No newline at end of file
diff --git a/VaporSong.py b/VaporSong.py
deleted file mode 100644
index bb75646..0000000
--- a/VaporSong.py
+++ /dev/null
@@ -1,182 +0,0 @@
-import os
-import subprocess
-import re
-from random import randint
-
-import logzero
-from logzero import logger
-from logzero import setup_logger
-
-CONFIDENCE_THRESH = 0.02
-
-class VaporSong:
-
- # Slows down Track
-
- def slow_down(src, rate, dest):
- cmd = "sox -G -D " + src + " " + dest + " speed " + str(rate)
- os.system(cmd)
- return dest
-
- # Adds Reverb
-
- 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
- os.system(cmd)
- return dest
-
-
- # Crops "src" from "start" plus "start + dur" and return it in "dest"
- def crop(src,dest,start,dur):
- cmd = "sox " + src + " " + dest + " trim " + " " + str(start) + " " + str(dur)
- os.system(cmd)
-
-
- # Randomly crops a part of the song of at most max_sec_len.
- def random_crop(src, max_sec_len, dest):
- out = subprocess.check_output(["soxi","-D",src]).rstrip()
- f_len = int(float(out))
- if (f_len <= max_sec_len):
- os.system("cp " + src + " " + dest)
- return
- else:
- start_region = f_len - max_sec_len
- start = randint(0,start_region)
- 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
- # TODO: Move away from executable and use aubio's Python module
- def fetchbeats(src):
- beat_matrix = []
- if os.name == 'posix':
- beats = subprocess.check_output(["noah", "get-beats",src]).rstrip()
- else:
- beats = subprocess.check_output(["get-beats",src]).rstrip()
- beats_ary = beats.splitlines()
- for i in beats_ary:
- record = i.split()
- record[0] = float(record[0])/1000.0
- record[1] = float(record[1])
- beat_matrix.append(record)
- return beat_matrix
-
- # Splits an audio file into beats according to beat_matrix list
-
- def split_beat(src,beat_matrix):
- split_files = []
- for i in range(0,len(beat_matrix)-1):
-
- if(beat_matrix[i][1] > CONFIDENCE_THRESH):
- dur = (beat_matrix[i+1][0] - beat_matrix[i][0])
- out = src.split(".")[0]+str(i)+".wav"
- VaporSong.crop(src,out,beat_matrix[i][0],dur)
- split_files.append(out)
- return split_files
-
- # Combines a list of sections
-
- def combine(sections,dest):
- tocomb = []
- tocomb.append("sox")
- tocomb.append("-G")
- for section in sections:
- for sample in section:
- tocomb.append(sample)
- tocomb.append(dest)
- tmpFileLimit = len(tocomb) + 256 # in case the program messes up, it does not actually frick up your system
- n = str(tmpFileLimit)
- #logger.info("Setting file limit to ", n)
- os.system("ulimit -n " + n)
- subprocess.check_output(tocomb)
- return dest
-
- # Arbitrarily groups beats into lists of 4, 6, 8, or 9, perfect for looping.
-
- def generate_sections(ary):
- sections = []
- beats = [4,6,8,9]
- index = 0
- while(index != len(ary)):
- current_beat = beats[randint(0,len(beats)-1)]
- new_section = []
- while((current_beat != 0) and (index != len(ary))):
- new_section.append(ary[index])
- current_beat -= 1
- index += 1
- sections.append(new_section)
- return sections
-
-
- # given a list of sections, selects some of them and duplicates them, perfect for that vaporwave looping effect
- def dup_sections(sections):
- new_section = []
- for section in sections:
- new_section.append(section)
- if(randint(0,1) == 0):
- new_section.append(section)
- return new_section
-
- # a passage is a list of sections. This takes some sections and groups them into passages.
-
- def make_passages(sections):
- passages = []
- index = 0
- while(index != len(sections)):
- passage_len = randint(1,4)
- passage = []
- while(index != len(sections) and passage_len > 0):
- passage.append(sections[index])
- index += 1
- passage_len -= 1
- passages.append(passage)
- return passages
-
- # Given all of our passages, picks some of them and inserts them into a list some number of times.
-
- def reorder_passages(passages):
- new_passages = []
- passage_count = randint(5,12)
- while(passage_count != 0):
- passage = passages[randint(0,len(passages)-1)]
- passage_count -= 1
- dup = randint(1,4)
- while(dup != 0):
- dup -= 1
- new_passages.append(passage)
- return new_passages
-
- # converts a list of passages to a list of sections.
-
- def flatten(passages):
- sections = []
- for passage in passages:
- for section in passage:
- sections.append(section)
- return sections
-
- # It's all coming together
-
- def vaporize_song(fname, title):
- logger.info("Slowing down the music")
- VaporSong.slow_down(fname, 0.7, "beats/out.wav")
- #logger.info("Cropping")
- #VaporSong.random_crop("beats/out.wav",150,"beats/outcrop.wav")
- logger.info("Doing Beat Analysis")
- bm = VaporSong.fetchbeats("beats/out.wav")
- logger.info("Split into beats")
- splitd = VaporSong.split_beat("beats/out.wav",bm)
- #group beats to sections
- logger.info("Divide into sections")
- sections = VaporSong.generate_sections(splitd)
- logger.info("Duping Sections")
- sdup = VaporSong.dup_sections(sections)
- # group sections into passages
- paslist = VaporSong.make_passages(sdup)
- # reorder packages
- pasloop = VaporSong.reorder_passages(paslist)
- sectionflat = VaporSong.flatten(pasloop)
- logger.info("Mastering & Reverbing")
- VaporSong.combine(sectionflat,"beats/out_norev.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")
diff --git a/assets/in-vhs.jpg b/assets/in-vhs.jpg
new file mode 100644
index 0000000..7bcafb0
--- /dev/null
+++ b/assets/in-vhs.jpg
Binary files differ
diff --git a/assets/out-vhs.jpg b/assets/out-vhs.jpg
new file mode 100644
index 0000000..9637d5c
--- /dev/null
+++ b/assets/out-vhs.jpg
Binary files differ
diff --git a/main.py b/main.py
index de93106..50a0d90 100644
--- a/main.py
+++ b/main.py
@@ -1,4 +1,5 @@
-from VaporSong import VaporSong
+from src.VaporSong import VaporSong
+from src.VHSImage import generateVHSStyle
import os
import sys
import youtube_dl
@@ -18,20 +19,28 @@ text = 'This program takes YouTube URL or title of a song and converts it into v
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("-P", "--picture", help="generate VHS Style image", action="store_true")
parser.add_argument("-V", "--version", help="show program version", action="store_true")
-parser.add_argument("-i", "--input", help="input url")
+parser.add_argument("-i", "--input")
+
args = parser.parse_args()
+music = False
+picture = False
+
if args.version:
print("vaporwave generator 旺育栄", version)
exit
if args.music:
music = True
+elif args.picture:
+ picture = True
if args.input:
query = args.input
else:
- query = input("Enter target song's name or YouTube URL: ")
+ parser.print_help()
+ exit
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')
@@ -149,3 +158,6 @@ for s in sys.argv:
if music:
name, title = download_file(query)
gen_vapor(name, title)
+elif picture:
+ generateVHSStyle(query,"out.jpg")
+ \ No newline at end of file