]> Raphaël G. Git Repositories - youtubedl/blob - youtube_dl/__init__.py
2acaab66859c3a268083ee738fbf6ea9d8c518f0
[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('--only-sub',
195 action='store_true', dest='skip_download',
196 help='[deprecated] alias of --skip-download', default=False)
197 video_format.add_option('--all-subs',
198 action='store_true', dest='allsubtitles',
199 help='downloads all the available subtitles of the video (currently youtube only)', default=False)
200 video_format.add_option('--list-subs',
201 action='store_true', dest='listsubtitles',
202 help='lists all available subtitles for the video (currently youtube only)', default=False)
203 video_format.add_option('--sub-format',
204 action='store', dest='subtitlesformat', metavar='FORMAT',
205 help='subtitle format [srt/sbv] (default=srt) (currently youtube only)', default='srt')
206 video_format.add_option('--sub-lang', '--srt-lang',
207 action='store', dest='subtitleslang', metavar='LANG',
208 help='language of the subtitles to download (optional) use IETF language tags like \'en\'')
209
210 verbosity.add_option('-q', '--quiet',
211 action='store_true', dest='quiet', help='activates quiet mode', default=False)
212 verbosity.add_option('-s', '--simulate',
213 action='store_true', dest='simulate', help='do not download the video and do not write anything to disk', default=False)
214 verbosity.add_option('--skip-download',
215 action='store_true', dest='skip_download', help='do not download the video', default=False)
216 verbosity.add_option('-g', '--get-url',
217 action='store_true', dest='geturl', help='simulate, quiet but print URL', default=False)
218 verbosity.add_option('-e', '--get-title',
219 action='store_true', dest='gettitle', help='simulate, quiet but print title', default=False)
220 verbosity.add_option('--get-id',
221 action='store_true', dest='getid', help='simulate, quiet but print id', default=False)
222 verbosity.add_option('--get-thumbnail',
223 action='store_true', dest='getthumbnail',
224 help='simulate, quiet but print thumbnail URL', default=False)
225 verbosity.add_option('--get-description',
226 action='store_true', dest='getdescription',
227 help='simulate, quiet but print video description', default=False)
228 verbosity.add_option('--get-filename',
229 action='store_true', dest='getfilename',
230 help='simulate, quiet but print output filename', default=False)
231 verbosity.add_option('--get-format',
232 action='store_true', dest='getformat',
233 help='simulate, quiet but print output format', default=False)
234 verbosity.add_option('--newline',
235 action='store_true', dest='progress_with_newline', help='output progress bar as new lines', default=False)
236 verbosity.add_option('--no-progress',
237 action='store_true', dest='noprogress', help='do not print progress bar', default=False)
238 verbosity.add_option('--console-title',
239 action='store_true', dest='consoletitle',
240 help='display progress in console titlebar', default=False)
241 verbosity.add_option('-v', '--verbose',
242 action='store_true', dest='verbose', help='print various debugging information', default=False)
243 verbosity.add_option('--dump-intermediate-pages',
244 action='store_true', dest='dump_intermediate_pages', default=False,
245 help='print downloaded pages to debug problems(very verbose)')
246
247 filesystem.add_option('-t', '--title',
248 action='store_true', dest='usetitle', help='use title in file name (default)', default=False)
249 filesystem.add_option('--id',
250 action='store_true', dest='useid', help='use only video ID in file name', default=False)
251 filesystem.add_option('-l', '--literal',
252 action='store_true', dest='usetitle', help='[deprecated] alias of --title', default=False)
253 filesystem.add_option('-A', '--auto-number',
254 action='store_true', dest='autonumber',
255 help='number downloaded files starting from 00000', default=False)
256 filesystem.add_option('-o', '--output',
257 dest='outtmpl', metavar='TEMPLATE',
258 help=('output filename template. Use %(title)s to get the title, '
259 '%(uploader)s for the uploader name, %(uploader_id)s for the uploader nickname if different, '
260 '%(autonumber)s to get an automatically incremented number, '
261 '%(ext)s for the filename extension, %(upload_date)s for the upload date (YYYYMMDD), '
262 '%(extractor)s for the provider (youtube, metacafe, etc), '
263 '%(id)s for the video id , %(playlist)s for the playlist the video is in, '
264 '%(playlist_index)s for the position in the playlist and %% for a literal percent. '
265 'Use - to output to stdout. Can also be used to download to a different directory, '
266 'for example with -o \'/my/downloads/%(uploader)s/%(title)s-%(id)s.%(ext)s\' .'))
267 filesystem.add_option('--autonumber-size',
268 dest='autonumber_size', metavar='NUMBER',
269 help='Specifies the number of digits in %(autonumber)s when it is present in output filename template or --autonumber option is given')
270 filesystem.add_option('--restrict-filenames',
271 action='store_true', dest='restrictfilenames',
272 help='Restrict filenames to only ASCII characters, and avoid "&" and spaces in filenames', default=False)
273 filesystem.add_option('-a', '--batch-file',
274 dest='batchfile', metavar='FILE', help='file containing URLs to download (\'-\' for stdin)')
275 filesystem.add_option('-w', '--no-overwrites',
276 action='store_true', dest='nooverwrites', help='do not overwrite files', default=False)
277 filesystem.add_option('-c', '--continue',
278 action='store_true', dest='continue_dl', help='resume partially downloaded files', default=True)
279 filesystem.add_option('--no-continue',
280 action='store_false', dest='continue_dl',
281 help='do not resume partially downloaded files (restart from beginning)')
282 filesystem.add_option('--cookies',
283 dest='cookiefile', metavar='FILE', help='file to read cookies from and dump cookie jar in')
284 filesystem.add_option('--no-part',
285 action='store_true', dest='nopart', help='do not use .part files', default=False)
286 filesystem.add_option('--no-mtime',
287 action='store_false', dest='updatetime',
288 help='do not use the Last-modified header to set the file modification time', default=True)
289 filesystem.add_option('--write-description',
290 action='store_true', dest='writedescription',
291 help='write video description to a .description file', default=False)
292 filesystem.add_option('--write-info-json',
293 action='store_true', dest='writeinfojson',
294 help='write video metadata to a .info.json file', default=False)
295 filesystem.add_option('--write-thumbnail',
296 action='store_true', dest='writethumbnail',
297 help='write thumbnail image to disk', default=False)
298
299
300 postproc.add_option('-x', '--extract-audio', action='store_true', dest='extractaudio', default=False,
301 help='convert video files to audio-only files (requires ffmpeg or avconv and ffprobe or avprobe)')
302 postproc.add_option('--audio-format', metavar='FORMAT', dest='audioformat', default='best',
303 help='"best", "aac", "vorbis", "mp3", "m4a", "opus", or "wav"; best by default')
304 postproc.add_option('--audio-quality', metavar='QUALITY', dest='audioquality', default='5',
305 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)')
306 postproc.add_option('--recode-video', metavar='FORMAT', dest='recodevideo', default=None,
307 help='Encode the video to another format if necessary (currently supported: mp4|flv|ogg|webm)')
308 postproc.add_option('-k', '--keep-video', action='store_true', dest='keepvideo', default=False,
309 help='keeps the video file on disk after the post-processing; the video is erased by default')
310 postproc.add_option('--no-post-overwrites', action='store_true', dest='nopostoverwrites', default=False,
311 help='do not overwrite post-processed files; the post-processed files are overwritten by default')
312
313
314 parser.add_option_group(general)
315 parser.add_option_group(selection)
316 parser.add_option_group(filesystem)
317 parser.add_option_group(verbosity)
318 parser.add_option_group(video_format)
319 parser.add_option_group(authentication)
320 parser.add_option_group(postproc)
321
322 if overrideArguments is not None:
323 opts, args = parser.parse_args(overrideArguments)
324 if opts.verbose:
325 sys.stderr.write(u'[debug] Override config: ' + repr(overrideArguments) + '\n')
326 else:
327 xdg_config_home = os.environ.get('XDG_CONFIG_HOME')
328 if xdg_config_home:
329 userConfFile = os.path.join(xdg_config_home, 'youtube-dl.conf')
330 else:
331 userConfFile = os.path.join(os.path.expanduser('~'), '.config', 'youtube-dl.conf')
332 systemConf = _readOptions('/etc/youtube-dl.conf')
333 userConf = _readOptions(userConfFile)
334 commandLineConf = sys.argv[1:]
335 argv = systemConf + userConf + commandLineConf
336 opts, args = parser.parse_args(argv)
337 if opts.verbose:
338 sys.stderr.write(u'[debug] System config: ' + repr(systemConf) + '\n')
339 sys.stderr.write(u'[debug] User config: ' + repr(userConf) + '\n')
340 sys.stderr.write(u'[debug] Command-line args: ' + repr(commandLineConf) + '\n')
341
342 return parser, opts, args
343
344 def _real_main(argv=None):
345 # Compatibility fixes for Windows
346 if sys.platform == 'win32':
347 # https://github.com/rg3/youtube-dl/issues/820
348 codecs.register(lambda name: codecs.lookup('utf-8') if name == 'cp65001' else None)
349
350 parser, opts, args = parseOpts(argv)
351
352 # Open appropriate CookieJar
353 if opts.cookiefile is None:
354 jar = compat_cookiejar.CookieJar()
355 else:
356 try:
357 jar = compat_cookiejar.MozillaCookieJar(opts.cookiefile)
358 if os.access(opts.cookiefile, os.R_OK):
359 jar.load()
360 except (IOError, OSError) as err:
361 if opts.verbose:
362 traceback.print_exc()
363 sys.stderr.write(u'ERROR: unable to open cookie file\n')
364 sys.exit(101)
365 # Set user agent
366 if opts.user_agent is not None:
367 std_headers['User-Agent'] = opts.user_agent
368
369 # Set referer
370 if opts.referer is not None:
371 std_headers['Referer'] = opts.referer
372
373 # Dump user agent
374 if opts.dump_user_agent:
375 compat_print(std_headers['User-Agent'])
376 sys.exit(0)
377
378 # Batch file verification
379 batchurls = []
380 if opts.batchfile is not None:
381 try:
382 if opts.batchfile == '-':
383 batchfd = sys.stdin
384 else:
385 batchfd = open(opts.batchfile, 'r')
386 batchurls = batchfd.readlines()
387 batchurls = [x.strip() for x in batchurls]
388 batchurls = [x for x in batchurls if len(x) > 0 and not re.search(r'^[#/;]', x)]
389 except IOError:
390 sys.exit(u'ERROR: batch file could not be read')
391 all_urls = batchurls + args
392 all_urls = [url.strip() for url in all_urls]
393
394 # General configuration
395 cookie_processor = compat_urllib_request.HTTPCookieProcessor(jar)
396 if opts.proxy is not None:
397 if opts.proxy == '':
398 proxies = {}
399 else:
400 proxies = {'http': opts.proxy, 'https': opts.proxy}
401 else:
402 proxies = compat_urllib_request.getproxies()
403 # Set HTTPS proxy to HTTP one if given (https://github.com/rg3/youtube-dl/issues/805)
404 if 'http' in proxies and 'https' not in proxies:
405 proxies['https'] = proxies['http']
406 proxy_handler = compat_urllib_request.ProxyHandler(proxies)
407 https_handler = make_HTTPS_handler(opts)
408 opener = compat_urllib_request.build_opener(https_handler, proxy_handler, cookie_processor, YoutubeDLHandler())
409 compat_urllib_request.install_opener(opener)
410 socket.setdefaulttimeout(300) # 5 minutes should be enough (famous last words)
411
412 extractors = gen_extractors()
413
414 if opts.list_extractors:
415 for ie in extractors:
416 compat_print(ie.IE_NAME + (' (CURRENTLY BROKEN)' if not ie._WORKING else ''))
417 matchedUrls = [url for url in all_urls if ie.suitable(url)]
418 all_urls = [url for url in all_urls if url not in matchedUrls]
419 for mu in matchedUrls:
420 compat_print(u' ' + mu)
421 sys.exit(0)
422
423 # Conflicting, missing and erroneous options
424 if opts.usenetrc and (opts.username is not None or opts.password is not None):
425 parser.error(u'using .netrc conflicts with giving username/password')
426 if opts.password is not None and opts.username is None:
427 parser.error(u' account username missing\n')
428 if opts.outtmpl is not None and (opts.usetitle or opts.autonumber or opts.useid):
429 parser.error(u'using output template conflicts with using title, video ID or auto number')
430 if opts.usetitle and opts.useid:
431 parser.error(u'using title conflicts with using video ID')
432 if opts.username is not None and opts.password is None:
433 opts.password = getpass.getpass(u'Type account password and press return:')
434 if opts.ratelimit is not None:
435 numeric_limit = FileDownloader.parse_bytes(opts.ratelimit)
436 if numeric_limit is None:
437 parser.error(u'invalid rate limit specified')
438 opts.ratelimit = numeric_limit
439 if opts.min_filesize is not None:
440 numeric_limit = FileDownloader.parse_bytes(opts.min_filesize)
441 if numeric_limit is None:
442 parser.error(u'invalid min_filesize specified')
443 opts.min_filesize = numeric_limit
444 if opts.max_filesize is not None:
445 numeric_limit = FileDownloader.parse_bytes(opts.max_filesize)
446 if numeric_limit is None:
447 parser.error(u'invalid max_filesize specified')
448 opts.max_filesize = numeric_limit
449 if opts.retries is not None:
450 try:
451 opts.retries = int(opts.retries)
452 except (TypeError, ValueError) as err:
453 parser.error(u'invalid retry count specified')
454 if opts.buffersize is not None:
455 numeric_buffersize = FileDownloader.parse_bytes(opts.buffersize)
456 if numeric_buffersize is None:
457 parser.error(u'invalid buffer size specified')
458 opts.buffersize = numeric_buffersize
459 try:
460 opts.playliststart = int(opts.playliststart)
461 if opts.playliststart <= 0:
462 raise ValueError(u'Playlist start must be positive')
463 except (TypeError, ValueError) as err:
464 parser.error(u'invalid playlist start number specified')
465 try:
466 opts.playlistend = int(opts.playlistend)
467 if opts.playlistend != -1 and (opts.playlistend <= 0 or opts.playlistend < opts.playliststart):
468 raise ValueError(u'Playlist end must be greater than playlist start')
469 except (TypeError, ValueError) as err:
470 parser.error(u'invalid playlist end number specified')
471 if opts.extractaudio:
472 if opts.audioformat not in ['best', 'aac', 'mp3', 'm4a', 'opus', 'vorbis', 'wav']:
473 parser.error(u'invalid audio format specified')
474 if opts.audioquality:
475 opts.audioquality = opts.audioquality.strip('k').strip('K')
476 if not opts.audioquality.isdigit():
477 parser.error(u'invalid audio quality specified')
478 if opts.recodevideo is not None:
479 if opts.recodevideo not in ['mp4', 'flv', 'webm', 'ogg']:
480 parser.error(u'invalid video recode format specified')
481 if opts.date is not None:
482 date = DateRange.day(opts.date)
483 else:
484 date = DateRange(opts.dateafter, opts.datebefore)
485
486 if sys.version_info < (3,):
487 # In Python 2, sys.argv is a bytestring (also note http://bugs.python.org/issue2128 for Windows systems)
488 if opts.outtmpl is not None:
489 opts.outtmpl = opts.outtmpl.decode(preferredencoding())
490 outtmpl =((opts.outtmpl is not None and opts.outtmpl)
491 or (opts.format == '-1' and opts.usetitle and u'%(title)s-%(id)s-%(format)s.%(ext)s')
492 or (opts.format == '-1' and u'%(id)s-%(format)s.%(ext)s')
493 or (opts.usetitle and opts.autonumber and u'%(autonumber)s-%(title)s-%(id)s.%(ext)s')
494 or (opts.usetitle and u'%(title)s-%(id)s.%(ext)s')
495 or (opts.useid and u'%(id)s.%(ext)s')
496 or (opts.autonumber and u'%(autonumber)s-%(id)s.%(ext)s')
497 or u'%(title)s-%(id)s.%(ext)s')
498
499 # YoutubeDL
500 ydl = YoutubeDL({
501 'usenetrc': opts.usenetrc,
502 'username': opts.username,
503 'password': opts.password,
504 'videopassword': opts.videopassword,
505 'quiet': (opts.quiet or opts.geturl or opts.gettitle or opts.getid or opts.getthumbnail or opts.getdescription or opts.getfilename or opts.getformat),
506 'forceurl': opts.geturl,
507 'forcetitle': opts.gettitle,
508 'forceid': opts.getid,
509 'forcethumbnail': opts.getthumbnail,
510 'forcedescription': opts.getdescription,
511 'forcefilename': opts.getfilename,
512 'forceformat': opts.getformat,
513 'simulate': opts.simulate,
514 '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),
515 'format': opts.format,
516 'format_limit': opts.format_limit,
517 'listformats': opts.listformats,
518 'outtmpl': outtmpl,
519 'autonumber_size': opts.autonumber_size,
520 'restrictfilenames': opts.restrictfilenames,
521 'ignoreerrors': opts.ignoreerrors,
522 'ratelimit': opts.ratelimit,
523 'nooverwrites': opts.nooverwrites,
524 'retries': opts.retries,
525 'buffersize': opts.buffersize,
526 'noresizebuffer': opts.noresizebuffer,
527 'continuedl': opts.continue_dl,
528 'noprogress': opts.noprogress,
529 'progress_with_newline': opts.progress_with_newline,
530 'playliststart': opts.playliststart,
531 'playlistend': opts.playlistend,
532 'logtostderr': opts.outtmpl == '-',
533 'consoletitle': opts.consoletitle,
534 'nopart': opts.nopart,
535 'updatetime': opts.updatetime,
536 'writedescription': opts.writedescription,
537 'writeinfojson': opts.writeinfojson,
538 'writethumbnail': opts.writethumbnail,
539 'writesubtitles': opts.writesubtitles,
540 'allsubtitles': opts.allsubtitles,
541 'listsubtitles': opts.listsubtitles,
542 'subtitlesformat': opts.subtitlesformat,
543 'subtitleslang': opts.subtitleslang,
544 'matchtitle': decodeOption(opts.matchtitle),
545 'rejecttitle': decodeOption(opts.rejecttitle),
546 'max_downloads': opts.max_downloads,
547 'prefer_free_formats': opts.prefer_free_formats,
548 'verbose': opts.verbose,
549 'dump_intermediate_pages': opts.dump_intermediate_pages,
550 'test': opts.test,
551 'keepvideo': opts.keepvideo,
552 'min_filesize': opts.min_filesize,
553 'max_filesize': opts.max_filesize,
554 'daterange': date,
555 })
556
557 if opts.verbose:
558 ydl.to_screen(u'[debug] youtube-dl version ' + __version__)
559 try:
560 sp = subprocess.Popen(['git', 'rev-parse', '--short', 'HEAD'], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
561 cwd=os.path.dirname(os.path.abspath(__file__)))
562 out, err = sp.communicate()
563 out = out.decode().strip()
564 if re.match('[0-9a-f]+', out):
565 ydl.to_screen(u'[debug] Git HEAD: ' + out)
566 except:
567 pass
568 ydl.to_screen(u'[debug] Python version %s - %s' %(platform.python_version(), platform.platform()))
569 ydl.to_screen(u'[debug] Proxy map: ' + str(proxy_handler.proxies))
570
571 for extractor in extractors:
572 ydl.add_info_extractor(extractor)
573
574 # PostProcessors
575 if opts.extractaudio:
576 ydl.add_post_processor(FFmpegExtractAudioPP(preferredcodec=opts.audioformat, preferredquality=opts.audioquality, nopostoverwrites=opts.nopostoverwrites))
577 if opts.recodevideo:
578 ydl.add_post_processor(FFmpegVideoConvertor(preferedformat=opts.recodevideo))
579
580 # Update version
581 if opts.update_self:
582 update_self(ydl.to_screen, opts.verbose, sys.argv[0])
583
584 # Maybe do nothing
585 if len(all_urls) < 1:
586 if not opts.update_self:
587 parser.error(u'you must provide at least one URL')
588 else:
589 sys.exit()
590
591 try:
592 retcode = ydl.download(all_urls)
593 except MaxDownloadsReached:
594 ydl.to_screen(u'--max-download limit reached, aborting.')
595 retcode = 101
596
597 # Dump cookie jar if requested
598 if opts.cookiefile is not None:
599 try:
600 jar.save()
601 except (IOError, OSError) as err:
602 sys.exit(u'ERROR: unable to save cookie jar')
603
604 sys.exit(retcode)
605
606 def main(argv=None):
607 try:
608 _real_main(argv)
609 except DownloadError:
610 sys.exit(1)
611 except SameFileError:
612 sys.exit(u'ERROR: fixed output name but more than one file to download')
613 except KeyboardInterrupt:
614 sys.exit(u'\nERROR: Interrupted by user')