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