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