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