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