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