]> jfr.im git - yt-dlp.git/blame - youtube_dl/__init__.py
add info_dict testing to test_download
[yt-dlp.git] / youtube_dl / __init__.py
CommitLineData
235b3ba4
PH
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
02b324a2 4from __future__ import with_statement
9e8056d5 5from __future__ import absolute_import
02b324a2 6
3906e6ce 7__authors__ = (
59ae15a5
PH
8 'Ricardo Garcia Gonzalez',
9 'Danny Colligan',
10 'Benjamin Johnson',
11 'Vasyl\' Vavrychuk',
12 'Witold Baryluk',
13 'Paweł Paprota',
14 'Gergely Imreh',
15 'Rogério Brito',
16 'Philipp Hagemeister',
17 'Sören Schulze',
18 'Kevin Ngo',
19 'Ori Avtalion',
20 'shizeeg',
21 'Filippo Valsorda',
22 'Christian Albrecht',
88f6c78b 23 'Dave Vasilevsky',
59ae15a5 24 )
235b3ba4
PH
25
26__license__ = 'Public Domain'
235b3ba4 27
c9ed14e6 28import getpass
c9ed14e6 29import optparse
235b3ba4 30import os
235b3ba4 31import re
c9ed14e6 32import shlex
235b3ba4 33import socket
235b3ba4
PH
34import subprocess
35import sys
235b3ba4 36import warnings
235b3ba4 37
9e8056d5 38from .utils import *
cc51a7d4 39from .version import __version__
9e8056d5
PH
40from .FileDownloader import *
41from .InfoExtractors import *
42from .PostProcessor import *
235b3ba4
PH
43
44def updateSelf(downloader, filename):
5a304a76 45 """Update the program file with the latest version from the repository"""
59ae15a5 46
5a304a76 47 # TODO: at least, check https certificates
59ae15a5 48
5a304a76 49 from zipimport import zipimporter
59ae15a5 50
5a304a76
FV
51 API_URL = "https://api.github.com/repos/rg3/youtube-dl/downloads"
52 BIN_URL = "https://github.com/downloads/rg3/youtube-dl/youtube-dl"
53 EXE_URL = "https://github.com/downloads/rg3/youtube-dl/youtube-dl.exe"
54
55 if hasattr(sys, "frozen"): # PY2EXE
56 if not os.access(filename, os.W_OK):
57 sys.exit('ERROR: no write permissions on %s' % filename)
58
59 downloader.to_screen(u'Updating to latest version...')
60
61 urla = compat_urllib_request.urlopen(API_URL)
62 download = filter(lambda x: x["name"] == "youtube-dl.exe", json.loads(urla.read()))
63 if not download:
64 downloader.to_screen(u'ERROR: can\'t find the current version. Please try again later.')
65 return
66 newversion = download[0]["description"].strip()
67 if newversion == __version__:
68 downloader.to_screen(u'youtube-dl is up-to-date (' + __version__ + ')')
69 return
70 urla.close()
59ae15a5 71
59ae15a5
PH
72 exe = os.path.abspath(filename)
73 directory = os.path.dirname(exe)
74 if not os.access(directory, os.W_OK):
75 sys.exit('ERROR: no write permissions on %s' % directory)
76
77 try:
5a304a76 78 urlh = compat_urllib_request.urlopen(EXE_URL)
59ae15a5
PH
79 newcontent = urlh.read()
80 urlh.close()
81 with open(exe + '.new', 'wb') as outf:
82 outf.write(newcontent)
83 except (IOError, OSError) as err:
84 sys.exit('ERROR: unable to download latest version')
85
86 try:
87 bat = os.path.join(directory, 'youtube-dl-updater.bat')
88 b = open(bat, 'w')
89 b.write("""
f36cd076 90echo Updating youtube-dl...
bcfde70d 91ping 127.0.0.1 -n 5 -w 1000 > NUL
53e89361
FV
92move /Y "%s.new" "%s"
93del "%s"
59ae15a5
PH
94 \n""" %(exe, exe, bat))
95 b.close()
51937c08 96
59ae15a5
PH
97 os.startfile(bat)
98 except (IOError, OSError) as err:
99 sys.exit('ERROR: unable to overwrite current version')
53e89361 100
5a304a76
FV
101 elif isinstance(globals().get('__loader__'), zipimporter): # UNIX ZIP
102 if not os.access(filename, os.W_OK):
103 sys.exit('ERROR: no write permissions on %s' % filename)
104
105 downloader.to_screen(u'Updating to latest version...')
106
107 urla = compat_urllib_request.urlopen(API_URL)
108 download = [x for x in json.loads(urla.read().decode('utf8')) if x["name"] == "youtube-dl"]
109 if not download:
110 downloader.to_screen(u'ERROR: can\'t find the current version. Please try again later.')
111 return
112 newversion = download[0]["description"].strip()
113 if newversion == __version__:
114 downloader.to_screen(u'youtube-dl is up-to-date (' + __version__ + ')')
115 return
116 urla.close()
117
59ae15a5 118 try:
5a304a76 119 urlh = compat_urllib_request.urlopen(BIN_URL)
59ae15a5
PH
120 newcontent = urlh.read()
121 urlh.close()
122 except (IOError, OSError) as err:
123 sys.exit('ERROR: unable to download latest version')
235b3ba4 124
59ae15a5
PH
125 try:
126 with open(filename, 'wb') as outf:
127 outf.write(newcontent)
128 except (IOError, OSError) as err:
129 sys.exit('ERROR: unable to overwrite current version')
235b3ba4 130
5a304a76
FV
131 else:
132 downloader.to_screen(u'It looks like you installed youtube-dl with pip or setup.py. Please use that to update.')
133 return
134
59ae15a5 135 downloader.to_screen(u'Updated youtube-dl. Restart youtube-dl to use the new version.')
235b3ba4
PH
136
137def parseOpts():
59ae15a5
PH
138 def _readOptions(filename_bytes):
139 try:
140 optionf = open(filename_bytes)
141 except IOError:
142 return [] # silently skip if file is not present
143 try:
144 res = []
145 for l in optionf:
146 res += shlex.split(l, comments=True)
147 finally:
148 optionf.close()
149 return res
150
151 def _format_option_string(option):
152 ''' ('-o', '--option') -> -o, --format METAVAR'''
153
154 opts = []
155
156 if option._short_opts:
157 opts.append(option._short_opts[0])
158 if option._long_opts:
159 opts.append(option._long_opts[0])
160 if len(opts) > 1:
161 opts.insert(1, ', ')
162
163 if option.takes_value(): opts.append(' %s' % option.metavar)
164
165 return "".join(opts)
166
167 def _find_term_columns():
168 columns = os.environ.get('COLUMNS', None)
169 if columns:
170 return int(columns)
171
172 try:
173 sp = subprocess.Popen(['stty', 'size'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
174 out,err = sp.communicate()
175 return int(out.split()[1])
176 except:
177 pass
178 return None
179
180 max_width = 80
181 max_help_position = 80
182
183 # No need to wrap help messages if we're on a wide console
184 columns = _find_term_columns()
185 if columns: max_width = columns
186
187 fmt = optparse.IndentedHelpFormatter(width=max_width, max_help_position=max_help_position)
188 fmt.format_option_strings = _format_option_string
189
190 kw = {
191 'version' : __version__,
192 'formatter' : fmt,
193 'usage' : '%prog [options] url [url...]',
194 'conflict_handler' : 'resolve',
195 }
196
197 parser = optparse.OptionParser(**kw)
198
199 # option groups
200 general = optparse.OptionGroup(parser, 'General Options')
201 selection = optparse.OptionGroup(parser, 'Video Selection')
202 authentication = optparse.OptionGroup(parser, 'Authentication Options')
203 video_format = optparse.OptionGroup(parser, 'Video Format Options')
204 postproc = optparse.OptionGroup(parser, 'Post-processing Options')
205 filesystem = optparse.OptionGroup(parser, 'Filesystem Options')
206 verbosity = optparse.OptionGroup(parser, 'Verbosity / Simulation Options')
207
208 general.add_option('-h', '--help',
209 action='help', help='print this help text and exit')
210 general.add_option('-v', '--version',
211 action='version', help='print program version and exit')
212 general.add_option('-U', '--update',
213 action='store_true', dest='update_self', help='update this program to latest version')
214 general.add_option('-i', '--ignore-errors',
215 action='store_true', dest='ignoreerrors', help='continue on download errors', default=False)
216 general.add_option('-r', '--rate-limit',
217 dest='ratelimit', metavar='LIMIT', help='download rate limit (e.g. 50k or 44.6m)')
218 general.add_option('-R', '--retries',
219 dest='retries', metavar='RETRIES', help='number of retries (default is %default)', default=10)
220 general.add_option('--buffer-size',
221 dest='buffersize', metavar='SIZE', help='size of download buffer (e.g. 1024 or 16k) (default is %default)', default="1024")
222 general.add_option('--no-resize-buffer',
223 action='store_true', dest='noresizebuffer',
224 help='do not automatically adjust the buffer size. By default, the buffer size is automatically resized from an initial value of SIZE.', default=False)
225 general.add_option('--dump-user-agent',
226 action='store_true', dest='dump_user_agent',
227 help='display the current browser identification', default=False)
228 general.add_option('--user-agent',
229 dest='user_agent', help='specify a custom user agent', metavar='UA')
230 general.add_option('--list-extractors',
231 action='store_true', dest='list_extractors',
232 help='List all supported extractors and the URLs they would handle', default=False)
8d5d3a5d 233 general.add_option('--test', action='store_true', dest='test', default=False, help=optparse.SUPPRESS_HELP)
59ae15a5
PH
234
235 selection.add_option('--playlist-start',
236 dest='playliststart', metavar='NUMBER', help='playlist video to start at (default is %default)', default=1)
237 selection.add_option('--playlist-end',
238 dest='playlistend', metavar='NUMBER', help='playlist video to end at (default is last)', default=-1)
239 selection.add_option('--match-title', dest='matchtitle', metavar='REGEX',help='download only matching titles (regex or caseless sub-string)')
240 selection.add_option('--reject-title', dest='rejecttitle', metavar='REGEX',help='skip download for matching titles (regex or caseless sub-string)')
241 selection.add_option('--max-downloads', metavar='NUMBER', dest='max_downloads', help='Abort after downloading NUMBER files', default=None)
242
243 authentication.add_option('-u', '--username',
244 dest='username', metavar='USERNAME', help='account username')
245 authentication.add_option('-p', '--password',
246 dest='password', metavar='PASSWORD', help='account password')
247 authentication.add_option('-n', '--netrc',
248 action='store_true', dest='usenetrc', help='use .netrc authentication data', default=False)
249
250
251 video_format.add_option('-f', '--format',
252 action='store', dest='format', metavar='FORMAT', help='video format code')
253 video_format.add_option('--all-formats',
254 action='store_const', dest='format', help='download all available video formats', const='all')
255 video_format.add_option('--prefer-free-formats',
256 action='store_true', dest='prefer_free_formats', default=False, help='prefer free video formats unless a specific one is requested')
257 video_format.add_option('--max-quality',
258 action='store', dest='format_limit', metavar='FORMAT', help='highest quality format to download')
259 video_format.add_option('-F', '--list-formats',
260 action='store_true', dest='listformats', help='list all available formats (currently youtube only)')
261 video_format.add_option('--write-srt',
262 action='store_true', dest='writesubtitles',
263 help='write video closed captions to a .srt file (currently youtube only)', default=False)
264 video_format.add_option('--srt-lang',
265 action='store', dest='subtitleslang', metavar='LANG',
266 help='language of the closed captions to download (optional) use IETF language tags like \'en\'')
267
268
269 verbosity.add_option('-q', '--quiet',
270 action='store_true', dest='quiet', help='activates quiet mode', default=False)
271 verbosity.add_option('-s', '--simulate',
272 action='store_true', dest='simulate', help='do not download the video and do not write anything to disk', default=False)
273 verbosity.add_option('--skip-download',
274 action='store_true', dest='skip_download', help='do not download the video', default=False)
275 verbosity.add_option('-g', '--get-url',
276 action='store_true', dest='geturl', help='simulate, quiet but print URL', default=False)
277 verbosity.add_option('-e', '--get-title',
278 action='store_true', dest='gettitle', help='simulate, quiet but print title', default=False)
279 verbosity.add_option('--get-thumbnail',
280 action='store_true', dest='getthumbnail',
281 help='simulate, quiet but print thumbnail URL', default=False)
282 verbosity.add_option('--get-description',
283 action='store_true', dest='getdescription',
284 help='simulate, quiet but print video description', default=False)
285 verbosity.add_option('--get-filename',
286 action='store_true', dest='getfilename',
287 help='simulate, quiet but print output filename', default=False)
288 verbosity.add_option('--get-format',
289 action='store_true', dest='getformat',
290 help='simulate, quiet but print output format', default=False)
291 verbosity.add_option('--no-progress',
292 action='store_true', dest='noprogress', help='do not print progress bar', default=False)
293 verbosity.add_option('--console-title',
294 action='store_true', dest='consoletitle',
295 help='display progress in console titlebar', default=False)
296 verbosity.add_option('-v', '--verbose',
297 action='store_true', dest='verbose', help='print various debugging information', default=False)
298
299
300 filesystem.add_option('-t', '--title',
301 action='store_true', dest='usetitle', help='use title in file name', default=False)
302 filesystem.add_option('--id',
303 action='store_true', dest='useid', help='use video ID in file name', default=False)
304 filesystem.add_option('-l', '--literal',
305 action='store_true', dest='usetitle', help='[deprecated] alias of --title', default=False)
306 filesystem.add_option('-A', '--auto-number',
307 action='store_true', dest='autonumber',
308 help='number downloaded files starting from 00000', default=False)
309 filesystem.add_option('-o', '--output',
077174f4 310 dest='outtmpl', metavar='TEMPLATE', help='output filename template. Use %(title)s to get the title, %(uploader)s for the uploader name, %(autonumber)s to get an automatically incremented number, %(ext)s for the filename extension, %(upload_date)s for the upload date (YYYYMMDD), %(extractor)s for the provider (youtube, metacafe, etc), %(id)s for the video id and %% for a literal percent. Use - to output to stdout. Can also be used to download to a different directory, for example with -o \'/my/downloads/%(uploader)s/%(title)s-%(id)s.%(ext)s\' .')
59ae15a5
PH
311 filesystem.add_option('--restrict-filenames',
312 action='store_true', dest='restrictfilenames',
313 help='Restrict filenames to only ASCII characters, and avoid "&" and spaces in filenames', default=False)
314 filesystem.add_option('-a', '--batch-file',
315 dest='batchfile', metavar='FILE', help='file containing URLs to download (\'-\' for stdin)')
316 filesystem.add_option('-w', '--no-overwrites',
317 action='store_true', dest='nooverwrites', help='do not overwrite files', default=False)
318 filesystem.add_option('-c', '--continue',
319 action='store_true', dest='continue_dl', help='resume partially downloaded files', default=True)
320 filesystem.add_option('--no-continue',
321 action='store_false', dest='continue_dl',
322 help='do not resume partially downloaded files (restart from beginning)')
323 filesystem.add_option('--cookies',
324 dest='cookiefile', metavar='FILE', help='file to read cookies from and dump cookie jar in')
325 filesystem.add_option('--no-part',
326 action='store_true', dest='nopart', help='do not use .part files', default=False)
327 filesystem.add_option('--no-mtime',
328 action='store_false', dest='updatetime',
329 help='do not use the Last-modified header to set the file modification time', default=True)
330 filesystem.add_option('--write-description',
331 action='store_true', dest='writedescription',
332 help='write video description to a .description file', default=False)
333 filesystem.add_option('--write-info-json',
334 action='store_true', dest='writeinfojson',
335 help='write video metadata to a .info.json file', default=False)
336
337
338 postproc.add_option('-x', '--extract-audio', action='store_true', dest='extractaudio', default=False,
339 help='convert video files to audio-only files (requires ffmpeg or avconv and ffprobe or avprobe)')
340 postproc.add_option('--audio-format', metavar='FORMAT', dest='audioformat', default='best',
341 help='"best", "aac", "vorbis", "mp3", "m4a", or "wav"; best by default')
342 postproc.add_option('--audio-quality', metavar='QUALITY', dest='audioquality', default='5',
343 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)')
344 postproc.add_option('-k', '--keep-video', action='store_true', dest='keepvideo', default=False,
345 help='keeps the video file on disk after the post-processing; the video is erased by default')
346
347
348 parser.add_option_group(general)
349 parser.add_option_group(selection)
350 parser.add_option_group(filesystem)
351 parser.add_option_group(verbosity)
352 parser.add_option_group(video_format)
353 parser.add_option_group(authentication)
354 parser.add_option_group(postproc)
355
356 xdg_config_home = os.environ.get('XDG_CONFIG_HOME')
357 if xdg_config_home:
358 userConf = os.path.join(xdg_config_home, 'youtube-dl.conf')
359 else:
360 userConf = os.path.join(os.path.expanduser('~'), '.config', 'youtube-dl.conf')
361 argv = _readOptions('/etc/youtube-dl.conf') + _readOptions(userConf) + sys.argv[1:]
362 opts, args = parser.parse_args(argv)
363
364 return parser, opts, args
235b3ba4
PH
365
366def gen_extractors():
59ae15a5
PH
367 """ Return a list of an instance of every supported extractor.
368 The order does matter; the first extractor matched is the one handling the URL.
369 """
370 return [
371 YoutubePlaylistIE(),
372 YoutubeChannelIE(),
373 YoutubeUserIE(),
374 YoutubeSearchIE(),
375 YoutubeIE(),
376 MetacafeIE(),
377 DailymotionIE(),
59ae15a5
PH
378 GoogleSearchIE(),
379 PhotobucketIE(),
380 YahooIE(),
381 YahooSearchIE(),
382 DepositFilesIE(),
383 FacebookIE(),
384 BlipTVUserIE(),
385 BlipTVIE(),
386 VimeoIE(),
387 MyVideoIE(),
388 ComedyCentralIE(),
389 EscapistIE(),
390 CollegeHumorIE(),
391 XVideosIE(),
392 SoundcloudIE(),
393 InfoQIE(),
394 MixcloudIE(),
395 StanfordOpenClassroomIE(),
396 MTVIE(),
397 YoukuIE(),
398 XNXXIE(),
399 GooglePlusIE(),
400 ArteTvIE(),
4cc3d074 401 NBAIE(),
0b40544f 402 JustinTVIE(),
59ae15a5
PH
403 GenericIE()
404 ]
235b3ba4
PH
405
406def _real_main():
59ae15a5
PH
407 parser, opts, args = parseOpts()
408
409 # Open appropriate CookieJar
410 if opts.cookiefile is None:
411 jar = compat_cookiejar.CookieJar()
412 else:
413 try:
414 jar = compat_cookiejar.MozillaCookieJar(opts.cookiefile)
415 if os.path.isfile(opts.cookiefile) and os.access(opts.cookiefile, os.R_OK):
416 jar.load()
417 except (IOError, OSError) as err:
418 sys.exit(u'ERROR: unable to open cookie file')
419 # Set user agent
420 if opts.user_agent is not None:
421 std_headers['User-Agent'] = opts.user_agent
422
423 # Dump user agent
424 if opts.dump_user_agent:
425 print(std_headers['User-Agent'])
426 sys.exit(0)
427
428 # Batch file verification
429 batchurls = []
430 if opts.batchfile is not None:
431 try:
432 if opts.batchfile == '-':
433 batchfd = sys.stdin
434 else:
435 batchfd = open(opts.batchfile, 'r')
436 batchurls = batchfd.readlines()
437 batchurls = [x.strip() for x in batchurls]
438 batchurls = [x for x in batchurls if len(x) > 0 and not re.search(r'^[#/;]', x)]
439 except IOError:
440 sys.exit(u'ERROR: batch file could not be read')
441 all_urls = batchurls + args
442 all_urls = [url.strip() for url in all_urls]
443
444 # General configuration
445 cookie_processor = compat_urllib_request.HTTPCookieProcessor(jar)
446 proxy_handler = compat_urllib_request.ProxyHandler()
447 opener = compat_urllib_request.build_opener(proxy_handler, cookie_processor, YoutubeDLHandler())
448 compat_urllib_request.install_opener(opener)
449 socket.setdefaulttimeout(300) # 5 minutes should be enough (famous last words)
450
451 extractors = gen_extractors()
452
453 if opts.list_extractors:
454 for ie in extractors:
b08e09c3 455 print(ie.IE_NAME + (' (CURRENTLY BROKEN)' if not ie._WORKING else ''))
59ae15a5
PH
456 matchedUrls = filter(lambda url: ie.suitable(url), all_urls)
457 all_urls = filter(lambda url: url not in matchedUrls, all_urls)
458 for mu in matchedUrls:
459 print(u' ' + mu)
460 sys.exit(0)
461
462 # Conflicting, missing and erroneous options
463 if opts.usenetrc and (opts.username is not None or opts.password is not None):
464 parser.error(u'using .netrc conflicts with giving username/password')
465 if opts.password is not None and opts.username is None:
466 parser.error(u'account username missing')
467 if opts.outtmpl is not None and (opts.usetitle or opts.autonumber or opts.useid):
468 parser.error(u'using output template conflicts with using title, video ID or auto number')
469 if opts.usetitle and opts.useid:
470 parser.error(u'using title conflicts with using video ID')
471 if opts.username is not None and opts.password is None:
472 opts.password = getpass.getpass(u'Type account password and press return:')
473 if opts.ratelimit is not None:
474 numeric_limit = FileDownloader.parse_bytes(opts.ratelimit)
475 if numeric_limit is None:
476 parser.error(u'invalid rate limit specified')
477 opts.ratelimit = numeric_limit
478 if opts.retries is not None:
479 try:
480 opts.retries = int(opts.retries)
481 except (TypeError, ValueError) as err:
482 parser.error(u'invalid retry count specified')
483 if opts.buffersize is not None:
484 numeric_buffersize = FileDownloader.parse_bytes(opts.buffersize)
485 if numeric_buffersize is None:
486 parser.error(u'invalid buffer size specified')
487 opts.buffersize = numeric_buffersize
488 try:
489 opts.playliststart = int(opts.playliststart)
490 if opts.playliststart <= 0:
491 raise ValueError(u'Playlist start must be positive')
492 except (TypeError, ValueError) as err:
493 parser.error(u'invalid playlist start number specified')
494 try:
495 opts.playlistend = int(opts.playlistend)
496 if opts.playlistend != -1 and (opts.playlistend <= 0 or opts.playlistend < opts.playliststart):
497 raise ValueError(u'Playlist end must be greater than playlist start')
498 except (TypeError, ValueError) as err:
499 parser.error(u'invalid playlist end number specified')
500 if opts.extractaudio:
501 if opts.audioformat not in ['best', 'aac', 'mp3', 'vorbis', 'm4a', 'wav']:
502 parser.error(u'invalid audio format specified')
503 if opts.audioquality:
504 opts.audioquality = opts.audioquality.strip('k').strip('K')
505 if not opts.audioquality.isdigit():
506 parser.error(u'invalid audio quality specified')
507
5cb9c312
PH
508 if sys.version_info < (3,):
509 # In Python 2, sys.argv is a bytestring (also note http://bugs.python.org/issue2128 for Windows systems)
0be41ec2
PH
510 if opts.outtmpl is not None:
511 opts.outtmpl = opts.outtmpl.decode(preferredencoding())
5cb9c312
PH
512 outtmpl =((opts.outtmpl is not None and opts.outtmpl)
513 or (opts.format == '-1' and opts.usetitle and u'%(title)s-%(id)s-%(format)s.%(ext)s')
514 or (opts.format == '-1' and u'%(id)s-%(format)s.%(ext)s')
515 or (opts.usetitle and opts.autonumber and u'%(autonumber)s-%(title)s-%(id)s.%(ext)s')
516 or (opts.usetitle and u'%(title)s-%(id)s.%(ext)s')
517 or (opts.useid and u'%(id)s.%(ext)s')
518 or (opts.autonumber and u'%(autonumber)s-%(id)s.%(ext)s')
519 or u'%(id)s.%(ext)s')
59ae15a5
PH
520 # File downloader
521 fd = FileDownloader({
522 'usenetrc': opts.usenetrc,
523 'username': opts.username,
524 'password': opts.password,
525 'quiet': (opts.quiet or opts.geturl or opts.gettitle or opts.getthumbnail or opts.getdescription or opts.getfilename or opts.getformat),
526 'forceurl': opts.geturl,
527 'forcetitle': opts.gettitle,
528 'forcethumbnail': opts.getthumbnail,
529 'forcedescription': opts.getdescription,
530 'forcefilename': opts.getfilename,
531 'forceformat': opts.getformat,
532 'simulate': opts.simulate,
533 'skip_download': (opts.skip_download or opts.simulate or opts.geturl or opts.gettitle or opts.getthumbnail or opts.getdescription or opts.getfilename or opts.getformat),
534 'format': opts.format,
535 'format_limit': opts.format_limit,
536 'listformats': opts.listformats,
5cb9c312 537 'outtmpl': outtmpl,
59ae15a5
PH
538 'restrictfilenames': opts.restrictfilenames,
539 'ignoreerrors': opts.ignoreerrors,
540 'ratelimit': opts.ratelimit,
541 'nooverwrites': opts.nooverwrites,
542 'retries': opts.retries,
543 'buffersize': opts.buffersize,
544 'noresizebuffer': opts.noresizebuffer,
545 'continuedl': opts.continue_dl,
546 'noprogress': opts.noprogress,
547 'playliststart': opts.playliststart,
548 'playlistend': opts.playlistend,
549 'logtostderr': opts.outtmpl == '-',
550 'consoletitle': opts.consoletitle,
551 'nopart': opts.nopart,
552 'updatetime': opts.updatetime,
553 'writedescription': opts.writedescription,
554 'writeinfojson': opts.writeinfojson,
555 'writesubtitles': opts.writesubtitles,
556 'subtitleslang': opts.subtitleslang,
557 'matchtitle': opts.matchtitle,
558 'rejecttitle': opts.rejecttitle,
559 'max_downloads': opts.max_downloads,
560 'prefer_free_formats': opts.prefer_free_formats,
561 'verbose': opts.verbose,
8d5d3a5d 562 'test': opts.test,
59ae15a5
PH
563 })
564
565 if opts.verbose:
566 fd.to_screen(u'[debug] Proxy map: ' + str(proxy_handler.proxies))
567
568 for extractor in extractors:
569 fd.add_info_extractor(extractor)
570
571 # PostProcessors
572 if opts.extractaudio:
573 fd.add_post_processor(FFmpegExtractAudioPP(preferredcodec=opts.audioformat, preferredquality=opts.audioquality, keepvideo=opts.keepvideo))
574
575 # Update version
576 if opts.update_self:
577 updateSelf(fd, sys.argv[0])
578
579 # Maybe do nothing
580 if len(all_urls) < 1:
581 if not opts.update_self:
582 parser.error(u'you must provide at least one URL')
583 else:
584 sys.exit()
585
586 try:
587 retcode = fd.download(all_urls)
588 except MaxDownloadsReached:
589 fd.to_screen(u'--max-download limit reached, aborting.')
590 retcode = 101
591
592 # Dump cookie jar if requested
593 if opts.cookiefile is not None:
594 try:
595 jar.save()
596 except (IOError, OSError) as err:
597 sys.exit(u'ERROR: unable to save cookie jar')
598
599 sys.exit(retcode)
235b3ba4
PH
600
601def main():
59ae15a5
PH
602 try:
603 _real_main()
604 except DownloadError:
605 sys.exit(1)
606 except SameFileError:
607 sys.exit(u'ERROR: fixed output name but more than one file to download')
608 except KeyboardInterrupt:
609 sys.exit(u'\nERROR: Interrupted by user')