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