]> jfr.im git - yt-dlp.git/blame - youtube_dl/__init__.py
Merge branch 'peugeot-tnaflix'
[yt-dlp.git] / youtube_dl / __init__.py
CommitLineData
235b3ba4
PH
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
3906e6ce 4__authors__ = (
59ae15a5
PH
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',
88f6c78b 20 'Dave Vasilevsky',
2069acc6 21 'Jaime Marquínez Ferrándiz',
fffec3b9 22 'Jeff Crouse',
6aabe820 23 'Osama Khalid',
e8600d69 24 'Michael Walter',
95464f14 25 'M. Yasoob Ullah Khalid',
0ae456f0 26 'Julien Fraichard',
be74864a 27 'Johny Mo Swag',
df725153 28 'Axel Noack',
ba7a1de0 29 'Albert Kim',
4a55479f 30 'Pierre Rudloff',
085bea45 31 'Huarong Huo',
ac4f319b 32 'Ismael Mejía',
2dad310e 33 'Steffan \'Ruirize\' James',
a623df4c 34 'Andras Elso',
b5bdc269 35 'Jelle van der Waa',
d3793638 36 'Marcin Cieślak',
0a120f74 37 'Anton Larionov',
38b2db6a 38 'Takuya Tsuchida',
87968574 39 'Sergey M.',
b83be81d 40 'Michael Orlitzky',
e63fc1be 41 'Chris Gahan',
a7732b67 42 'Saimadhav Heblikar',
2a893862 43 'Mike Col',
6d784e87 44 'Oleg Prutz',
0cea52cc 45 'pulpe',
845d14d3 46 'Andreas Schmitz',
cbffec0c 47 'Michael Kaiser',
96d16370 48 'Niklas Laxström',
f38da667 49 'David Triendl',
a339d7ba 50 'Anthony Weems',
dc3727b6 51 'David Wagner',
2fcec131 52 'Juan C. Olivares',
855e2750 53 'Mattias Harrysson',
2cc0082d 54 'phaer',
610e47c8 55 'Sainyam Kapoor',
bbe99d26 56 'Nicolas Évrard',
ccdd34ed 57 'Jason Normore',
25dfe0eb 58 'Hoje Lee',
c2ef2923 59 'Adam Thalhammer',
d30d2815 60 'Georg Jähnig',
9cc977f1 61 'Ralf Haring',
ba4133c9 62 'Koki Takahashi',
3d55f280 63 'Ariset Llerena',
cdc22cb8 64 'Adam Malcontenti-Wilson',
1df0ae21 65 'Tobias Bell',
0d90e0f0 66 'Naglis Jonaitis',
3b09757b 67 'Charles Chen',
5e95cb27 68 'Hassaan Ali',
e48a2c64 69 'Dobrosław Żybort',
4665664c 70 'David Fabijan',
56ca04f6 71 'Sebastian Haas',
3f338cd6 72 'Alexander Kirk',
deda8ac3 73 'Erik Johnson',
00558d94 74 'Keith Beckman',
36b0079f 75 'Ole Ernst',
a7cacbca 76 'Aaron McDaniel (mcd1992)',
ba7a1de0 77)
235b3ba4
PH
78
79__license__ = 'Public Domain'
235b3ba4 80
0d94f247 81import codecs
8f563f32 82import io
c9ed14e6 83import optparse
235b3ba4 84import os
0f818663 85import random
c9ed14e6 86import shlex
052421ff 87import shutil
235b3ba4 88import sys
235b3ba4 89
c496ca96 90
a4fd0415 91from .utils import (
e68301af 92 compat_getpass,
a4fd0415 93 compat_print,
a4fd0415 94 DateRange,
acd69589 95 DEFAULT_OUTTMPL,
a4fd0415 96 decodeOption,
1c088fa8 97 get_term_width,
a4fd0415
PH
98 DownloadError,
99 get_cachedir,
a4fd0415 100 MaxDownloadsReached,
a4fd0415 101 preferredencoding,
62e609ab 102 read_batch_urls,
a4fd0415 103 SameFileError,
e3946f98 104 setproctitle,
a4fd0415
PH
105 std_headers,
106 write_string,
a4fd0415 107)
d5ed35b6 108from .update import update_self
92a86f4c 109from .downloader import (
a4fd0415
PH
110 FileDownloader,
111)
0824c28c 112from .extractor import gen_extractors
dca08720 113from .version import __version__
8222d8de 114from .YoutubeDL import YoutubeDL
56327689 115from .postprocessor import (
0c14e2fb 116 AtomicParsleyPP,
149254d0 117 FFmpegAudioFixPP,
a4fd0415
PH
118 FFmpegMetadataPP,
119 FFmpegVideoConvertor,
120 FFmpegExtractAudioPP,
121 FFmpegEmbedSubtitlePP,
e63fc1be 122 XAttrMetadataPP,
a2360a4c 123 ExecAfterDownloadPP,
a4fd0415
PH
124)
125
235b3ba4 126
75b5c590 127def parseOpts(overrideArguments=None):
fb27c229 128 def _readOptions(filename_bytes, default=[]):
59ae15a5
PH
129 try:
130 optionf = open(filename_bytes)
131 except IOError:
fb27c229 132 return default # silently skip if file is not present
59ae15a5 133 try:
a0eaa341
PH
134 res = []
135 for l in optionf:
136 res += shlex.split(l, comments=True)
59ae15a5
PH
137 finally:
138 optionf.close()
139 return res
140
588128d0
PH
141 def _readUserConf():
142 xdg_config_home = os.environ.get('XDG_CONFIG_HOME')
143 if xdg_config_home:
144 userConfFile = os.path.join(xdg_config_home, 'youtube-dl', 'config')
145 if not os.path.isfile(userConfFile):
146 userConfFile = os.path.join(xdg_config_home, 'youtube-dl.conf')
147 else:
148 userConfFile = os.path.join(os.path.expanduser('~'), '.config', 'youtube-dl', 'config')
149 if not os.path.isfile(userConfFile):
150 userConfFile = os.path.join(os.path.expanduser('~'), '.config', 'youtube-dl.conf')
151 userConf = _readOptions(userConfFile, None)
152
153 if userConf is None:
154 appdata_dir = os.environ.get('appdata')
155 if appdata_dir:
156 userConf = _readOptions(
157 os.path.join(appdata_dir, 'youtube-dl', 'config'),
158 default=None)
159 if userConf is None:
160 userConf = _readOptions(
161 os.path.join(appdata_dir, 'youtube-dl', 'config.txt'),
162 default=None)
163
164 if userConf is None:
165 userConf = _readOptions(
166 os.path.join(os.path.expanduser('~'), 'youtube-dl.conf'),
167 default=None)
168 if userConf is None:
169 userConf = _readOptions(
170 os.path.join(os.path.expanduser('~'), 'youtube-dl.conf.txt'),
171 default=None)
172
173 if userConf is None:
174 userConf = []
175
176 return userConf
177
59ae15a5
PH
178 def _format_option_string(option):
179 ''' ('-o', '--option') -> -o, --format METAVAR'''
180
181 opts = []
182
183 if option._short_opts:
184 opts.append(option._short_opts[0])
185 if option._long_opts:
186 opts.append(option._long_opts[0])
187 if len(opts) > 1:
188 opts.insert(1, ', ')
189
190 if option.takes_value(): opts.append(' %s' % option.metavar)
191
192 return "".join(opts)
193
d6e203b3
IM
194 def _comma_separated_values_options_callback(option, opt_str, value, parser):
195 setattr(parser.values, option.dest, value.split(','))
196
920ef077
JMF
197 def _hide_login_info(opts):
198 opts = list(opts)
3126050c 199 for private_opt in ['-p', '--password', '-u', '--username', '--video-password']:
920ef077
JMF
200 try:
201 i = opts.index(private_opt)
202 opts[i+1] = '<PRIVATE>'
203 except ValueError:
204 pass
205 return opts
206
59ae15a5
PH
207 max_width = 80
208 max_help_position = 80
209
210 # No need to wrap help messages if we're on a wide console
1c088fa8 211 columns = get_term_width()
59ae15a5
PH
212 if columns: max_width = columns
213
214 fmt = optparse.IndentedHelpFormatter(width=max_width, max_help_position=max_help_position)
215 fmt.format_option_strings = _format_option_string
216
217 kw = {
218 'version' : __version__,
219 'formatter' : fmt,
220 'usage' : '%prog [options] url [url...]',
221 'conflict_handler' : 'resolve',
222 }
223
224 parser = optparse.OptionParser(**kw)
225
226 # option groups
227 general = optparse.OptionGroup(parser, 'General Options')
228 selection = optparse.OptionGroup(parser, 'Video Selection')
229 authentication = optparse.OptionGroup(parser, 'Authentication Options')
230 video_format = optparse.OptionGroup(parser, 'Video Format Options')
505c28aa 231 subtitles = optparse.OptionGroup(parser, 'Subtitle Options')
0beb3add 232 downloader = optparse.OptionGroup(parser, 'Download Options')
59ae15a5
PH
233 postproc = optparse.OptionGroup(parser, 'Post-processing Options')
234 filesystem = optparse.OptionGroup(parser, 'Filesystem Options')
2fe3d240 235 workarounds = optparse.OptionGroup(parser, 'Workarounds')
59ae15a5
PH
236 verbosity = optparse.OptionGroup(parser, 'Verbosity / Simulation Options')
237
238 general.add_option('-h', '--help',
239 action='help', help='print this help text and exit')
240 general.add_option('-v', '--version',
241 action='version', help='print program version and exit')
242 general.add_option('-U', '--update',
f631c331 243 action='store_true', dest='update_self', help='update this program to latest version. Make sure that you have sufficient permissions (run with sudo if needed)')
59ae15a5 244 general.add_option('-i', '--ignore-errors',
98c4b8fa 245 action='store_true', dest='ignoreerrors', help='continue on download errors, for example to skip unavailable videos in a playlist', default=False)
41fd7c7e
PH
246 general.add_option('--abort-on-error',
247 action='store_false', dest='ignoreerrors',
248 help='Abort downloading of further videos (in the playlist or the command line) if an error occurs')
59ae15a5
PH
249 general.add_option('--dump-user-agent',
250 action='store_true', dest='dump_user_agent',
251 help='display the current browser identification', default=False)
59ae15a5
PH
252 general.add_option('--list-extractors',
253 action='store_true', dest='list_extractors',
254 help='List all supported extractors and the URLs they would handle', default=False)
62067cb9 255 general.add_option('--extractor-descriptions',
0f818663
PH
256 action='store_true', dest='list_extractor_descriptions',
257 help='Output descriptions of all supported extractors', default=False)
cf6758d2
PH
258 general.add_option(
259 '--proxy', dest='proxy', default=None, metavar='URL',
260 help='Use the specified HTTP/HTTPS proxy. Pass in an empty string (--proxy "") for direct connection')
6ad14cab
PH
261 general.add_option(
262 '--socket-timeout', dest='socket_timeout',
9656ee5d 263 type=float, default=None, help=u'Time to wait before giving up, in seconds')
9c1fc022
PH
264 general.add_option(
265 '--default-search',
266 dest='default_search', metavar='PREFIX',
1f7ccb90 267 help='Use this prefix for unqualified URLs. For example "gvsearch2:" downloads two videos from google videos for youtube-dl "large apple". Use the value "auto" to let youtube-dl guess ("auto_warning" to emit a warning when guessing). "error" just throws an error. The default value "fixup_error" repairs broken URLs, but emits an error if this is not possible instead of searching.')
588128d0
PH
268 general.add_option(
269 '--ignore-config',
270 action='store_true',
271 help='Do not read configuration files. When given in the global configuration file /etc/youtube-dl.conf: do not read the user configuration in ~/.config/youtube-dl.conf (%APPDATA%/youtube-dl/config.txt on Windows)')
272
a19fd00c
PH
273 selection.add_option(
274 '--playlist-start',
275 dest='playliststart', metavar='NUMBER', default=1, type=int,
276 help='playlist video to start at (default is %default)')
277 selection.add_option(
278 '--playlist-end',
279 dest='playlistend', metavar='NUMBER', default=None, type=int,
280 help='playlist video to end at (default is last)')
59ae15a5
PH
281 selection.add_option('--match-title', dest='matchtitle', metavar='REGEX',help='download only matching titles (regex or caseless sub-string)')
282 selection.add_option('--reject-title', dest='rejecttitle', metavar='REGEX',help='skip download for matching titles (regex or caseless sub-string)')
0c75c3fa
PH
283 selection.add_option('--max-downloads', metavar='NUMBER',
284 dest='max_downloads', type=int, default=None,
285 help='Abort after downloading NUMBER files')
dbf2ba3d
PH
286 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)
287 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)
bd558525 288 selection.add_option('--date', metavar='DATE', dest='date', help='download only videos uploaded in this date', default=None)
bac268e2
PH
289 selection.add_option(
290 '--datebefore', metavar='DATE', dest='datebefore', default=None,
291 help='download only videos uploaded on or before this date (i.e. inclusive)')
292 selection.add_option(
293 '--dateafter', metavar='DATE', dest='dateafter', default=None,
294 help='download only videos uploaded on or after this date (i.e. inclusive)')
5fe18bdb
PH
295 selection.add_option(
296 '--min-views', metavar='COUNT', dest='min_views',
297 default=None, type=int,
298 help="Do not download any videos with less than COUNT views",)
299 selection.add_option(
300 '--max-views', metavar='COUNT', dest='max_views',
301 default=None, type=int,
302 help="Do not download any videos with more than COUNT views",)
47192f92 303 selection.add_option('--no-playlist', action='store_true', dest='noplaylist', help='download only the currently playing video', default=False)
8dbe9899
PH
304 selection.add_option('--age-limit', metavar='YEARS', dest='age_limit',
305 help='download only videos suitable for the given age',
306 default=None, type=int)
c1c9a79c
PH
307 selection.add_option('--download-archive', metavar='FILE',
308 dest='download_archive',
36a826a5 309 help='Download only videos not listed in the archive file. Record the IDs of all downloaded videos in it.')
7b0817e8
PH
310 selection.add_option(
311 '--include-ads', dest='include_ads',
312 action='store_true',
313 help='Download advertisements as well (experimental)')
8b1be5cd 314 selection.add_option(
4919603f
PH
315 '--youtube-include-dash-manifest', action='store_true',
316 dest='youtube_include_dash_manifest', default=False,
317 help='Try to download the DASH manifest on YouTube videos (experimental)')
9e982f9e 318
59ae15a5
PH
319 authentication.add_option('-u', '--username',
320 dest='username', metavar='USERNAME', help='account username')
321 authentication.add_option('-p', '--password',
322 dest='password', metavar='PASSWORD', help='account password')
83317f69 323 authentication.add_option('-2', '--twofactor',
324 dest='twofactor', metavar='TWOFACTOR', help='two-factor auth code')
59ae15a5
PH
325 authentication.add_option('-n', '--netrc',
326 action='store_true', dest='usenetrc', help='use .netrc authentication data', default=False)
c6c19746 327 authentication.add_option('--video-password',
67d28bff 328 dest='videopassword', metavar='PASSWORD', help='video password (vimeo, smotri)')
59ae15a5
PH
329
330
331 video_format.add_option('-f', '--format',
de3ef3ed 332 action='store', dest='format', metavar='FORMAT', default=None,
bc6d5978 333 help='video format code, specify the order of preference using slashes: "-f 22/17/18". "-f mp4" and "-f flv" are also supported. You can also use the special names "best", "bestvideo", "bestaudio", "worst", "worstvideo" and "worstaudio". By default, youtube-dl will pick the best quality.')
59ae15a5
PH
334 video_format.add_option('--all-formats',
335 action='store_const', dest='format', help='download all available video formats', const='all')
336 video_format.add_option('--prefer-free-formats',
337 action='store_true', dest='prefer_free_formats', default=False, help='prefer free video formats unless a specific one is requested')
338 video_format.add_option('--max-quality',
339 action='store', dest='format_limit', metavar='FORMAT', help='highest quality format to download')
340 video_format.add_option('-F', '--list-formats',
4950f308 341 action='store_true', dest='listformats', help='list all available formats')
505c28aa
IM
342
343 subtitles.add_option('--write-sub', '--write-srt',
59ae15a5 344 action='store_true', dest='writesubtitles',
953e32b2 345 help='write subtitle file', default=False)
505c28aa 346 subtitles.add_option('--write-auto-sub', '--write-automatic-sub',
b004821f 347 action='store_true', dest='writeautomaticsub',
953e32b2 348 help='write automatic subtitle file (youtube only)', default=False)
505c28aa 349 subtitles.add_option('--all-subs',
ae608b80 350 action='store_true', dest='allsubtitles',
953e32b2 351 help='downloads all the available subtitles of the video', default=False)
505c28aa 352 subtitles.add_option('--list-subs',
2a4093ea 353 action='store_true', dest='listsubtitles',
953e32b2 354 help='lists all available subtitles for the video', default=False)
505c28aa 355 subtitles.add_option('--sub-format',
c3ab8f86 356 action='store', dest='subtitlesformat', metavar='FORMAT',
953e32b2 357 help='subtitle format (default=srt) ([sbv/vtt] youtube only)', default='srt')
d6e203b3
IM
358 subtitles.add_option('--sub-lang', '--sub-langs', '--srt-lang',
359 action='callback', dest='subtitleslangs', metavar='LANGS', type='str',
360 default=[], callback=_comma_separated_values_options_callback,
361 help='languages of the subtitles to download (optional) separated by commas, use IETF language tags like \'en,pt\'')
59ae15a5 362
0beb3add 363 downloader.add_option('-r', '--rate-limit',
cd054fc4 364 dest='ratelimit', metavar='LIMIT', help='maximum download rate in bytes per second (e.g. 50K or 4.2M)')
0beb3add
PH
365 downloader.add_option('-R', '--retries',
366 dest='retries', metavar='RETRIES', help='number of retries (default is %default)', default=10)
367 downloader.add_option('--buffer-size',
cd054fc4 368 dest='buffersize', metavar='SIZE', help='size of download buffer (e.g. 1024 or 16K) (default is %default)', default="1024")
0beb3add
PH
369 downloader.add_option('--no-resize-buffer',
370 action='store_true', dest='noresizebuffer',
371 help='do not automatically adjust the buffer size. By default, the buffer size is automatically resized from an initial value of SIZE.', default=False)
372 downloader.add_option('--test', action='store_true', dest='test', default=False, help=optparse.SUPPRESS_HELP)
373
2fe3d240
PH
374 workarounds.add_option(
375 '--encoding', dest='encoding', metavar='ENCODING',
376 help='Force the specified encoding (experimental)')
377 workarounds.add_option(
378 '--no-check-certificate', action='store_true',
379 dest='no_check_certificate', default=False,
380 help='Suppress HTTPS certificate validation.')
381 workarounds.add_option(
382 '--prefer-insecure', '--prefer-unsecure', action='store_true', dest='prefer_insecure',
383 help='Use an unencrypted connection to retrieve information about the video. (Currently supported only for YouTube)')
384 workarounds.add_option(
385 '--user-agent', metavar='UA',
386 dest='user_agent', help='specify a custom user agent')
387 workarounds.add_option(
388 '--referer', metavar='REF',
389 dest='referer', default=None,
390 help='specify a custom referer, use if the video access is restricted to one domain',
391 )
392 workarounds.add_option(
393 '--add-header', metavar='FIELD:VALUE',
394 dest='headers', action='append',
395 help='specify a custom HTTP header and its value, separated by a colon \':\'. You can use this option multiple times',
396 )
10b04ff7
PH
397 workarounds.add_option(
398 '--bidi-workaround', dest='bidi_workaround', action='store_true',
399 help=u'Work around terminals that lack bidirectional text support. Requires bidiv or fribidi executable in PATH')
2fe3d240 400
59ae15a5
PH
401 verbosity.add_option('-q', '--quiet',
402 action='store_true', dest='quiet', help='activates quiet mode', default=False)
ad8915b7
PH
403 verbosity.add_option(
404 '--no-warnings',
405 dest='no_warnings', action='store_true', default=False,
406 help='Ignore warnings')
59ae15a5
PH
407 verbosity.add_option('-s', '--simulate',
408 action='store_true', dest='simulate', help='do not download the video and do not write anything to disk', default=False)
409 verbosity.add_option('--skip-download',
410 action='store_true', dest='skip_download', help='do not download the video', default=False)
411 verbosity.add_option('-g', '--get-url',
412 action='store_true', dest='geturl', help='simulate, quiet but print URL', default=False)
413 verbosity.add_option('-e', '--get-title',
414 action='store_true', dest='gettitle', help='simulate, quiet but print title', default=False)
1a2adf3f 415 verbosity.add_option('--get-id',
416 action='store_true', dest='getid', help='simulate, quiet but print id', default=False)
59ae15a5
PH
417 verbosity.add_option('--get-thumbnail',
418 action='store_true', dest='getthumbnail',
419 help='simulate, quiet but print thumbnail URL', default=False)
420 verbosity.add_option('--get-description',
421 action='store_true', dest='getdescription',
422 help='simulate, quiet but print video description', default=False)
525ef922
PH
423 verbosity.add_option('--get-duration',
424 action='store_true', dest='getduration',
425 help='simulate, quiet but print video length', default=False)
59ae15a5
PH
426 verbosity.add_option('--get-filename',
427 action='store_true', dest='getfilename',
428 help='simulate, quiet but print output filename', default=False)
429 verbosity.add_option('--get-format',
430 action='store_true', dest='getformat',
431 help='simulate, quiet but print output format', default=False)
9d153818
MF
432 verbosity.add_option('-j', '--dump-json',
433 action='store_true', dest='dumpjson',
330edf2d 434 help='simulate, quiet but print JSON information. See --output for a description of available keys.', default=False)
7311fef8 435 verbosity.add_option('--newline',
5717d91a 436 action='store_true', dest='progress_with_newline', help='output progress bar as new lines', default=False)
59ae15a5
PH
437 verbosity.add_option('--no-progress',
438 action='store_true', dest='noprogress', help='do not print progress bar', default=False)
439 verbosity.add_option('--console-title',
440 action='store_true', dest='consoletitle',
441 help='display progress in console titlebar', default=False)
442 verbosity.add_option('-v', '--verbose',
443 action='store_true', dest='verbose', help='print various debugging information', default=False)
855703e5
PH
444 verbosity.add_option('--dump-intermediate-pages',
445 action='store_true', dest='dump_intermediate_pages', default=False,
67d28bff 446 help='print downloaded pages to debug problems (very verbose)')
d41e6efc
PH
447 verbosity.add_option('--write-pages',
448 action='store_true', dest='write_pages', default=False,
06dcbb71 449 help='Write downloaded intermediary pages to files in the current directory to debug problems')
edf3e38e
PH
450 verbosity.add_option('--youtube-print-sig-code',
451 action='store_true', dest='youtube_print_sig_code', default=False,
452 help=optparse.SUPPRESS_HELP)
a0ddb8a2
PH
453 verbosity.add_option('--print-traffic',
454 dest='debug_printtraffic', action='store_true', default=False,
4919603f
PH
455 help='Display sent and read HTTP traffic')
456
59ae15a5 457
a11165ec
PH
458 filesystem.add_option('-a', '--batch-file',
459 dest='batchfile', metavar='FILE', help='file containing URLs to download (\'-\' for stdin)')
59ae15a5 460 filesystem.add_option('--id',
08b2ac74 461 action='store_true', dest='useid', help='use only video ID in file name', default=False)
59ae15a5
PH
462 filesystem.add_option('-A', '--auto-number',
463 action='store_true', dest='autonumber',
464 help='number downloaded files starting from 00000', default=False)
465 filesystem.add_option('-o', '--output',
74e3452b
JMF
466 dest='outtmpl', metavar='TEMPLATE',
467 help=('output filename template. Use %(title)s to get the title, '
468 '%(uploader)s for the uploader name, %(uploader_id)s for the uploader nickname if different, '
469 '%(autonumber)s to get an automatically incremented number, '
fdefe96b 470 '%(ext)s for the filename extension, '
67d28bff 471 '%(format)s for the format description (like "22 - 1280x720" or "HD"), '
472 '%(format_id)s for the unique id of the format (like Youtube\'s itags: "137"), '
fdefe96b 473 '%(upload_date)s for the upload date (YYYYMMDD), '
74e3452b 474 '%(extractor)s for the provider (youtube, metacafe, etc), '
67d28bff 475 '%(id)s for the video id, %(playlist)s for the playlist the video is in, '
74e3452b 476 '%(playlist_index)s for the position in the playlist and %% for a literal percent. '
17b75c0d
PH
477 '%(height)s and %(width)s for the width and height of the video format. '
478 '%(resolution)s for a textual description of the resolution of the video format. '
74e3452b
JMF
479 'Use - to output to stdout. Can also be used to download to a different directory, '
480 'for example with -o \'/my/downloads/%(uploader)s/%(title)s-%(id)s.%(ext)s\' .'))
213c31ae
SK
481 filesystem.add_option('--autonumber-size',
482 dest='autonumber_size', metavar='NUMBER',
2a9e9b21 483 help='Specifies the number of digits in %(autonumber)s when it is present in output filename template or --auto-number option is given')
59ae15a5
PH
484 filesystem.add_option('--restrict-filenames',
485 action='store_true', dest='restrictfilenames',
486 help='Restrict filenames to only ASCII characters, and avoid "&" and spaces in filenames', default=False)
a11165ec 487 filesystem.add_option('-t', '--title',
4e99f488 488 action='store_true', dest='usetitle', help='[deprecated] use title in file name (default)', default=False)
a11165ec
PH
489 filesystem.add_option('-l', '--literal',
490 action='store_true', dest='usetitle', help='[deprecated] alias of --title', default=False)
59ae15a5
PH
491 filesystem.add_option('-w', '--no-overwrites',
492 action='store_true', dest='nooverwrites', help='do not overwrite files', default=False)
493 filesystem.add_option('-c', '--continue',
d4b7da84 494 action='store_true', dest='continue_dl', help='force resume of partially downloaded files. By default, youtube-dl will resume downloads if possible.', default=True)
59ae15a5
PH
495 filesystem.add_option('--no-continue',
496 action='store_false', dest='continue_dl',
497 help='do not resume partially downloaded files (restart from beginning)')
59ae15a5
PH
498 filesystem.add_option('--no-part',
499 action='store_true', dest='nopart', help='do not use .part files', default=False)
500 filesystem.add_option('--no-mtime',
501 action='store_false', dest='updatetime',
502 help='do not use the Last-modified header to set the file modification time', default=True)
503 filesystem.add_option('--write-description',
504 action='store_true', dest='writedescription',
505 help='write video description to a .description file', default=False)
506 filesystem.add_option('--write-info-json',
507 action='store_true', dest='writeinfojson',
508 help='write video metadata to a .info.json file', default=False)
1fb07d10
JG
509 filesystem.add_option('--write-annotations',
510 action='store_true', dest='writeannotations',
511 help='write video annotations to a .annotation file', default=False)
11d9224e
PH
512 filesystem.add_option('--write-thumbnail',
513 action='store_true', dest='writethumbnail',
514 help='write thumbnail image to disk', default=False)
a11165ec
PH
515 filesystem.add_option('--load-info',
516 dest='load_info_filename', metavar='FILE',
517 help='json file containing the video information (created with the "--write-json" option)')
518 filesystem.add_option('--cookies',
519 dest='cookiefile', metavar='FILE', help='file to read cookies from and dump cookie jar in')
fbb2fc55
PH
520 filesystem.add_option(
521 '--cache-dir', dest='cachedir', default=get_cachedir(), metavar='DIR',
522 help='Location in the filesystem where youtube-dl can store some downloaded information permanently. By default $XDG_CACHE_HOME/youtube-dl or ~/.cache/youtube-dl . At the moment, only YouTube player files (for videos with obfuscated signatures) are cached, but that may change.')
523 filesystem.add_option(
524 '--no-cache-dir', action='store_const', const=None, dest='cachedir',
525 help='Disable filesystem caching')
052421ff
PH
526 filesystem.add_option(
527 '--rm-cache-dir', action='store_true', dest='rm_cachedir',
528 help='Delete all filesystem cache files')
59ae15a5
PH
529
530
531 postproc.add_option('-x', '--extract-audio', action='store_true', dest='extractaudio', default=False,
532 help='convert video files to audio-only files (requires ffmpeg or avconv and ffprobe or avprobe)')
533 postproc.add_option('--audio-format', metavar='FORMAT', dest='audioformat', default='best',
510e6f6d 534 help='"best", "aac", "vorbis", "mp3", "m4a", "opus", or "wav"; best by default')
59ae15a5
PH
535 postproc.add_option('--audio-quality', metavar='QUALITY', dest='audioquality', default='5',
536 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)')
7851b379 537 postproc.add_option('--recode-video', metavar='FORMAT', dest='recodevideo', default=None,
133af938 538 help='Encode the video to another format if necessary (currently supported: mp4|flv|ogg|webm|mkv)')
59ae15a5
PH
539 postproc.add_option('-k', '--keep-video', action='store_true', dest='keepvideo', default=False,
540 help='keeps the video file on disk after the post-processing; the video is erased by default')
f0648fc1
BPG
541 postproc.add_option('--no-post-overwrites', action='store_true', dest='nopostoverwrites', default=False,
542 help='do not overwrite post-processed files; the post-processed files are overwritten by default')
d4051a8e
JMF
543 postproc.add_option('--embed-subs', action='store_true', dest='embedsubtitles', default=False,
544 help='embed subtitles in the video (only for mp4 videos)')
0c14e2fb 545 postproc.add_option('--embed-thumbnail', action='store_true', dest='embedthumbnail', default=False,
546 help='embed thumbnail in the audio as cover art')
bc4f2917 547 postproc.add_option('--add-metadata', action='store_true', dest='addmetadata', default=False,
e63fc1be 548 help='write metadata to the video file')
549 postproc.add_option('--xattrs', action='store_true', dest='xattrs', default=False,
550 help='write metadata to the video file\'s xattrs (using dublin core and xdg standards)')
76b1bd67
JMF
551 postproc.add_option('--prefer-avconv', action='store_false', dest='prefer_ffmpeg',
552 help='Prefer avconv over ffmpeg for running the postprocessors (default)')
553 postproc.add_option('--prefer-ffmpeg', action='store_true', dest='prefer_ffmpeg',
554 help='Prefer ffmpeg over avconv for running the postprocessors')
8d31fa3c
PH
555 postproc.add_option(
556 '--exec', metavar='CMD', dest='exec_cmd',
557 help='Execute a command on the file after downloading, similar to find\'s -exec syntax. Example: --exec \'adb push {} /sdcard/Music/ && rm {}\'' )
59ae15a5
PH
558
559 parser.add_option_group(general)
560 parser.add_option_group(selection)
0beb3add 561 parser.add_option_group(downloader)
59ae15a5
PH
562 parser.add_option_group(filesystem)
563 parser.add_option_group(verbosity)
2fe3d240 564 parser.add_option_group(workarounds)
59ae15a5 565 parser.add_option_group(video_format)
505c28aa 566 parser.add_option_group(subtitles)
59ae15a5
PH
567 parser.add_option_group(authentication)
568 parser.add_option_group(postproc)
569
75b5c590
PH
570 if overrideArguments is not None:
571 opts, args = parser.parse_args(overrideArguments)
572 if opts.verbose:
7459e3a2 573 write_string(u'[debug] Override config: ' + repr(overrideArguments) + '\n')
59ae15a5 574 else:
1865ed31 575 commandLineConf = sys.argv[1:]
588128d0
PH
576 if '--ignore-config' in commandLineConf:
577 systemConf = []
578 userConf = []
579 else:
580 systemConf = _readOptions('/etc/youtube-dl.conf')
581 if '--ignore-config' in systemConf:
582 userConf = []
583 else:
584 userConf = _readUserConf()
75b5c590 585 argv = systemConf + userConf + commandLineConf
588128d0 586
75b5c590 587 opts, args = parser.parse_args(argv)
c76cb6d5 588 if opts.verbose:
7459e3a2
PH
589 write_string(u'[debug] System config: ' + repr(_hide_login_info(systemConf)) + '\n')
590 write_string(u'[debug] User config: ' + repr(_hide_login_info(userConf)) + '\n')
591 write_string(u'[debug] Command-line args: ' + repr(_hide_login_info(commandLineConf)) + '\n')
8c42c506 592
59ae15a5 593 return parser, opts, args
235b3ba4 594
e3946f98 595
b8ad4f02 596def _real_main(argv=None):
0d94f247
PH
597 # Compatibility fixes for Windows
598 if sys.platform == 'win32':
599 # https://github.com/rg3/youtube-dl/issues/820
600 codecs.register(lambda name: codecs.lookup('utf-8') if name == 'cp65001' else None)
601
e3946f98
PH
602 setproctitle(u'youtube-dl')
603
b8ad4f02 604 parser, opts, args = parseOpts(argv)
59ae15a5 605
59ae15a5
PH
606 # Set user agent
607 if opts.user_agent is not None:
608 std_headers['User-Agent'] = opts.user_agent
1865ed31 609
28535652
BH
610 # Set referer
611 if opts.referer is not None:
612 std_headers['Referer'] = opts.referer
59ae15a5 613
410afb20
AA
614 # Custom HTTP headers
615 if opts.headers is not None:
616 for h in opts.headers:
617 if h.find(':', 1) < 0:
618 parser.error(u'wrong header formatting, it should be key:value, not "%s"'%h)
619 key, value = h.split(':', 2)
620 if opts.verbose:
621 write_string(u'[debug] Adding header from command line option %s:%s\n'%(key, value))
622 std_headers[key] = value
623
59ae15a5
PH
624 # Dump user agent
625 if opts.dump_user_agent:
93eb15c5 626 compat_print(std_headers['User-Agent'])
59ae15a5
PH
627 sys.exit(0)
628
629 # Batch file verification
62e609ab 630 batch_urls = []
59ae15a5
PH
631 if opts.batchfile is not None:
632 try:
633 if opts.batchfile == '-':
634 batchfd = sys.stdin
635 else:
62e609ab
PH
636 batchfd = io.open(opts.batchfile, 'r', encoding='utf-8', errors='ignore')
637 batch_urls = read_batch_urls(batchfd)
05afc96b 638 if opts.verbose:
62e609ab 639 write_string(u'[debug] Batch file urls: ' + repr(batch_urls) + u'\n')
59ae15a5
PH
640 except IOError:
641 sys.exit(u'ERROR: batch file could not be read')
62e609ab 642 all_urls = batch_urls + args
59ae15a5 643 all_urls = [url.strip() for url in all_urls]
c774b3c6 644 _enc = preferredencoding()
41292a38 645 all_urls = [url.decode(_enc, 'ignore') if isinstance(url, bytes) else url for url in all_urls]
59ae15a5 646
59ae15a5
PH
647 extractors = gen_extractors()
648
649 if opts.list_extractors:
7dba9cd0 650 for ie in sorted(extractors, key=lambda ie: ie.IE_NAME.lower()):
93eb15c5 651 compat_print(ie.IE_NAME + (' (CURRENTLY BROKEN)' if not ie._WORKING else ''))
1a2c3c0f 652 matchedUrls = [url for url in all_urls if ie.suitable(url)]
59ae15a5 653 for mu in matchedUrls:
93eb15c5 654 compat_print(u' ' + mu)
59ae15a5 655 sys.exit(0)
0f818663
PH
656 if opts.list_extractor_descriptions:
657 for ie in sorted(extractors, key=lambda ie: ie.IE_NAME.lower()):
658 if not ie._WORKING:
659 continue
660 desc = getattr(ie, 'IE_DESC', ie.IE_NAME)
15870e90
PH
661 if desc is False:
662 continue
0f818663 663 if hasattr(ie, 'SEARCH_KEY'):
53eb2176 664 _SEARCHES = (u'cute kittens', u'slithering pythons', u'falling cat', u'angry poodle', u'purple fish', u'running tortoise', u'sleeping bunny')
0f818663
PH
665 _COUNTS = (u'', u'5', u'10', u'all')
666 desc += u' (Example: "%s%s:%s" )' % (ie.SEARCH_KEY, random.choice(_COUNTS), random.choice(_SEARCHES))
667 compat_print(desc)
668 sys.exit(0)
669
59ae15a5
PH
670
671 # Conflicting, missing and erroneous options
672 if opts.usenetrc and (opts.username is not None or opts.password is not None):
673 parser.error(u'using .netrc conflicts with giving username/password')
674 if opts.password is not None and opts.username is None:
67d28bff 675 parser.error(u'account username missing\n')
59ae15a5
PH
676 if opts.outtmpl is not None and (opts.usetitle or opts.autonumber or opts.useid):
677 parser.error(u'using output template conflicts with using title, video ID or auto number')
678 if opts.usetitle and opts.useid:
679 parser.error(u'using title conflicts with using video ID')
680 if opts.username is not None and opts.password is None:
e68301af 681 opts.password = compat_getpass(u'Type account password and press [Return]: ')
59ae15a5
PH
682 if opts.ratelimit is not None:
683 numeric_limit = FileDownloader.parse_bytes(opts.ratelimit)
684 if numeric_limit is None:
685 parser.error(u'invalid rate limit specified')
686 opts.ratelimit = numeric_limit
9e982f9e
JC
687 if opts.min_filesize is not None:
688 numeric_limit = FileDownloader.parse_bytes(opts.min_filesize)
689 if numeric_limit is None:
690 parser.error(u'invalid min_filesize specified')
691 opts.min_filesize = numeric_limit
692 if opts.max_filesize is not None:
693 numeric_limit = FileDownloader.parse_bytes(opts.max_filesize)
694 if numeric_limit is None:
695 parser.error(u'invalid max_filesize specified')
696 opts.max_filesize = numeric_limit
59ae15a5
PH
697 if opts.retries is not None:
698 try:
699 opts.retries = int(opts.retries)
dca08720 700 except (TypeError, ValueError):
59ae15a5
PH
701 parser.error(u'invalid retry count specified')
702 if opts.buffersize is not None:
703 numeric_buffersize = FileDownloader.parse_bytes(opts.buffersize)
704 if numeric_buffersize is None:
705 parser.error(u'invalid buffer size specified')
706 opts.buffersize = numeric_buffersize
a19fd00c
PH
707 if opts.playliststart <= 0:
708 raise ValueError(u'Playlist start must be positive')
709 if opts.playlistend not in (-1, None) and opts.playlistend < opts.playliststart:
710 raise ValueError(u'Playlist end must be greater than playlist start')
59ae15a5 711 if opts.extractaudio:
510e6f6d 712 if opts.audioformat not in ['best', 'aac', 'mp3', 'm4a', 'opus', 'vorbis', 'wav']:
59ae15a5
PH
713 parser.error(u'invalid audio format specified')
714 if opts.audioquality:
715 opts.audioquality = opts.audioquality.strip('k').strip('K')
716 if not opts.audioquality.isdigit():
717 parser.error(u'invalid audio quality specified')
7851b379 718 if opts.recodevideo is not None:
b7d73595 719 if opts.recodevideo not in ['mp4', 'flv', 'webm', 'ogg', 'mkv']:
7851b379 720 parser.error(u'invalid video recode format specified')
bd558525
JMF
721 if opts.date is not None:
722 date = DateRange.day(opts.date)
723 else:
724 date = DateRange(opts.dateafter, opts.datebefore)
1f7ccb90 725 if opts.default_search not in ('auto', 'auto_warning', 'error', 'fixup_error', None) and ':' not in opts.default_search:
04b4d394 726 parser.error(u'--default-search invalid; did you forget a colon (:) at the end?')
59ae15a5 727
de3ef3ed
PH
728 # Do not download videos when there are audio-only formats
729 if opts.extractaudio and not opts.keepvideo and opts.format is None:
730 opts.format = 'bestaudio/best'
731
0b7f3118
JMF
732 # --all-sub automatically sets --write-sub if --write-auto-sub is not given
733 # this was the old behaviour if only --all-sub was given.
734 if opts.allsubtitles and (opts.writeautomaticsub == False):
735 opts.writesubtitles = True
736
5cb9c312
PH
737 if sys.version_info < (3,):
738 # In Python 2, sys.argv is a bytestring (also note http://bugs.python.org/issue2128 for Windows systems)
0be41ec2
PH
739 if opts.outtmpl is not None:
740 opts.outtmpl = opts.outtmpl.decode(preferredencoding())
5cb9c312
PH
741 outtmpl =((opts.outtmpl is not None and opts.outtmpl)
742 or (opts.format == '-1' and opts.usetitle and u'%(title)s-%(id)s-%(format)s.%(ext)s')
743 or (opts.format == '-1' and u'%(id)s-%(format)s.%(ext)s')
744 or (opts.usetitle and opts.autonumber and u'%(autonumber)s-%(title)s-%(id)s.%(ext)s')
745 or (opts.usetitle and u'%(title)s-%(id)s.%(ext)s')
746 or (opts.useid and u'%(id)s.%(ext)s')
747 or (opts.autonumber and u'%(autonumber)s-%(id)s.%(ext)s')
acd69589 748 or DEFAULT_OUTTMPL)
dca02c80 749 if not os.path.splitext(outtmpl)[1] and opts.extractaudio:
b61067fa 750 parser.error(u'Cannot download a video and extract audio into the same'
dca02c80
JMF
751 u' file! Use "{0}.%(ext)s" instead of "{0}" as the output'
752 u' template'.format(outtmpl))
29c7a63d 753
525ef922 754 any_printing = opts.geturl or opts.gettitle or opts.getid or opts.getthumbnail or opts.getdescription or opts.getfilename or opts.getformat or opts.getduration or opts.dumpjson
17093b83 755 download_archive_fn = os.path.expanduser(opts.download_archive) if opts.download_archive is not None else opts.download_archive
525ef922 756
bdde425c 757 ydl_opts = {
59ae15a5
PH
758 'usenetrc': opts.usenetrc,
759 'username': opts.username,
760 'password': opts.password,
83317f69 761 'twofactor': opts.twofactor,
c6c19746 762 'videopassword': opts.videopassword,
525ef922 763 'quiet': (opts.quiet or any_printing),
ad8915b7 764 'no_warnings': opts.no_warnings,
59ae15a5
PH
765 'forceurl': opts.geturl,
766 'forcetitle': opts.gettitle,
1a2adf3f 767 'forceid': opts.getid,
59ae15a5
PH
768 'forcethumbnail': opts.getthumbnail,
769 'forcedescription': opts.getdescription,
525ef922 770 'forceduration': opts.getduration,
59ae15a5
PH
771 'forcefilename': opts.getfilename,
772 'forceformat': opts.getformat,
9d153818 773 'forcejson': opts.dumpjson,
59ae15a5 774 'simulate': opts.simulate,
525ef922 775 'skip_download': (opts.skip_download or opts.simulate or any_printing),
59ae15a5
PH
776 'format': opts.format,
777 'format_limit': opts.format_limit,
778 'listformats': opts.listformats,
5cb9c312 779 'outtmpl': outtmpl,
213c31ae 780 'autonumber_size': opts.autonumber_size,
59ae15a5
PH
781 'restrictfilenames': opts.restrictfilenames,
782 'ignoreerrors': opts.ignoreerrors,
783 'ratelimit': opts.ratelimit,
784 'nooverwrites': opts.nooverwrites,
785 'retries': opts.retries,
786 'buffersize': opts.buffersize,
787 'noresizebuffer': opts.noresizebuffer,
788 'continuedl': opts.continue_dl,
789 'noprogress': opts.noprogress,
5717d91a 790 'progress_with_newline': opts.progress_with_newline,
59ae15a5
PH
791 'playliststart': opts.playliststart,
792 'playlistend': opts.playlistend,
47192f92 793 'noplaylist': opts.noplaylist,
59ae15a5
PH
794 'logtostderr': opts.outtmpl == '-',
795 'consoletitle': opts.consoletitle,
796 'nopart': opts.nopart,
797 'updatetime': opts.updatetime,
798 'writedescription': opts.writedescription,
1fb07d10 799 'writeannotations': opts.writeannotations,
59ae15a5 800 'writeinfojson': opts.writeinfojson,
11d9224e 801 'writethumbnail': opts.writethumbnail,
59ae15a5 802 'writesubtitles': opts.writesubtitles,
b004821f 803 'writeautomaticsub': opts.writeautomaticsub,
ae608b80 804 'allsubtitles': opts.allsubtitles,
2a4093ea 805 'listsubtitles': opts.listsubtitles,
9e62bc44 806 'subtitlesformat': opts.subtitlesformat,
d6e203b3 807 'subtitleslangs': opts.subtitleslangs,
8271226a
PH
808 'matchtitle': decodeOption(opts.matchtitle),
809 'rejecttitle': decodeOption(opts.rejecttitle),
59ae15a5
PH
810 'max_downloads': opts.max_downloads,
811 'prefer_free_formats': opts.prefer_free_formats,
812 'verbose': opts.verbose,
855703e5 813 'dump_intermediate_pages': opts.dump_intermediate_pages,
d41e6efc 814 'write_pages': opts.write_pages,
8d5d3a5d 815 'test': opts.test,
7851b379 816 'keepvideo': opts.keepvideo,
9e982f9e 817 'min_filesize': opts.min_filesize,
bd558525 818 'max_filesize': opts.max_filesize,
5fe18bdb
PH
819 'min_views': opts.min_views,
820 'max_views': opts.max_views,
11d9224e 821 'daterange': date,
7f747732 822 'cachedir': opts.cachedir,
f8061589 823 'youtube_print_sig_code': opts.youtube_print_sig_code,
8dbe9899 824 'age_limit': opts.age_limit,
17093b83 825 'download_archive': download_archive_fn,
dca08720
PH
826 'cookiefile': opts.cookiefile,
827 'nocheckcertificate': opts.no_check_certificate,
7e8c0af0 828 'prefer_insecure': opts.prefer_insecure,
c2e52508 829 'proxy': opts.proxy,
6ad14cab 830 'socket_timeout': opts.socket_timeout,
0783b09b 831 'bidi_workaround': opts.bidi_workaround,
a0ddb8a2 832 'debug_printtraffic': opts.debug_printtraffic,
76b1bd67 833 'prefer_ffmpeg': opts.prefer_ffmpeg,
7b0817e8 834 'include_ads': opts.include_ads,
04b4d394 835 'default_search': opts.default_search,
4919603f 836 'youtube_include_dash_manifest': opts.youtube_include_dash_manifest,
62fec3b2 837 'encoding': opts.encoding,
8d31fa3c 838 'exec_cmd': opts.exec_cmd,
bdde425c 839 }
59ae15a5 840
bdde425c 841 with YoutubeDL(ydl_opts) as ydl:
dca08720 842 ydl.print_debug_header()
bdde425c
PH
843 ydl.add_default_info_extractors()
844
845 # PostProcessors
846 # Add the metadata pp first, the other pps will copy it
847 if opts.addmetadata:
848 ydl.add_post_processor(FFmpegMetadataPP())
849 if opts.extractaudio:
850 ydl.add_post_processor(FFmpegExtractAudioPP(preferredcodec=opts.audioformat, preferredquality=opts.audioquality, nopostoverwrites=opts.nopostoverwrites))
851 if opts.recodevideo:
852 ydl.add_post_processor(FFmpegVideoConvertor(preferedformat=opts.recodevideo))
853 if opts.embedsubtitles:
854 ydl.add_post_processor(FFmpegEmbedSubtitlePP(subtitlesformat=opts.subtitlesformat))
e63fc1be 855 if opts.xattrs:
856 ydl.add_post_processor(XAttrMetadataPP())
0c14e2fb 857 if opts.embedthumbnail:
784763c5 858 if not opts.addmetadata:
859 ydl.add_post_processor(FFmpegAudioFixPP())
0c14e2fb 860 ydl.add_post_processor(AtomicParsleyPP())
bdde425c 861
a7cacbca 862
863 # Please keep ExecAfterDownload towards the bottom as it allows the user to modify the final file in any way.
864 # So if the user is able to remove the file before your postprocessor runs it might cause a few problems.
8d31fa3c
PH
865 if opts.exec_cmd:
866 ydl.add_post_processor(ExecAfterDownloadPP(
867 verboseOutput=opts.verbose, exec_cmd=opts.exec_cmd))
a7cacbca 868
bdde425c
PH
869 # Update version
870 if opts.update_self:
871 update_self(ydl.to_screen, opts.verbose)
872
052421ff
PH
873 # Remove cache dir
874 if opts.rm_cachedir:
875 if opts.cachedir is None:
876 ydl.to_screen(u'No cache dir specified (Did you combine --no-cache-dir and --rm-cache-dir?)')
877 else:
878 if ('.cache' not in opts.cachedir) or ('youtube-dl' not in opts.cachedir):
35b1e445 879 ydl.to_screen(u'Not removing directory %s - this does not look like a cache dir' % opts.cachedir)
052421ff
PH
880 retcode = 141
881 else:
882 ydl.to_screen(
883 u'Removing cache dir %s .' % opts.cachedir,
884 skip_eol=True)
885 if os.path.exists(opts.cachedir):
886 ydl.to_screen(u'.', skip_eol=True)
887 shutil.rmtree(opts.cachedir)
888 ydl.to_screen(u'.')
889
bdde425c 890 # Maybe do nothing
1dcc4c0c 891 if (len(all_urls) < 1) and (opts.load_info_filename is None):
052421ff 892 if not (opts.update_self or opts.rm_cachedir):
bdde425c
PH
893 parser.error(u'you must provide at least one URL')
894 else:
895 sys.exit()
59ae15a5 896
bdde425c 897 try:
1dcc4c0c
JMF
898 if opts.load_info_filename is not None:
899 retcode = ydl.download_with_info_file(opts.load_info_filename)
900 else:
901 retcode = ydl.download(all_urls)
bdde425c
PH
902 except MaxDownloadsReached:
903 ydl.to_screen(u'--max-download limit reached, aborting.')
904 retcode = 101
59ae15a5 905
59ae15a5 906 sys.exit(retcode)
235b3ba4 907
a27b9e8b 908
b8ad4f02 909def main(argv=None):
59ae15a5 910 try:
b8ad4f02 911 _real_main(argv)
59ae15a5
PH
912 except DownloadError:
913 sys.exit(1)
914 except SameFileError:
915 sys.exit(u'ERROR: fixed output name but more than one file to download')
916 except KeyboardInterrupt:
917 sys.exit(u'\nERROR: Interrupted by user')