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