123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- # This is a youtube-dl youtube song downloader. It uses both youtube-dl
- # for actual download and the invidious API for fetching info about the
- # song. GPLv3+
- import os
- from subprocess import *
- import json
- import random
- import urllib.request
- import urllib.parse
- dfolder = "downloads"
- def difference(x,y):
- if x > y:
- return x - y
- else:
- return y - x
- def fetch_info(videoId):
- # This function will output the info about our song.
- try:
- url = "https://invidious.namazso.eu/api/v1/videos/"+videoId
- req = urllib.request.Request(url, data=None)
- f = urllib.request.urlopen(req)
- data = json.loads(f.read().decode('utf-8'))
- except:
- url = "https://yewtu.be/api/v1/videos/"+videoId
- req = urllib.request.Request(url, data=None)
- f = urllib.request.urlopen(req)
- data = json.loads(f.read().decode('utf-8'))
-
-
- return data
- def search(query):
- # This function will search on youtube a query.
- url = "https://invidious.namazso.eu/api/v1/search/?q="+urllib.parse.quote_plus(query)
- req = urllib.request.Request(url, data=None)
- f = urllib.request.urlopen(req)
- data = json.loads(f.read().decode('utf-8'))
- return data
-
- def try_download(videoId, filename):
-
- # This fucntion will try download the song via youtube-dl
- #print("Trying to download", videoId)
-
- # Making sure that the download folder exists
- try:
- os.mkdir(dfolder)
- except:
- pass
-
- try:
- # We are using subbrocess.check_output here to catch errors.
- check_output(["youtube-dl",
- "https://youtube.com/watch?v="+videoId,
- "-x",
- "--output",
- dfolder+"/"+str(filename)+".%(ext)s"])
- return True
- except Exception as e:
- print("youtube-dl error", e)
- return False
- def insure_song(videoId, filename):
- # This function will insure a song is downloaded.
- songInfo = fetch_info(videoId)
- #print("Song", songInfo["title"], "by", songInfo["author"], "direct attempt.")
-
- # First we will try downloading the song as is.
- if try_download(videoId, filename):
- #print("Worked!")
- return True
- else:
- #print("Failed! Trying similar...")
-
- # If it failed we are going to try downloading a similar song.
- titleblacklist = ["cover", "react", "review", "remix", "acoustic", "teaser", "live"]
- query = songInfo["title"]
- if " - Topic" in songInfo["author"]:
- query = songInfo["author"].replace(" - Topic", "")+" "+query
-
- others = search(query)
- for song in others:
- # Chekcing that it's a video
- if song["type"] != "video":
- print("Skipped:", song["title"], "because not a video." )
- continue
-
- # Checking if the song is a cover or a remix
-
- cont = False
- for i in titleblacklist:
- if i.lower() in song["title"].lower():
- cont = i
- break
- if cont:
- #print("Skipped:", song["title"], "because", cont )
- continue
- # Chekcing the length of the song to be roughly the original
- if difference(song["lengthSeconds"], songInfo["lengthSeconds"]) > 60:
- print("Skipped:", song["title"], "because length is too different." )
- continue
- #print("Trying to download", song["title"])
-
- if try_download(song["videoId"], filename):
- return "Got Similar"
- return False
|