Skip to content

Instantly share code, notes, and snippets.

@pdxjohnny
Last active August 29, 2015 14:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pdxjohnny/eb5fa12391ffc2c5a48d to your computer and use it in GitHub Desktop.
Save pdxjohnny/eb5fa12391ffc2c5a48d to your computer and use it in GitHub Desktop.
Downloads youtube videos as music, metadata.txt is column numbers
[metadata]
title = 1
artist = 2
album = 3
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