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