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