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