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