Separate downloader options
[youtube-dl] / youtube_dl / __init__.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 __authors__  = (
5     'Ricardo Garcia Gonzalez',
6     'Danny Colligan',
7     'Benjamin Johnson',
8     'Vasyl\' Vavrychuk',
9     'Witold Baryluk',
10     'Paweł Paprota',
11     'Gergely Imreh',
12     'Rogério Brito',
13     'Philipp Hagemeister',
14     'Sören Schulze',
15     'Kevin Ngo',
16     'Ori Avtalion',
17     'shizeeg',
18     'Filippo Valsorda',
19     'Christian Albrecht',
20     'Dave Vasilevsky',
21     'Jaime Marquínez Ferrándiz',
22     'Jeff Crouse',
23     'Osama Khalid',
24     'Michael Walter',
25     'M. Yasoob Ullah Khalid',
26     'Julien Fraichard',
27     'Johny Mo Swag',
28     'Axel Noack',
29     'Albert Kim',
30 )
31
32 __license__ = 'Public Domain'
33
34 import codecs
35 import getpass
36 import optparse
37 import os
38 import re
39 import shlex
40 import socket
41 import subprocess
42 import sys
43 import warnings
44 import platform
45
46 from .utils import *
47 from .update import update_self
48 from .version import __version__
49 from .FileDownloader import *
50 from .extractor import gen_extractors
51 from .YoutubeDL import YoutubeDL
52 from .PostProcessor import *
53
54 def parseOpts(overrideArguments=None):
55     def _readOptions(filename_bytes):
56         try:
57             optionf = open(filename_bytes)
58         except IOError:
59             return [] # silently skip if file is not present
60         try:
61             res = []
62             for l in optionf:
63                 res += shlex.split(l, comments=True)
64         finally:
65             optionf.close()
66         return res
67
68     def _format_option_string(option):
69         ''' ('-o', '--option') -> -o, --format METAVAR'''
70
71         opts = []
72
73         if option._short_opts:
74             opts.append(option._short_opts[0])
75         if option._long_opts:
76             opts.append(option._long_opts[0])
77         if len(opts) > 1:
78             opts.insert(1, ', ')
79
80         if option.takes_value(): opts.append(' %s' % option.metavar)
81
82         return "".join(opts)
83
84     def _find_term_columns():
85         columns = os.environ.get('COLUMNS', None)
86         if columns:
87             return int(columns)
88
89         try:
90             sp = subprocess.Popen(['stty', 'size'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
91             out,err = sp.communicate()
92             return int(out.split()[1])
93         except:
94             pass
95         return None
96
97     max_width = 80
98     max_help_position = 80
99
100     # No need to wrap help messages if we're on a wide console
101     columns = _find_term_columns()
102     if columns: max_width = columns
103
104     fmt = optparse.IndentedHelpFormatter(width=max_width, max_help_position=max_help_position)
105     fmt.format_option_strings = _format_option_string
106
107     kw = {
108         'version'   : __version__,
109         'formatter' : fmt,
110         'usage' : '%prog [options] url [url...]',
111         'conflict_handler' : 'resolve',
112     }
113
114     parser = optparse.OptionParser(**kw)
115
116     # option groups
117     general        = optparse.OptionGroup(parser, 'General Options')
118     selection      = optparse.OptionGroup(parser, 'Video Selection')
119     authentication = optparse.OptionGroup(parser, 'Authentication Options')
120     video_format   = optparse.OptionGroup(parser, 'Video Format Options')
121     downloader     = optparse.OptionGroup(parser, 'Download Options')
122     postproc       = optparse.OptionGroup(parser, 'Post-processing Options')
123     filesystem     = optparse.OptionGroup(parser, 'Filesystem Options')
124     verbosity      = optparse.OptionGroup(parser, 'Verbosity / Simulation Options')
125
126     general.add_option('-h', '--help',
127             action='help', help='print this help text and exit')
128     general.add_option('-v', '--version',
129             action='version', help='print program version and exit')
130     general.add_option('-U', '--update',
131             action='store_true', dest='update_self', help='update this program to latest version')
132     general.add_option('-i', '--ignore-errors',
133             action='store_true', dest='ignoreerrors', help='continue on download errors', default=False)
134     general.add_option('--dump-user-agent',
135             action='store_true', dest='dump_user_agent',
136             help='display the current browser identification', default=False)
137     general.add_option('--user-agent',
138             dest='user_agent', help='specify a custom user agent', metavar='UA')
139     general.add_option('--referer',
140             dest='referer', help='specify a custom referer, use if the video access is restricted to one domain',
141             metavar='REF', default=None)
142     general.add_option('--list-extractors',
143             action='store_true', dest='list_extractors',
144             help='List all supported extractors and the URLs they would handle', default=False)
145     general.add_option('--proxy', dest='proxy', default=None, help='Use the specified HTTP/HTTPS proxy', metavar='URL')
146     general.add_option('--no-check-certificate', action='store_true', dest='no_check_certificate', default=False, help='Suppress HTTPS certificate validation.')
147
148
149     selection.add_option('--playlist-start',
150             dest='playliststart', metavar='NUMBER', help='playlist video to start at (default is %default)', default=1)
151     selection.add_option('--playlist-end',
152             dest='playlistend', metavar='NUMBER', help='playlist video to end at (default is last)', default=-1)
153     selection.add_option('--match-title', dest='matchtitle', metavar='REGEX',help='download only matching titles (regex or caseless sub-string)')
154     selection.add_option('--reject-title', dest='rejecttitle', metavar='REGEX',help='skip download for matching titles (regex or caseless sub-string)')
155     selection.add_option('--max-downloads', metavar='NUMBER', dest='max_downloads', help='Abort after downloading NUMBER files', default=None)
156     selection.add_option('--min-filesize', metavar='SIZE', dest='min_filesize', help="Do not download any videos smaller than SIZE (e.g. 50k or 44.6m)", default=None)
157     selection.add_option('--max-filesize', metavar='SIZE', dest='max_filesize', help="Do not download any videos larger than SIZE (e.g. 50k or 44.6m)", default=None)
158     selection.add_option('--date', metavar='DATE', dest='date', help='download only videos uploaded in this date', default=None)
159     selection.add_option('--datebefore', metavar='DATE', dest='datebefore', help='download only videos uploaded before this date', default=None)
160     selection.add_option('--dateafter', metavar='DATE', dest='dateafter', help='download only videos uploaded after this date', default=None)
161
162
163     authentication.add_option('-u', '--username',
164             dest='username', metavar='USERNAME', help='account username')
165     authentication.add_option('-p', '--password',
166             dest='password', metavar='PASSWORD', help='account password')
167     authentication.add_option('-n', '--netrc',
168             action='store_true', dest='usenetrc', help='use .netrc authentication data', default=False)
169     authentication.add_option('--video-password',
170             dest='videopassword', metavar='PASSWORD', help='video password (vimeo only)')
171
172
173     video_format.add_option('-f', '--format',
174             action='store', dest='format', metavar='FORMAT',
175             help='video format code, specifiy the order of preference using slashes: "-f 22/17/18"')
176     video_format.add_option('--all-formats',
177             action='store_const', dest='format', help='download all available video formats', const='all')
178     video_format.add_option('--prefer-free-formats',
179             action='store_true', dest='prefer_free_formats', default=False, help='prefer free video formats unless a specific one is requested')
180     video_format.add_option('--max-quality',
181             action='store', dest='format_limit', metavar='FORMAT', help='highest quality format to download')
182     video_format.add_option('-F', '--list-formats',
183             action='store_true', dest='listformats', help='list all available formats (currently youtube only)')
184     video_format.add_option('--write-sub', '--write-srt',
185             action='store_true', dest='writesubtitles',
186             help='write subtitle file (currently youtube only)', default=False)
187     video_format.add_option('--write-auto-sub', '--write-automatic-sub',
188             action='store_true', dest='writeautomaticsub',
189             help='write automatic subtitle file (currently youtube only)', default=False)
190     video_format.add_option('--only-sub',
191             action='store_true', dest='skip_download',
192             help='[deprecated] alias of --skip-download', default=False)
193     video_format.add_option('--all-subs',
194             action='store_true', dest='allsubtitles',
195             help='downloads all the available subtitles of the video (currently youtube only)', default=False)
196     video_format.add_option('--list-subs',
197             action='store_true', dest='listsubtitles',
198             help='lists all available subtitles for the video (currently youtube only)', default=False)
199     video_format.add_option('--sub-format',
200             action='store', dest='subtitlesformat', metavar='FORMAT',
201             help='subtitle format [srt/sbv/vtt] (default=srt) (currently youtube only)', default='srt')
202     video_format.add_option('--sub-lang', '--srt-lang',
203             action='store', dest='subtitleslang', metavar='LANG',
204             help='language of the subtitles to download (optional) use IETF language tags like \'en\'')
205
206     downloader.add_option('-r', '--rate-limit',
207             dest='ratelimit', metavar='LIMIT', help='maximum download rate (e.g. 50k or 44.6m)')
208     downloader.add_option('-R', '--retries',
209             dest='retries', metavar='RETRIES', help='number of retries (default is %default)', default=10)
210     downloader.add_option('--buffer-size',
211             dest='buffersize', metavar='SIZE', help='size of download buffer (e.g. 1024 or 16k) (default is %default)', default="1024")
212     downloader.add_option('--no-resize-buffer',
213             action='store_true', dest='noresizebuffer',
214             help='do not automatically adjust the buffer size. By default, the buffer size is automatically resized from an initial value of SIZE.', default=False)
215     downloader.add_option('--test', action='store_true', dest='test', default=False, help=optparse.SUPPRESS_HELP)
216
217     verbosity.add_option('-q', '--quiet',
218             action='store_true', dest='quiet', help='activates quiet mode', default=False)
219     verbosity.add_option('-s', '--simulate',
220             action='store_true', dest='simulate', help='do not download the video and do not write anything to disk', default=False)
221     verbosity.add_option('--skip-download',
222             action='store_true', dest='skip_download', help='do not download the video', default=False)
223     verbosity.add_option('-g', '--get-url',
224             action='store_true', dest='geturl', help='simulate, quiet but print URL', default=False)
225     verbosity.add_option('-e', '--get-title',
226             action='store_true', dest='gettitle', help='simulate, quiet but print title', default=False)
227     verbosity.add_option('--get-id',
228             action='store_true', dest='getid', help='simulate, quiet but print id', default=False)
229     verbosity.add_option('--get-thumbnail',
230             action='store_true', dest='getthumbnail',
231             help='simulate, quiet but print thumbnail URL', default=False)
232     verbosity.add_option('--get-description',
233             action='store_true', dest='getdescription',
234             help='simulate, quiet but print video description', default=False)
235     verbosity.add_option('--get-filename',
236             action='store_true', dest='getfilename',
237             help='simulate, quiet but print output filename', default=False)
238     verbosity.add_option('--get-format',
239             action='store_true', dest='getformat',
240             help='simulate, quiet but print output format', default=False)
241     verbosity.add_option('--newline',
242             action='store_true', dest='progress_with_newline', help='output progress bar as new lines', default=False)
243     verbosity.add_option('--no-progress',
244             action='store_true', dest='noprogress', help='do not print progress bar', default=False)
245     verbosity.add_option('--console-title',
246             action='store_true', dest='consoletitle',
247             help='display progress in console titlebar', default=False)
248     verbosity.add_option('-v', '--verbose',
249             action='store_true', dest='verbose', help='print various debugging information', default=False)
250     verbosity.add_option('--dump-intermediate-pages',
251             action='store_true', dest='dump_intermediate_pages', default=False,
252             help='print downloaded pages to debug problems(very verbose)')
253
254     filesystem.add_option('-t', '--title',
255             action='store_true', dest='usetitle', help='use title in file name (default)', default=False)
256     filesystem.add_option('--id',
257             action='store_true', dest='useid', help='use only video ID in file name', default=False)
258     filesystem.add_option('-l', '--literal',
259             action='store_true', dest='usetitle', help='[deprecated] alias of --title', default=False)
260     filesystem.add_option('-A', '--auto-number',
261             action='store_true', dest='autonumber',
262             help='number downloaded files starting from 00000', default=False)
263     filesystem.add_option('-o', '--output',
264             dest='outtmpl', metavar='TEMPLATE',
265             help=('output filename template. Use %(title)s to get the title, '
266                   '%(uploader)s for the uploader name, %(uploader_id)s for the uploader nickname if different, '
267                   '%(autonumber)s to get an automatically incremented number, '
268                   '%(ext)s for the filename extension, %(upload_date)s for the upload date (YYYYMMDD), '
269                   '%(extractor)s for the provider (youtube, metacafe, etc), '
270                   '%(id)s for the video id , %(playlist)s for the playlist the video is in, '
271                   '%(playlist_index)s for the position in the playlist and %% for a literal percent. '
272                   'Use - to output to stdout. Can also be used to download to a different directory, '
273                   'for example with -o \'/my/downloads/%(uploader)s/%(title)s-%(id)s.%(ext)s\' .'))
274     filesystem.add_option('--autonumber-size',
275             dest='autonumber_size', metavar='NUMBER',
276             help='Specifies the number of digits in %(autonumber)s when it is present in output filename template or --autonumber option is given')
277     filesystem.add_option('--restrict-filenames',
278             action='store_true', dest='restrictfilenames',
279             help='Restrict filenames to only ASCII characters, and avoid "&" and spaces in filenames', default=False)
280     filesystem.add_option('-a', '--batch-file',
281             dest='batchfile', metavar='FILE', help='file containing URLs to download (\'-\' for stdin)')
282     filesystem.add_option('-w', '--no-overwrites',
283             action='store_true', dest='nooverwrites', help='do not overwrite files', default=False)
284     filesystem.add_option('-c', '--continue',
285             action='store_true', dest='continue_dl', help='resume partially downloaded files', default=True)
286     filesystem.add_option('--no-continue',
287             action='store_false', dest='continue_dl',
288             help='do not resume partially downloaded files (restart from beginning)')
289     filesystem.add_option('--cookies',
290             dest='cookiefile', metavar='FILE', help='file to read cookies from and dump cookie jar in')
291     filesystem.add_option('--no-part',
292             action='store_true', dest='nopart', help='do not use .part files', default=False)
293     filesystem.add_option('--no-mtime',
294             action='store_false', dest='updatetime',
295             help='do not use the Last-modified header to set the file modification time', default=True)
296     filesystem.add_option('--write-description',
297             action='store_true', dest='writedescription',
298             help='write video description to a .description file', default=False)
299     filesystem.add_option('--write-info-json',
300             action='store_true', dest='writeinfojson',
301             help='write video metadata to a .info.json file', default=False)
302     filesystem.add_option('--write-thumbnail',
303             action='store_true', dest='writethumbnail',
304             help='write thumbnail image to disk', default=False)
305
306
307     postproc.add_option('-x', '--extract-audio', action='store_true', dest='extractaudio', default=False,
308             help='convert video files to audio-only files (requires ffmpeg or avconv and ffprobe or avprobe)')
309     postproc.add_option('--audio-format', metavar='FORMAT', dest='audioformat', default='best',
310             help='"best", "aac", "vorbis", "mp3", "m4a", "opus", or "wav"; best by default')
311     postproc.add_option('--audio-quality', metavar='QUALITY', dest='audioquality', default='5',
312             help='ffmpeg/avconv audio quality specification, insert a value between 0 (better) and 9 (worse) for VBR or a specific bitrate like 128K (default 5)')
313     postproc.add_option('--recode-video', metavar='FORMAT', dest='recodevideo', default=None,
314             help='Encode the video to another format if necessary (currently supported: mp4|flv|ogg|webm)')
315     postproc.add_option('-k', '--keep-video', action='store_true', dest='keepvideo', default=False,
316             help='keeps the video file on disk after the post-processing; the video is erased by default')
317     postproc.add_option('--no-post-overwrites', action='store_true', dest='nopostoverwrites', default=False,
318             help='do not overwrite post-processed files; the post-processed files are overwritten by default')
319
320
321     parser.add_option_group(general)
322     parser.add_option_group(selection)
323     parser.add_option_group(downloader)
324     parser.add_option_group(filesystem)
325     parser.add_option_group(verbosity)
326     parser.add_option_group(video_format)
327     parser.add_option_group(authentication)
328     parser.add_option_group(postproc)
329
330     if overrideArguments is not None:
331         opts, args = parser.parse_args(overrideArguments)
332         if opts.verbose:
333             sys.stderr.write(u'[debug] Override config: ' + repr(overrideArguments) + '\n')
334     else:
335         xdg_config_home = os.environ.get('XDG_CONFIG_HOME')
336         if xdg_config_home:
337             userConfFile = os.path.join(xdg_config_home, 'youtube-dl.conf')
338         else:
339             userConfFile = os.path.join(os.path.expanduser('~'), '.config', 'youtube-dl.conf')
340         systemConf = _readOptions('/etc/youtube-dl.conf')
341         userConf = _readOptions(userConfFile)
342         commandLineConf = sys.argv[1:] 
343         argv = systemConf + userConf + commandLineConf
344         opts, args = parser.parse_args(argv)
345         if opts.verbose:
346             sys.stderr.write(u'[debug] System config: ' + repr(systemConf) + '\n')
347             sys.stderr.write(u'[debug] User config: ' + repr(userConf) + '\n')
348             sys.stderr.write(u'[debug] Command-line args: ' + repr(commandLineConf) + '\n')
349
350     return parser, opts, args
351
352 def _real_main(argv=None):
353     # Compatibility fixes for Windows
354     if sys.platform == 'win32':
355         # https://github.com/rg3/youtube-dl/issues/820
356         codecs.register(lambda name: codecs.lookup('utf-8') if name == 'cp65001' else None)
357
358     parser, opts, args = parseOpts(argv)
359
360     # Open appropriate CookieJar
361     if opts.cookiefile is None:
362         jar = compat_cookiejar.CookieJar()
363     else:
364         try:
365             jar = compat_cookiejar.MozillaCookieJar(opts.cookiefile)
366             if os.access(opts.cookiefile, os.R_OK):
367                 jar.load()
368         except (IOError, OSError) as err:
369             if opts.verbose:
370                 traceback.print_exc()
371             sys.stderr.write(u'ERROR: unable to open cookie file\n')
372             sys.exit(101)
373     # Set user agent
374     if opts.user_agent is not None:
375         std_headers['User-Agent'] = opts.user_agent
376     
377     # Set referer
378     if opts.referer is not None:
379         std_headers['Referer'] = opts.referer
380
381     # Dump user agent
382     if opts.dump_user_agent:
383         compat_print(std_headers['User-Agent'])
384         sys.exit(0)
385
386     # Batch file verification
387     batchurls = []
388     if opts.batchfile is not None:
389         try:
390             if opts.batchfile == '-':
391                 batchfd = sys.stdin
392             else:
393                 batchfd = open(opts.batchfile, 'r')
394             batchurls = batchfd.readlines()
395             batchurls = [x.strip() for x in batchurls]
396             batchurls = [x for x in batchurls if len(x) > 0 and not re.search(r'^[#/;]', x)]
397         except IOError:
398             sys.exit(u'ERROR: batch file could not be read')
399     all_urls = batchurls + args
400     all_urls = [url.strip() for url in all_urls]
401
402     # General configuration
403     cookie_processor = compat_urllib_request.HTTPCookieProcessor(jar)
404     if opts.proxy is not None:
405         if opts.proxy == '':
406             proxies = {}
407         else:
408             proxies = {'http': opts.proxy, 'https': opts.proxy}
409     else:
410         proxies = compat_urllib_request.getproxies()
411         # Set HTTPS proxy to HTTP one if given (https://github.com/rg3/youtube-dl/issues/805)
412         if 'http' in proxies and 'https' not in proxies:
413             proxies['https'] = proxies['http']
414     proxy_handler = compat_urllib_request.ProxyHandler(proxies)
415     https_handler = make_HTTPS_handler(opts)
416     opener = compat_urllib_request.build_opener(https_handler, proxy_handler, cookie_processor, YoutubeDLHandler())
417     compat_urllib_request.install_opener(opener)
418     socket.setdefaulttimeout(300) # 5 minutes should be enough (famous last words)
419
420     extractors = gen_extractors()
421
422     if opts.list_extractors:
423         for ie in extractors:
424             compat_print(ie.IE_NAME + (' (CURRENTLY BROKEN)' if not ie._WORKING else ''))
425             matchedUrls = [url for url in all_urls if ie.suitable(url)]
426             all_urls = [url for url in all_urls if url not in matchedUrls]
427             for mu in matchedUrls:
428                 compat_print(u'  ' + mu)
429         sys.exit(0)
430
431     # Conflicting, missing and erroneous options
432     if opts.usenetrc and (opts.username is not None or opts.password is not None):
433         parser.error(u'using .netrc conflicts with giving username/password')
434     if opts.password is not None and opts.username is None:
435         parser.error(u' account username missing\n')
436     if opts.outtmpl is not None and (opts.usetitle or opts.autonumber or opts.useid):
437         parser.error(u'using output template conflicts with using title, video ID or auto number')
438     if opts.usetitle and opts.useid:
439         parser.error(u'using title conflicts with using video ID')
440     if opts.username is not None and opts.password is None:
441         opts.password = getpass.getpass(u'Type account password and press return:')
442     if opts.ratelimit is not None:
443         numeric_limit = FileDownloader.parse_bytes(opts.ratelimit)
444         if numeric_limit is None:
445             parser.error(u'invalid rate limit specified')
446         opts.ratelimit = numeric_limit
447     if opts.min_filesize is not None:
448         numeric_limit = FileDownloader.parse_bytes(opts.min_filesize)
449         if numeric_limit is None:
450             parser.error(u'invalid min_filesize specified')
451         opts.min_filesize = numeric_limit
452     if opts.max_filesize is not None:
453         numeric_limit = FileDownloader.parse_bytes(opts.max_filesize)
454         if numeric_limit is None:
455             parser.error(u'invalid max_filesize specified')
456         opts.max_filesize = numeric_limit
457     if opts.retries is not None:
458         try:
459             opts.retries = int(opts.retries)
460         except (TypeError, ValueError) as err:
461             parser.error(u'invalid retry count specified')
462     if opts.buffersize is not None:
463         numeric_buffersize = FileDownloader.parse_bytes(opts.buffersize)
464         if numeric_buffersize is None:
465             parser.error(u'invalid buffer size specified')
466         opts.buffersize = numeric_buffersize
467     try:
468         opts.playliststart = int(opts.playliststart)
469         if opts.playliststart <= 0:
470             raise ValueError(u'Playlist start must be positive')
471     except (TypeError, ValueError) as err:
472         parser.error(u'invalid playlist start number specified')
473     try:
474         opts.playlistend = int(opts.playlistend)
475         if opts.playlistend != -1 and (opts.playlistend <= 0 or opts.playlistend < opts.playliststart):
476             raise ValueError(u'Playlist end must be greater than playlist start')
477     except (TypeError, ValueError) as err:
478         parser.error(u'invalid playlist end number specified')
479     if opts.extractaudio:
480         if opts.audioformat not in ['best', 'aac', 'mp3', 'm4a', 'opus', 'vorbis', 'wav']:
481             parser.error(u'invalid audio format specified')
482     if opts.audioquality:
483         opts.audioquality = opts.audioquality.strip('k').strip('K')
484         if not opts.audioquality.isdigit():
485             parser.error(u'invalid audio quality specified')
486     if opts.recodevideo is not None:
487         if opts.recodevideo not in ['mp4', 'flv', 'webm', 'ogg']:
488             parser.error(u'invalid video recode format specified')
489     if opts.date is not None:
490         date = DateRange.day(opts.date)
491     else:
492         date = DateRange(opts.dateafter, opts.datebefore)
493
494     if sys.version_info < (3,):
495         # In Python 2, sys.argv is a bytestring (also note http://bugs.python.org/issue2128 for Windows systems)
496         if opts.outtmpl is not None:
497             opts.outtmpl = opts.outtmpl.decode(preferredencoding())
498     outtmpl =((opts.outtmpl is not None and opts.outtmpl)
499             or (opts.format == '-1' and opts.usetitle and u'%(title)s-%(id)s-%(format)s.%(ext)s')
500             or (opts.format == '-1' and u'%(id)s-%(format)s.%(ext)s')
501             or (opts.usetitle and opts.autonumber and u'%(autonumber)s-%(title)s-%(id)s.%(ext)s')
502             or (opts.usetitle and u'%(title)s-%(id)s.%(ext)s')
503             or (opts.useid and u'%(id)s.%(ext)s')
504             or (opts.autonumber and u'%(autonumber)s-%(id)s.%(ext)s')
505             or u'%(title)s-%(id)s.%(ext)s')
506
507     # YoutubeDL
508     ydl = YoutubeDL({
509         'usenetrc': opts.usenetrc,
510         'username': opts.username,
511         'password': opts.password,
512         'videopassword': opts.videopassword,
513         'quiet': (opts.quiet or opts.geturl or opts.gettitle or opts.getid or opts.getthumbnail or opts.getdescription or opts.getfilename or opts.getformat),
514         'forceurl': opts.geturl,
515         'forcetitle': opts.gettitle,
516         'forceid': opts.getid,
517         'forcethumbnail': opts.getthumbnail,
518         'forcedescription': opts.getdescription,
519         'forcefilename': opts.getfilename,
520         'forceformat': opts.getformat,
521         'simulate': opts.simulate,
522         'skip_download': (opts.skip_download or opts.simulate or opts.geturl or opts.gettitle or opts.getid or opts.getthumbnail or opts.getdescription or opts.getfilename or opts.getformat),
523         'format': opts.format,
524         'format_limit': opts.format_limit,
525         'listformats': opts.listformats,
526         'outtmpl': outtmpl,
527         'autonumber_size': opts.autonumber_size,
528         'restrictfilenames': opts.restrictfilenames,
529         'ignoreerrors': opts.ignoreerrors,
530         'ratelimit': opts.ratelimit,
531         'nooverwrites': opts.nooverwrites,
532         'retries': opts.retries,
533         'buffersize': opts.buffersize,
534         'noresizebuffer': opts.noresizebuffer,
535         'continuedl': opts.continue_dl,
536         'noprogress': opts.noprogress,
537         'progress_with_newline': opts.progress_with_newline,
538         'playliststart': opts.playliststart,
539         'playlistend': opts.playlistend,
540         'logtostderr': opts.outtmpl == '-',
541         'consoletitle': opts.consoletitle,
542         'nopart': opts.nopart,
543         'updatetime': opts.updatetime,
544         'writedescription': opts.writedescription,
545         'writeinfojson': opts.writeinfojson,
546         'writethumbnail': opts.writethumbnail,
547         'writesubtitles': opts.writesubtitles,
548         'writeautomaticsub': opts.writeautomaticsub,
549         'allsubtitles': opts.allsubtitles,
550         'listsubtitles': opts.listsubtitles,
551         'subtitlesformat': opts.subtitlesformat,
552         'subtitleslang': opts.subtitleslang,
553         'matchtitle': decodeOption(opts.matchtitle),
554         'rejecttitle': decodeOption(opts.rejecttitle),
555         'max_downloads': opts.max_downloads,
556         'prefer_free_formats': opts.prefer_free_formats,
557         'verbose': opts.verbose,
558         'dump_intermediate_pages': opts.dump_intermediate_pages,
559         'test': opts.test,
560         'keepvideo': opts.keepvideo,
561         'min_filesize': opts.min_filesize,
562         'max_filesize': opts.max_filesize,
563         'daterange': date,
564         })
565
566     if opts.verbose:
567         ydl.to_screen(u'[debug] youtube-dl version ' + __version__)
568         try:
569             sp = subprocess.Popen(['git', 'rev-parse', '--short', 'HEAD'], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
570                                   cwd=os.path.dirname(os.path.abspath(__file__)))
571             out, err = sp.communicate()
572             out = out.decode().strip()
573             if re.match('[0-9a-f]+', out):
574                 ydl.to_screen(u'[debug] Git HEAD: ' + out)
575         except:
576             pass
577         ydl.to_screen(u'[debug] Python version %s - %s' %(platform.python_version(), platform.platform()))
578         ydl.to_screen(u'[debug] Proxy map: ' + str(proxy_handler.proxies))
579
580     ydl.add_default_info_extractors()
581
582     # PostProcessors
583     if opts.extractaudio:
584         ydl.add_post_processor(FFmpegExtractAudioPP(preferredcodec=opts.audioformat, preferredquality=opts.audioquality, nopostoverwrites=opts.nopostoverwrites))
585     if opts.recodevideo:
586         ydl.add_post_processor(FFmpegVideoConvertor(preferedformat=opts.recodevideo))
587
588     # Update version
589     if opts.update_self:
590         update_self(ydl.to_screen, opts.verbose, sys.argv[0])
591
592     # Maybe do nothing
593     if len(all_urls) < 1:
594         if not opts.update_self:
595             parser.error(u'you must provide at least one URL')
596         else:
597             sys.exit()
598
599     try:
600         retcode = ydl.download(all_urls)
601     except MaxDownloadsReached:
602         ydl.to_screen(u'--max-download limit reached, aborting.')
603         retcode = 101
604
605     # Dump cookie jar if requested
606     if opts.cookiefile is not None:
607         try:
608             jar.save()
609         except (IOError, OSError) as err:
610             sys.exit(u'ERROR: unable to save cookie jar')
611
612     sys.exit(retcode)
613
614 def main(argv=None):
615     try:
616         _real_main(argv)
617     except DownloadError:
618         sys.exit(1)
619     except SameFileError:
620         sys.exit(u'ERROR: fixed output name but more than one file to download')
621     except KeyboardInterrupt:
622         sys.exit(u'\nERROR: Interrupted by user')