Skip to content

Instantly share code, notes, and snippets.

@samhutchins
Last active May 16, 2016 18:18
Show Gist options
  • Save samhutchins/6aa3d442a8826d744867aad07805ea3b to your computer and use it in GitHub Desktop.
Save samhutchins/6aa3d442a8826d744867aad07805ea3b to your computer and use it in GitHub Desktop.
YouTube Downloader.py
from urllib.parse import urlparse, parse_qs
from os import getcwd, path
import requests, appex, ui
class YouTube_video:
def __init__(self, url):
self.id = self.get_id(url)
self.title = None
self.stream_map = None
self.get_video_info()
self.format_dict = {
'22': '720p HD',
'18': '360p SD',
'17': '144p SD'
}
def get_id(self, url): # can only parse youtu.be links
parsed_url = urlparse(url)
_, id = parsed_url.path.split('/')
return id
def get_video_info(self): #gets title and stream_map
info_page = requests.get(
'http://youtube.com/get_video_info?video_id=' + self.id)
info_page = parse_qs(info_page.text)
self.title = info_page['title'][0]
self.stream_map = str(info_page['url_encoded_fmt_stream_map'][0]).split(',')
def get_download_url(self, itag):
for stream in self.stream_map:
url = parse_qs(stream)
if url['itag'][0] == str(itag):
return url['url'][0]
def get_formats(self):
formats = []
for stream in self.stream_map:
page = parse_qs(stream)
itag = page['itag'][0]
if itag in self.format_dict:
formats.append((self.format_dict[itag], itag))
return formats
def debug_stream_map(self):
page = parse_qs(self.stream_map[0])
for key in page:
print(key)
def debug_formats(self):
for stream in self.stream_map:
page = parse_qs(stream)
print(page['quality'][0])
print(page['type'][0])
print(page['itag'][0])
print('---')
class Formats: # the data provider for the tableview
def __init__(self, data, callback):
self.data = data
self.callback = callback
def tableview_number_of_sections(self, tableview):
return 1
def tableview_number_of_rows(self, tableview, section):
return len(self.data)
def tableview_cell_for_row(self, tableview, section, row):
cell = ui.TableViewCell()
cell.text_label.text, _ = self.data[row]
return cell
def tableview_did_select(self, tableview, section, row):
_, itag = self.data[row]
self.callback(itag)
class Downloader: #Responsible for downloading a given url.
def __init__(self, callback):
self.callback = callback
def download(self, title, url):
self.callback.start()
file_path = path.join(
getcwd(),
title + '.mp4')
with open(file_path, 'wb') as f:
r = requests.get(url, stream=True)
total_size = float(r.headers.get('content-length'))
dl = 0
for chunk in r.iter_content(32768):
dl += len(chunk)
f.write(chunk)
self.callback.update_progress(dl/total_size)
self.callback.stop()
class DownloaderCallback(object): # Acts as an interface between the Downloader and the front end
def __init__(self, start, stop, progress):
self.start = start
self.stop = stop
self.progress = progress
def start(self):
self.start()
def stop(self):
self.stop()
def update_progress(self, progress):
self.progress(progress)
class DownloaderUI(ui.View):
def __init__(self, video_url):
self.name = 'Downloader'
self.video = YouTube_video(video_url)
self.frame = (0, 0, 540, 540)
self.background_color = 'white'
self.data_source = Formats(self.video.get_formats(), self.action_event)
self.tv = ui.TableView(
frame = (0, 50, 540, 490),
flex = 'WH')
self.tv.data_source = self.data_source
self.tv.delegate = self.data_source
self.progress_bar = ui.Label(
frame = (0, 0, 0, 50),
flex = '',
background_color = (0.00, 0.50, 1.00, 0.5))
self.activity_indicator = ui.ActivityIndicator(
frame = (270,25,0,0),
flex = 'W',
alignment = ui.ALIGN_CENTER)
self.add_subview(self.tv)
self.add_subview(self.progress_bar)
self.add_subview(self.activity_indicator)
self.callback = DownloaderCallback(
self.activity_indicator.start,
self.activity_indicator.stop,
self.set_progress)
@ui.in_background
def action_event(self, itag):
downloader = Downloader(self.callback)
downloader.download(
self.video.title,
self.video.get_download_url(itag))
def set_progress(self, progress):
self.progress_bar.width = self.width*progress
if self.progress_bar.width == self.width:
self.progress_bar.background_color = (0.00, 1.00, 0.10, 0.7)
self.activity_indicator.stop()
if __name__ == '__main__':
view = DownloaderUI(appex.get_url())
view.present('sheet')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment