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