]> jfr.im git - yt-dlp.git/blame - youtube_dl/__init__.py
[youtube] fix the order of DASH formats
[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')
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)')
b9fc4284 189 video_format.add_option('--write-sub', '--write-srt',
59ae15a5 190 action='store_true', dest='writesubtitles',
553d0974 191 help='write subtitle file (currently youtube only)', default=False)
b004821f
JMF
192 video_format.add_option('--write-auto-sub', '--write-automatic-sub',
193 action='store_true', dest='writeautomaticsub',
194 help='write automatic subtitle file (currently youtube only)', default=False)
553d0974 195 video_format.add_option('--only-sub',
1bd96c3a
PH
196 action='store_true', dest='skip_download',
197 help='[deprecated] alias of --skip-download', default=False)
553d0974 198 video_format.add_option('--all-subs',
ae608b80
IM
199 action='store_true', dest='allsubtitles',
200 help='downloads all the available subtitles of the video (currently youtube only)', default=False)
2a4093ea
IM
201 video_format.add_option('--list-subs',
202 action='store_true', dest='listsubtitles',
203 help='lists all available subtitles for the video (currently youtube only)', default=False)
9e62bc44 204 video_format.add_option('--sub-format',
c3ab8f86 205 action='store', dest='subtitlesformat', metavar='FORMAT',
65cceef8 206 help='subtitle format [srt/sbv/vtt] (default=srt) (currently youtube only)', default='srt')
b9fc4284 207 video_format.add_option('--sub-lang', '--srt-lang',
59ae15a5 208 action='store', dest='subtitleslang', metavar='LANG',
553d0974 209 help='language of the subtitles to download (optional) use IETF language tags like \'en\'')
59ae15a5 210
0beb3add
PH
211 downloader.add_option('-r', '--rate-limit',
212 dest='ratelimit', metavar='LIMIT', help='maximum download rate (e.g. 50k or 44.6m)')
213 downloader.add_option('-R', '--retries',
214 dest='retries', metavar='RETRIES', help='number of retries (default is %default)', default=10)
215 downloader.add_option('--buffer-size',
216 dest='buffersize', metavar='SIZE', help='size of download buffer (e.g. 1024 or 16k) (default is %default)', default="1024")
217 downloader.add_option('--no-resize-buffer',
218 action='store_true', dest='noresizebuffer',
219 help='do not automatically adjust the buffer size. By default, the buffer size is automatically resized from an initial value of SIZE.', default=False)
220 downloader.add_option('--test', action='store_true', dest='test', default=False, help=optparse.SUPPRESS_HELP)
221
59ae15a5
PH
222 verbosity.add_option('-q', '--quiet',
223 action='store_true', dest='quiet', help='activates quiet mode', default=False)
224 verbosity.add_option('-s', '--simulate',
225 action='store_true', dest='simulate', help='do not download the video and do not write anything to disk', default=False)
226 verbosity.add_option('--skip-download',
227 action='store_true', dest='skip_download', help='do not download the video', default=False)
228 verbosity.add_option('-g', '--get-url',
229 action='store_true', dest='geturl', help='simulate, quiet but print URL', default=False)
230 verbosity.add_option('-e', '--get-title',
231 action='store_true', dest='gettitle', help='simulate, quiet but print title', default=False)
1a2adf3f 232 verbosity.add_option('--get-id',
233 action='store_true', dest='getid', help='simulate, quiet but print id', default=False)
59ae15a5
PH
234 verbosity.add_option('--get-thumbnail',
235 action='store_true', dest='getthumbnail',
236 help='simulate, quiet but print thumbnail URL', default=False)
237 verbosity.add_option('--get-description',
238 action='store_true', dest='getdescription',
239 help='simulate, quiet but print video description', default=False)
240 verbosity.add_option('--get-filename',
241 action='store_true', dest='getfilename',
242 help='simulate, quiet but print output filename', default=False)
243 verbosity.add_option('--get-format',
244 action='store_true', dest='getformat',
245 help='simulate, quiet but print output format', default=False)
7311fef8 246 verbosity.add_option('--newline',
5717d91a 247 action='store_true', dest='progress_with_newline', help='output progress bar as new lines', default=False)
59ae15a5
PH
248 verbosity.add_option('--no-progress',
249 action='store_true', dest='noprogress', help='do not print progress bar', default=False)
250 verbosity.add_option('--console-title',
251 action='store_true', dest='consoletitle',
252 help='display progress in console titlebar', default=False)
253 verbosity.add_option('-v', '--verbose',
254 action='store_true', dest='verbose', help='print various debugging information', default=False)
855703e5
PH
255 verbosity.add_option('--dump-intermediate-pages',
256 action='store_true', dest='dump_intermediate_pages', default=False,
257 help='print downloaded pages to debug problems(very verbose)')
59ae15a5 258
59ae15a5 259 filesystem.add_option('-t', '--title',
08b2ac74 260 action='store_true', dest='usetitle', help='use title in file name (default)', default=False)
59ae15a5 261 filesystem.add_option('--id',
08b2ac74 262 action='store_true', dest='useid', help='use only video ID in file name', default=False)
59ae15a5
PH
263 filesystem.add_option('-l', '--literal',
264 action='store_true', dest='usetitle', help='[deprecated] alias of --title', default=False)
265 filesystem.add_option('-A', '--auto-number',
266 action='store_true', dest='autonumber',
267 help='number downloaded files starting from 00000', default=False)
268 filesystem.add_option('-o', '--output',
74e3452b
JMF
269 dest='outtmpl', metavar='TEMPLATE',
270 help=('output filename template. Use %(title)s to get the title, '
271 '%(uploader)s for the uploader name, %(uploader_id)s for the uploader nickname if different, '
272 '%(autonumber)s to get an automatically incremented number, '
273 '%(ext)s for the filename extension, %(upload_date)s for the upload date (YYYYMMDD), '
274 '%(extractor)s for the provider (youtube, metacafe, etc), '
275 '%(id)s for the video id , %(playlist)s for the playlist the video is in, '
276 '%(playlist_index)s for the position in the playlist and %% for a literal percent. '
277 'Use - to output to stdout. Can also be used to download to a different directory, '
278 'for example with -o \'/my/downloads/%(uploader)s/%(title)s-%(id)s.%(ext)s\' .'))
213c31ae
SK
279 filesystem.add_option('--autonumber-size',
280 dest='autonumber_size', metavar='NUMBER',
281 help='Specifies the number of digits in %(autonumber)s when it is present in output filename template or --autonumber option is given')
59ae15a5
PH
282 filesystem.add_option('--restrict-filenames',
283 action='store_true', dest='restrictfilenames',
284 help='Restrict filenames to only ASCII characters, and avoid "&" and spaces in filenames', default=False)
285 filesystem.add_option('-a', '--batch-file',
286 dest='batchfile', metavar='FILE', help='file containing URLs to download (\'-\' for stdin)')
287 filesystem.add_option('-w', '--no-overwrites',
288 action='store_true', dest='nooverwrites', help='do not overwrite files', default=False)
289 filesystem.add_option('-c', '--continue',
290 action='store_true', dest='continue_dl', help='resume partially downloaded files', default=True)
291 filesystem.add_option('--no-continue',
292 action='store_false', dest='continue_dl',
293 help='do not resume partially downloaded files (restart from beginning)')
294 filesystem.add_option('--cookies',
295 dest='cookiefile', metavar='FILE', help='file to read cookies from and dump cookie jar in')
296 filesystem.add_option('--no-part',
297 action='store_true', dest='nopart', help='do not use .part files', default=False)
298 filesystem.add_option('--no-mtime',
299 action='store_false', dest='updatetime',
300 help='do not use the Last-modified header to set the file modification time', default=True)
301 filesystem.add_option('--write-description',
302 action='store_true', dest='writedescription',
303 help='write video description to a .description file', default=False)
304 filesystem.add_option('--write-info-json',
305 action='store_true', dest='writeinfojson',
306 help='write video metadata to a .info.json file', default=False)
11d9224e
PH
307 filesystem.add_option('--write-thumbnail',
308 action='store_true', dest='writethumbnail',
309 help='write thumbnail image to disk', default=False)
59ae15a5
PH
310
311
312 postproc.add_option('-x', '--extract-audio', action='store_true', dest='extractaudio', default=False,
313 help='convert video files to audio-only files (requires ffmpeg or avconv and ffprobe or avprobe)')
314 postproc.add_option('--audio-format', metavar='FORMAT', dest='audioformat', default='best',
510e6f6d 315 help='"best", "aac", "vorbis", "mp3", "m4a", "opus", or "wav"; best by default')
59ae15a5
PH
316 postproc.add_option('--audio-quality', metavar='QUALITY', dest='audioquality', default='5',
317 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
318 postproc.add_option('--recode-video', metavar='FORMAT', dest='recodevideo', default=None,
319 help='Encode the video to another format if necessary (currently supported: mp4|flv|ogg|webm)')
59ae15a5
PH
320 postproc.add_option('-k', '--keep-video', action='store_true', dest='keepvideo', default=False,
321 help='keeps the video file on disk after the post-processing; the video is erased by default')
f0648fc1
BPG
322 postproc.add_option('--no-post-overwrites', action='store_true', dest='nopostoverwrites', default=False,
323 help='do not overwrite post-processed files; the post-processed files are overwritten by default')
59ae15a5
PH
324
325
326 parser.add_option_group(general)
327 parser.add_option_group(selection)
0beb3add 328 parser.add_option_group(downloader)
59ae15a5
PH
329 parser.add_option_group(filesystem)
330 parser.add_option_group(verbosity)
331 parser.add_option_group(video_format)
332 parser.add_option_group(authentication)
333 parser.add_option_group(postproc)
334
75b5c590
PH
335 if overrideArguments is not None:
336 opts, args = parser.parse_args(overrideArguments)
337 if opts.verbose:
93eb15c5 338 sys.stderr.write(u'[debug] Override config: ' + repr(overrideArguments) + '\n')
59ae15a5 339 else:
75b5c590
PH
340 xdg_config_home = os.environ.get('XDG_CONFIG_HOME')
341 if xdg_config_home:
342 userConfFile = os.path.join(xdg_config_home, 'youtube-dl.conf')
343 else:
344 userConfFile = os.path.join(os.path.expanduser('~'), '.config', 'youtube-dl.conf')
345 systemConf = _readOptions('/etc/youtube-dl.conf')
346 userConf = _readOptions(userConfFile)
347 commandLineConf = sys.argv[1:]
348 argv = systemConf + userConf + commandLineConf
349 opts, args = parser.parse_args(argv)
c76cb6d5 350 if opts.verbose:
93eb15c5
FV
351 sys.stderr.write(u'[debug] System config: ' + repr(systemConf) + '\n')
352 sys.stderr.write(u'[debug] User config: ' + repr(userConf) + '\n')
353 sys.stderr.write(u'[debug] Command-line args: ' + repr(commandLineConf) + '\n')
8c42c506 354
59ae15a5 355 return parser, opts, args
235b3ba4 356
b8ad4f02 357def _real_main(argv=None):
0d94f247
PH
358 # Compatibility fixes for Windows
359 if sys.platform == 'win32':
360 # https://github.com/rg3/youtube-dl/issues/820
361 codecs.register(lambda name: codecs.lookup('utf-8') if name == 'cp65001' else None)
362
b8ad4f02 363 parser, opts, args = parseOpts(argv)
59ae15a5
PH
364
365 # Open appropriate CookieJar
366 if opts.cookiefile is None:
367 jar = compat_cookiejar.CookieJar()
368 else:
369 try:
370 jar = compat_cookiejar.MozillaCookieJar(opts.cookiefile)
229cac75 371 if os.access(opts.cookiefile, os.R_OK):
59ae15a5
PH
372 jar.load()
373 except (IOError, OSError) as err:
229cac75
PH
374 if opts.verbose:
375 traceback.print_exc()
376 sys.stderr.write(u'ERROR: unable to open cookie file\n')
377 sys.exit(101)
59ae15a5
PH
378 # Set user agent
379 if opts.user_agent is not None:
380 std_headers['User-Agent'] = opts.user_agent
28535652
BH
381
382 # Set referer
383 if opts.referer is not None:
384 std_headers['Referer'] = opts.referer
59ae15a5
PH
385
386 # Dump user agent
387 if opts.dump_user_agent:
93eb15c5 388 compat_print(std_headers['User-Agent'])
59ae15a5
PH
389 sys.exit(0)
390
391 # Batch file verification
392 batchurls = []
393 if opts.batchfile is not None:
394 try:
395 if opts.batchfile == '-':
396 batchfd = sys.stdin
397 else:
398 batchfd = open(opts.batchfile, 'r')
399 batchurls = batchfd.readlines()
400 batchurls = [x.strip() for x in batchurls]
401 batchurls = [x for x in batchurls if len(x) > 0 and not re.search(r'^[#/;]', x)]
05afc96b
JMF
402 if opts.verbose:
403 sys.stderr.write(u'[debug] Batch file urls: ' + repr(batchurls) + u'\n')
59ae15a5
PH
404 except IOError:
405 sys.exit(u'ERROR: batch file could not be read')
406 all_urls = batchurls + args
407 all_urls = [url.strip() for url in all_urls]
408
409 # General configuration
410 cookie_processor = compat_urllib_request.HTTPCookieProcessor(jar)
53f72b11
PH
411 if opts.proxy is not None:
412 if opts.proxy == '':
413 proxies = {}
414 else:
415 proxies = {'http': opts.proxy, 'https': opts.proxy}
5fb16555
PH
416 else:
417 proxies = compat_urllib_request.getproxies()
418 # Set HTTPS proxy to HTTP one if given (https://github.com/rg3/youtube-dl/issues/805)
419 if 'http' in proxies and 'https' not in proxies:
420 proxies['https'] = proxies['http']
434aca5b 421 proxy_handler = compat_urllib_request.ProxyHandler(proxies)
ea6d901e 422 https_handler = make_HTTPS_handler(opts)
c34407d1 423 opener = compat_urllib_request.build_opener(https_handler, proxy_handler, cookie_processor, YoutubeDLHandler())
59ae15a5
PH
424 compat_urllib_request.install_opener(opener)
425 socket.setdefaulttimeout(300) # 5 minutes should be enough (famous last words)
426
427 extractors = gen_extractors()
428
429 if opts.list_extractors:
7dba9cd0 430 for ie in sorted(extractors, key=lambda ie: ie.IE_NAME.lower()):
93eb15c5 431 compat_print(ie.IE_NAME + (' (CURRENTLY BROKEN)' if not ie._WORKING else ''))
1a2c3c0f
FV
432 matchedUrls = [url for url in all_urls if ie.suitable(url)]
433 all_urls = [url for url in all_urls if url not in matchedUrls]
59ae15a5 434 for mu in matchedUrls:
93eb15c5 435 compat_print(u' ' + mu)
59ae15a5 436 sys.exit(0)
0f818663
PH
437 if opts.list_extractor_descriptions:
438 for ie in sorted(extractors, key=lambda ie: ie.IE_NAME.lower()):
439 if not ie._WORKING:
440 continue
441 desc = getattr(ie, 'IE_DESC', ie.IE_NAME)
442 if hasattr(ie, 'SEARCH_KEY'):
443 _SEARCHES = (u'cute kittens', u'slithering pythons', u'falling cat', u'angry poodle', u'purple fish', u'running tortoise')
444 _COUNTS = (u'', u'5', u'10', u'all')
445 desc += u' (Example: "%s%s:%s" )' % (ie.SEARCH_KEY, random.choice(_COUNTS), random.choice(_SEARCHES))
446 compat_print(desc)
447 sys.exit(0)
448
59ae15a5
PH
449
450 # Conflicting, missing and erroneous options
451 if opts.usenetrc and (opts.username is not None or opts.password is not None):
452 parser.error(u'using .netrc conflicts with giving username/password')
453 if opts.password is not None and opts.username is None:
c6c19746 454 parser.error(u' account username missing\n')
59ae15a5
PH
455 if opts.outtmpl is not None and (opts.usetitle or opts.autonumber or opts.useid):
456 parser.error(u'using output template conflicts with using title, video ID or auto number')
457 if opts.usetitle and opts.useid:
458 parser.error(u'using title conflicts with using video ID')
459 if opts.username is not None and opts.password is None:
460 opts.password = getpass.getpass(u'Type account password and press return:')
461 if opts.ratelimit is not None:
462 numeric_limit = FileDownloader.parse_bytes(opts.ratelimit)
463 if numeric_limit is None:
464 parser.error(u'invalid rate limit specified')
465 opts.ratelimit = numeric_limit
9e982f9e
JC
466 if opts.min_filesize is not None:
467 numeric_limit = FileDownloader.parse_bytes(opts.min_filesize)
468 if numeric_limit is None:
469 parser.error(u'invalid min_filesize specified')
470 opts.min_filesize = numeric_limit
471 if opts.max_filesize is not None:
472 numeric_limit = FileDownloader.parse_bytes(opts.max_filesize)
473 if numeric_limit is None:
474 parser.error(u'invalid max_filesize specified')
475 opts.max_filesize = numeric_limit
59ae15a5
PH
476 if opts.retries is not None:
477 try:
478 opts.retries = int(opts.retries)
479 except (TypeError, ValueError) as err:
480 parser.error(u'invalid retry count specified')
481 if opts.buffersize is not None:
482 numeric_buffersize = FileDownloader.parse_bytes(opts.buffersize)
483 if numeric_buffersize is None:
484 parser.error(u'invalid buffer size specified')
485 opts.buffersize = numeric_buffersize
486 try:
487 opts.playliststart = int(opts.playliststart)
488 if opts.playliststart <= 0:
489 raise ValueError(u'Playlist start must be positive')
490 except (TypeError, ValueError) as err:
491 parser.error(u'invalid playlist start number specified')
492 try:
493 opts.playlistend = int(opts.playlistend)
494 if opts.playlistend != -1 and (opts.playlistend <= 0 or opts.playlistend < opts.playliststart):
495 raise ValueError(u'Playlist end must be greater than playlist start')
496 except (TypeError, ValueError) as err:
497 parser.error(u'invalid playlist end number specified')
498 if opts.extractaudio:
510e6f6d 499 if opts.audioformat not in ['best', 'aac', 'mp3', 'm4a', 'opus', 'vorbis', 'wav']:
59ae15a5
PH
500 parser.error(u'invalid audio format specified')
501 if opts.audioquality:
502 opts.audioquality = opts.audioquality.strip('k').strip('K')
503 if not opts.audioquality.isdigit():
504 parser.error(u'invalid audio quality specified')
7851b379
PH
505 if opts.recodevideo is not None:
506 if opts.recodevideo not in ['mp4', 'flv', 'webm', 'ogg']:
507 parser.error(u'invalid video recode format specified')
bd558525
JMF
508 if opts.date is not None:
509 date = DateRange.day(opts.date)
510 else:
511 date = DateRange(opts.dateafter, opts.datebefore)
59ae15a5 512
5cb9c312
PH
513 if sys.version_info < (3,):
514 # In Python 2, sys.argv is a bytestring (also note http://bugs.python.org/issue2128 for Windows systems)
0be41ec2
PH
515 if opts.outtmpl is not None:
516 opts.outtmpl = opts.outtmpl.decode(preferredencoding())
5cb9c312
PH
517 outtmpl =((opts.outtmpl is not None and opts.outtmpl)
518 or (opts.format == '-1' and opts.usetitle and u'%(title)s-%(id)s-%(format)s.%(ext)s')
519 or (opts.format == '-1' and u'%(id)s-%(format)s.%(ext)s')
520 or (opts.usetitle and opts.autonumber and u'%(autonumber)s-%(title)s-%(id)s.%(ext)s')
521 or (opts.usetitle and u'%(title)s-%(id)s.%(ext)s')
522 or (opts.useid and u'%(id)s.%(ext)s')
523 or (opts.autonumber and u'%(autonumber)s-%(id)s.%(ext)s')
08b2ac74 524 or u'%(title)s-%(id)s.%(ext)s')
8271226a 525
8222d8de
JMF
526 # YoutubeDL
527 ydl = YoutubeDL({
59ae15a5
PH
528 'usenetrc': opts.usenetrc,
529 'username': opts.username,
530 'password': opts.password,
c6c19746 531 'videopassword': opts.videopassword,
1a2adf3f 532 '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
533 'forceurl': opts.geturl,
534 'forcetitle': opts.gettitle,
1a2adf3f 535 'forceid': opts.getid,
59ae15a5
PH
536 'forcethumbnail': opts.getthumbnail,
537 'forcedescription': opts.getdescription,
538 'forcefilename': opts.getfilename,
539 'forceformat': opts.getformat,
540 'simulate': opts.simulate,
1a2adf3f 541 '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
542 'format': opts.format,
543 'format_limit': opts.format_limit,
544 'listformats': opts.listformats,
5cb9c312 545 'outtmpl': outtmpl,
213c31ae 546 'autonumber_size': opts.autonumber_size,
59ae15a5
PH
547 'restrictfilenames': opts.restrictfilenames,
548 'ignoreerrors': opts.ignoreerrors,
549 'ratelimit': opts.ratelimit,
550 'nooverwrites': opts.nooverwrites,
551 'retries': opts.retries,
552 'buffersize': opts.buffersize,
553 'noresizebuffer': opts.noresizebuffer,
554 'continuedl': opts.continue_dl,
555 'noprogress': opts.noprogress,
5717d91a 556 'progress_with_newline': opts.progress_with_newline,
59ae15a5
PH
557 'playliststart': opts.playliststart,
558 'playlistend': opts.playlistend,
559 'logtostderr': opts.outtmpl == '-',
560 'consoletitle': opts.consoletitle,
561 'nopart': opts.nopart,
562 'updatetime': opts.updatetime,
563 'writedescription': opts.writedescription,
564 'writeinfojson': opts.writeinfojson,
11d9224e 565 'writethumbnail': opts.writethumbnail,
59ae15a5 566 'writesubtitles': opts.writesubtitles,
b004821f 567 'writeautomaticsub': opts.writeautomaticsub,
ae608b80 568 'allsubtitles': opts.allsubtitles,
2a4093ea 569 'listsubtitles': opts.listsubtitles,
9e62bc44 570 'subtitlesformat': opts.subtitlesformat,
59ae15a5 571 'subtitleslang': opts.subtitleslang,
8271226a
PH
572 'matchtitle': decodeOption(opts.matchtitle),
573 'rejecttitle': decodeOption(opts.rejecttitle),
59ae15a5
PH
574 'max_downloads': opts.max_downloads,
575 'prefer_free_formats': opts.prefer_free_formats,
576 'verbose': opts.verbose,
855703e5 577 'dump_intermediate_pages': opts.dump_intermediate_pages,
8d5d3a5d 578 'test': opts.test,
7851b379 579 'keepvideo': opts.keepvideo,
9e982f9e 580 'min_filesize': opts.min_filesize,
bd558525 581 'max_filesize': opts.max_filesize,
11d9224e 582 'daterange': date,
59ae15a5
PH
583 })
584
585 if opts.verbose:
f3bab004 586 sys.stderr.write(u'[debug] youtube-dl version ' + __version__ + u'\n')
4e38899e 587 try:
deacef65
PH
588 sp = subprocess.Popen(
589 ['git', 'rev-parse', '--short', 'HEAD'],
590 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
591 cwd=os.path.dirname(os.path.abspath(__file__)))
4e38899e
FV
592 out, err = sp.communicate()
593 out = out.decode().strip()
594 if re.match('[0-9a-f]+', out):
f3bab004 595 sys.stderr.write(u'[debug] Git HEAD: ' + out + u'\n')
4e38899e 596 except:
de29c414
PH
597 try:
598 sys.exc_clear()
599 except:
600 pass
f3bab004
PH
601 sys.stderr.write(u'[debug] Python version %s - %s' %(platform.python_version(), platform.platform()) + u'\n')
602 sys.stderr.write(u'[debug] Proxy map: ' + str(proxy_handler.proxies) + u'\n')
59ae15a5 603
023fa8c4 604 ydl.add_default_info_extractors()
59ae15a5
PH
605
606 # PostProcessors
607 if opts.extractaudio:
8222d8de 608 ydl.add_post_processor(FFmpegExtractAudioPP(preferredcodec=opts.audioformat, preferredquality=opts.audioquality, nopostoverwrites=opts.nopostoverwrites))
7851b379 609 if opts.recodevideo:
8222d8de 610 ydl.add_post_processor(FFmpegVideoConvertor(preferedformat=opts.recodevideo))
59ae15a5 611
67353612
PH
612 # Update version
613 if opts.update_self:
8222d8de 614 update_self(ydl.to_screen, opts.verbose, sys.argv[0])
67353612 615
59ae15a5
PH
616 # Maybe do nothing
617 if len(all_urls) < 1:
618 if not opts.update_self:
619 parser.error(u'you must provide at least one URL')
620 else:
621 sys.exit()
622
623 try:
8222d8de 624 retcode = ydl.download(all_urls)
59ae15a5 625 except MaxDownloadsReached:
8222d8de 626 ydl.to_screen(u'--max-download limit reached, aborting.')
59ae15a5
PH
627 retcode = 101
628
629 # Dump cookie jar if requested
630 if opts.cookiefile is not None:
631 try:
632 jar.save()
633 except (IOError, OSError) as err:
634 sys.exit(u'ERROR: unable to save cookie jar')
635
636 sys.exit(retcode)
235b3ba4 637
b8ad4f02 638def main(argv=None):
59ae15a5 639 try:
b8ad4f02 640 _real_main(argv)
59ae15a5
PH
641 except DownloadError:
642 sys.exit(1)
643 except SameFileError:
644 sys.exit(u'ERROR: fixed output name but more than one file to download')
645 except KeyboardInterrupt:
646 sys.exit(u'\nERROR: Interrupted by user')