Last active
August 29, 2015 14:20
-
-
Save pdxjohnny/eb5fa12391ffc2c5a48d to your computer and use it in GitHub Desktop.
Downloads youtube videos as music, metadata.txt is column numbers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[metadata] | |
title = 1 | |
artist = 2 | |
album = 3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import re | |
import sys | |
import socket | |
import thread | |
import urllib | |
import httplib | |
import traceback | |
import subprocess | |
import ConfigParser | |
# Need to pip install these | |
import youtube_dl | |
import easygui | |
# Need ffmgep or else they will be in m4a format | |
HOME = os.path.expanduser("~") | |
SAVEDIR = "%s\Music\iTunes\iTunes Media\Automatically Add to iTunes" % (HOME, ) | |
DELIM = " - " | |
ORIGIN = "www.youtube.com" | |
FORMAT = "mp3" | |
YOUTUBEDL_OPTIONS = { | |
'format': 'bestaudio/best', # choice of quality | |
'extractaudio' : True, # only keep the audio | |
'audioformat' : FORMAT, # convert to FORMAT | |
'outtmpl': u'%(id)s', # name the file the ID of the video | |
'noplaylist' : True,} # only download single song, not playlist | |
YDL = youtube_dl.YoutubeDL(YOUTUBEDL_OPTIONS) | |
DOWNLOADED = 0 | |
CONVERTED = 0 | |
def str2bool(variable): | |
""" | |
Tests whether a variable would equate to True | |
""" | |
return str(variable).lower() in ("yes", "true", "t", "1", "on") | |
def config(file_name='metadata.txt'): | |
""" | |
Reads the config file and returns config object | |
""" | |
config_txt = ConfigParser.ConfigParser() | |
config_txt.read(file_name) | |
return config_txt | |
def section(name): | |
""" | |
Returns the section of the config file as a dict | |
""" | |
items = {} | |
all_items = config().items(name) | |
for item in all_items: | |
items[item[0]] = item[1] | |
return items | |
def fix_path(to_file): | |
if os.name == 'nt': | |
to_file = to_file.replace('/', '\\') | |
else: | |
to_file = to_file.replace('\\', '/') | |
return to_file | |
SAVEDIR = fix_path(SAVEDIR) | |
def make_savepath(title, artist, savedir=SAVEDIR): | |
savedir = fix_path(savedir + '/' + artist) | |
if not os.path.exists(savedir): | |
try: | |
os.makedirs(savedir) | |
except Exception, e: | |
pass | |
return os.path.join(savedir, "%s.%s" % (title, FORMAT)) | |
def search(search_string): | |
query = { | |
"search_query": search_string | |
} | |
url = "/results?" + urllib.urlencode(query) | |
conn = httplib.HTTPSConnection(ORIGIN) | |
conn.request("GET", url) | |
res = conn.getresponse() | |
data = res.read() | |
start = data.find("\"/watch?v") + 1 | |
end = data.find("\"", start) | |
url = data[start:end] | |
conn.close() | |
return url | |
def download(metadata): | |
result = False | |
savepath = make_savepath(metadata["title"], metadata["artist"]) | |
if not os.path.exists( savepath ): | |
search_string = metadata["title"] + " " + metadata["artist"] | |
if "album" in metadata: | |
search_string += " " + metadata["album"] | |
link = search(search_string) | |
link = "https://" + ORIGIN + link | |
try: | |
print "Downloading: %s from %s..." % (metadata["title"], link) | |
result = YDL.extract_info(link, download=True) | |
print "Downloaded %s successfully!" % savepath | |
except Exception as e: | |
print "Can't download audio! %s\n" % traceback.format_exc() | |
global DOWNLOADED | |
DOWNLOADED += 1 | |
return result | |
def convert(result, metadata): | |
savepath = make_savepath(metadata["title"], metadata["artist"]) | |
if not os.path.exists( savepath ): | |
try: | |
print "Converting: %s..." % (metadata["title"], ) | |
command = ["ffmpeg", "-i", result['id'], savepath] | |
for name in metadata: | |
command.insert(3, "%s=%s" % (name, metadata[name], )) | |
command.insert(3, "-metadata") | |
subprocess.call(command) | |
os.remove(result['id']) | |
print "Converted %s successfully!" % savepath | |
except Exception as e: | |
print "Can't convert audio! %s\n" % traceback.format_exc() | |
global CONVERTED | |
CONVERTED += 1 | |
def get(metadata): | |
result = download(metadata) | |
if result: | |
convert(result, metadata) | |
return result | |
def from_file(file_name, threading=False): | |
file_name = fix_path(file_name) | |
needed = 0 | |
album = False | |
metadata = section("metadata") | |
for line in open(file_name, 'r'): | |
if len(line) > 3: | |
track_metadata = {} | |
needed += 1 | |
line = line.replace("\r", "").replace("\n", "") | |
line = line.split(DELIM) | |
for name in metadata: | |
track_metadata[name] = line[int(metadata[name]) - 1] | |
if threading: | |
thread.start_new_thread( get, (track_metadata, ) ) | |
else: | |
get(track_metadata) | |
if threading: | |
global DOWNLOADED | |
global CONVERTED | |
while needed > CONVERTED and needed > DOWNLOADED: | |
pass | |
DOWNLOADED = 0 | |
CONVERTED = 0 | |
easygui.msgbox("Done Downloading Music", title="Done") | |
return True | |
def main(): | |
if len(sys.argv) > 2: | |
metadata = { | |
"title": sys.argv[1], | |
"artist": sys.argv[2] | |
} | |
get(metadata) | |
elif len(sys.argv) > 1: | |
file_name = sys.argv[1] | |
from_file(file_name, threading=False) | |
else: | |
print "Usage: file name or track and artist" | |
return 0 | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment