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