]> jfr.im git - yt-dlp.git/blame - youtube_dl/__init__.py
[cnn] Improve thumbnail extraction
[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',
a623df4c 34 'Andras Elso',
b5bdc269 35 'Jelle van der Waa',
d3793638 36 'Marcin Cieślak',
0a120f74 37 'Anton Larionov',
38b2db6a 38 'Takuya Tsuchida',
87968574 39 'Sergey M.',
b83be81d 40 'Michael Orlitzky',
e63fc1be 41 'Chris Gahan',
a7732b67 42 'Saimadhav Heblikar',
2a893862 43 'Mike Col',
6d784e87 44 'Oleg Prutz',
0cea52cc 45 'pulpe',
845d14d3 46 'Andreas Schmitz',
cbffec0c 47 'Michael Kaiser',
96d16370 48 'Niklas Laxström',
f38da667 49 'David Triendl',
a339d7ba 50 'Anthony Weems',
dc3727b6 51 'David Wagner',
2fcec131 52 'Juan C. Olivares',
855e2750 53 'Mattias Harrysson',
2cc0082d 54 'phaer',
610e47c8 55 'Sainyam Kapoor',
bbe99d26 56 'Nicolas Évrard',
ccdd34ed 57 'Jason Normore',
25dfe0eb 58 'Hoje Lee',
c2ef2923 59 'Adam Thalhammer',
ba7a1de0 60)
235b3ba4
PH
61
62__license__ = 'Public Domain'
235b3ba4 63
0d94f247 64import codecs
8f563f32 65import io
fd46a318 66import locale
c9ed14e6 67import optparse
235b3ba4 68import os
0f818663 69import random
235b3ba4 70import re
c9ed14e6 71import shlex
235b3ba4 72import sys
235b3ba4 73
c496ca96 74
a4fd0415 75from .utils import (
e68301af 76 compat_getpass,
a4fd0415 77 compat_print,
a4fd0415 78 DateRange,
acd69589 79 DEFAULT_OUTTMPL,
a4fd0415 80 decodeOption,
1c088fa8 81 get_term_width,
a4fd0415
PH
82 DownloadError,
83 get_cachedir,
a4fd0415 84 MaxDownloadsReached,
a4fd0415 85 preferredencoding,
62e609ab 86 read_batch_urls,
a4fd0415 87 SameFileError,
e3946f98 88 setproctitle,
a4fd0415
PH
89 std_headers,
90 write_string,
a4fd0415 91)
d5ed35b6 92from .update import update_self
a4fd0415
PH
93from .FileDownloader import (
94 FileDownloader,
95)
0824c28c 96from .extractor import gen_extractors
dca08720 97from .version import __version__
8222d8de 98from .YoutubeDL import YoutubeDL
56327689 99from .postprocessor import (
0c14e2fb 100 AtomicParsleyPP,
149254d0 101 FFmpegAudioFixPP,
a4fd0415
PH
102 FFmpegMetadataPP,
103 FFmpegVideoConvertor,
104 FFmpegExtractAudioPP,
105 FFmpegEmbedSubtitlePP,
e63fc1be 106 XAttrMetadataPP,
a4fd0415
PH
107)
108
235b3ba4 109
75b5c590 110def parseOpts(overrideArguments=None):
fb27c229 111 def _readOptions(filename_bytes, default=[]):
59ae15a5
PH
112 try:
113 optionf = open(filename_bytes)
114 except IOError:
fb27c229 115 return default # silently skip if file is not present
59ae15a5 116 try:
a0eaa341
PH
117 res = []
118 for l in optionf:
119 res += shlex.split(l, comments=True)
59ae15a5
PH
120 finally:
121 optionf.close()
122 return res
123
588128d0
PH
124 def _readUserConf():
125 xdg_config_home = os.environ.get('XDG_CONFIG_HOME')
126 if xdg_config_home:
127 userConfFile = os.path.join(xdg_config_home, 'youtube-dl', 'config')
128 if not os.path.isfile(userConfFile):
129 userConfFile = os.path.join(xdg_config_home, 'youtube-dl.conf')
130 else:
131 userConfFile = os.path.join(os.path.expanduser('~'), '.config', 'youtube-dl', 'config')
132 if not os.path.isfile(userConfFile):
133 userConfFile = os.path.join(os.path.expanduser('~'), '.config', 'youtube-dl.conf')
134 userConf = _readOptions(userConfFile, None)
135
136 if userConf is None:
137 appdata_dir = os.environ.get('appdata')
138 if appdata_dir:
139 userConf = _readOptions(
140 os.path.join(appdata_dir, 'youtube-dl', 'config'),
141 default=None)
142 if userConf is None:
143 userConf = _readOptions(
144 os.path.join(appdata_dir, 'youtube-dl', 'config.txt'),
145 default=None)
146
147 if userConf is None:
148 userConf = _readOptions(
149 os.path.join(os.path.expanduser('~'), 'youtube-dl.conf'),
150 default=None)
151 if userConf is None:
152 userConf = _readOptions(
153 os.path.join(os.path.expanduser('~'), 'youtube-dl.conf.txt'),
154 default=None)
155
156 if userConf is None:
157 userConf = []
158
159 return userConf
160
59ae15a5
PH
161 def _format_option_string(option):
162 ''' ('-o', '--option') -> -o, --format METAVAR'''
163
164 opts = []
165
166 if option._short_opts:
167 opts.append(option._short_opts[0])
168 if option._long_opts:
169 opts.append(option._long_opts[0])
170 if len(opts) > 1:
171 opts.insert(1, ', ')
172
173 if option.takes_value(): opts.append(' %s' % option.metavar)
174
175 return "".join(opts)
176
d6e203b3
IM
177 def _comma_separated_values_options_callback(option, opt_str, value, parser):
178 setattr(parser.values, option.dest, value.split(','))
179
920ef077
JMF
180 def _hide_login_info(opts):
181 opts = list(opts)
3126050c 182 for private_opt in ['-p', '--password', '-u', '--username', '--video-password']:
920ef077
JMF
183 try:
184 i = opts.index(private_opt)
185 opts[i+1] = '<PRIVATE>'
186 except ValueError:
187 pass
188 return opts
189
59ae15a5
PH
190 max_width = 80
191 max_help_position = 80
192
193 # No need to wrap help messages if we're on a wide console
1c088fa8 194 columns = get_term_width()
59ae15a5
PH
195 if columns: max_width = columns
196
197 fmt = optparse.IndentedHelpFormatter(width=max_width, max_help_position=max_help_position)
198 fmt.format_option_strings = _format_option_string
199
200 kw = {
201 'version' : __version__,
202 'formatter' : fmt,
203 'usage' : '%prog [options] url [url...]',
204 'conflict_handler' : 'resolve',
205 }
206
207 parser = optparse.OptionParser(**kw)
208
209 # option groups
210 general = optparse.OptionGroup(parser, 'General Options')
211 selection = optparse.OptionGroup(parser, 'Video Selection')
212 authentication = optparse.OptionGroup(parser, 'Authentication Options')
213 video_format = optparse.OptionGroup(parser, 'Video Format Options')
505c28aa 214 subtitles = optparse.OptionGroup(parser, 'Subtitle Options')
0beb3add 215 downloader = optparse.OptionGroup(parser, 'Download Options')
59ae15a5
PH
216 postproc = optparse.OptionGroup(parser, 'Post-processing Options')
217 filesystem = optparse.OptionGroup(parser, 'Filesystem Options')
218 verbosity = optparse.OptionGroup(parser, 'Verbosity / Simulation Options')
219
220 general.add_option('-h', '--help',
221 action='help', help='print this help text and exit')
222 general.add_option('-v', '--version',
223 action='version', help='print program version and exit')
224 general.add_option('-U', '--update',
f631c331 225 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 226 general.add_option('-i', '--ignore-errors',
98c4b8fa 227 action='store_true', dest='ignoreerrors', help='continue on download errors, for example to skip unavailable videos in a playlist', default=False)
41fd7c7e
PH
228 general.add_option('--abort-on-error',
229 action='store_false', dest='ignoreerrors',
230 help='Abort downloading of further videos (in the playlist or the command line) if an error occurs')
59ae15a5
PH
231 general.add_option('--dump-user-agent',
232 action='store_true', dest='dump_user_agent',
233 help='display the current browser identification', default=False)
234 general.add_option('--user-agent',
235 dest='user_agent', help='specify a custom user agent', metavar='UA')
28535652 236 general.add_option('--referer',
3820df01
JMF
237 dest='referer', help='specify a custom referer, use if the video access is restricted to one domain',
238 metavar='REF', default=None)
410afb20
AA
239 general.add_option('--add-header',
240 dest='headers', help='specify a custom HTTP header and its value, separated by a colon \':\'. You can use this option multiple times', action="append",
241 metavar='FIELD:VALUE')
59ae15a5
PH
242 general.add_option('--list-extractors',
243 action='store_true', dest='list_extractors',
244 help='List all supported extractors and the URLs they would handle', default=False)
62067cb9 245 general.add_option('--extractor-descriptions',
0f818663
PH
246 action='store_true', dest='list_extractor_descriptions',
247 help='Output descriptions of all supported extractors', default=False)
cf6758d2
PH
248 general.add_option(
249 '--proxy', dest='proxy', default=None, metavar='URL',
250 help='Use the specified HTTP/HTTPS proxy. Pass in an empty string (--proxy "") for direct connection')
ea6d901e 251 general.add_option('--no-check-certificate', action='store_true', dest='no_check_certificate', default=False, help='Suppress HTTPS certificate validation.')
7e8c0af0 252 general.add_option(
29a1ab2a 253 '--prefer-insecure', '--prefer-unsecure', action='store_true', dest='prefer_insecure',
7e8c0af0 254 help='Use an unencrypted connection to retrieve information about the video. (Currently supported only for YouTube)')
7f747732 255 general.add_option(
cce722b7 256 '--cache-dir', dest='cachedir', default=get_cachedir(), metavar='DIR',
7c094bfe 257 help='Location in the filesystem where youtube-dl can store some downloaded information permanently. By default $XDG_CACHE_HOME/youtube-dl or ~/.cache/youtube-dl . At the moment, only YouTube player files (for videos with obfuscated signatures) are cached, but that may change.')
7f747732
PH
258 general.add_option(
259 '--no-cache-dir', action='store_const', const=None, dest='cachedir',
260 help='Disable filesystem caching')
6ad14cab
PH
261 general.add_option(
262 '--socket-timeout', dest='socket_timeout',
9656ee5d 263 type=float, default=None, help=u'Time to wait before giving up, in seconds')
0783b09b
PH
264 general.add_option(
265 '--bidi-workaround', dest='bidi_workaround', action='store_true',
5d681e96 266 help=u'Work around terminals that lack bidirectional text support. Requires bidiv or fribidi executable in PATH')
9c1fc022
PH
267 general.add_option(
268 '--default-search',
269 dest='default_search', metavar='PREFIX',
270 help='Use this prefix for unqualified URLs. For example "gvsearch2:" downloads two videos from google videos for youtube-dl "large apple". By default (with value "auto") youtube-dl guesses.')
588128d0
PH
271 general.add_option(
272 '--ignore-config',
273 action='store_true',
274 help='Do not read configuration files. When given in the global configuration file /etc/youtube-dl.conf: do not read the user configuration in ~/.config/youtube-dl.conf (%APPDATA%/youtube-dl/config.txt on Windows)')
62fec3b2
PH
275 general.add_option(
276 '--encoding', dest='encoding', metavar='ENCODING',
277 help='Force the specified encoding (experimental)')
588128d0 278
a19fd00c
PH
279 selection.add_option(
280 '--playlist-start',
281 dest='playliststart', metavar='NUMBER', default=1, type=int,
282 help='playlist video to start at (default is %default)')
283 selection.add_option(
284 '--playlist-end',
285 dest='playlistend', metavar='NUMBER', default=None, type=int,
286 help='playlist video to end at (default is last)')
59ae15a5
PH
287 selection.add_option('--match-title', dest='matchtitle', metavar='REGEX',help='download only matching titles (regex or caseless sub-string)')
288 selection.add_option('--reject-title', dest='rejecttitle', metavar='REGEX',help='skip download for matching titles (regex or caseless sub-string)')
0c75c3fa
PH
289 selection.add_option('--max-downloads', metavar='NUMBER',
290 dest='max_downloads', type=int, default=None,
291 help='Abort after downloading NUMBER files')
dbf2ba3d
PH
292 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)
293 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 294 selection.add_option('--date', metavar='DATE', dest='date', help='download only videos uploaded in this date', default=None)
bac268e2
PH
295 selection.add_option(
296 '--datebefore', metavar='DATE', dest='datebefore', default=None,
297 help='download only videos uploaded on or before this date (i.e. inclusive)')
298 selection.add_option(
299 '--dateafter', metavar='DATE', dest='dateafter', default=None,
300 help='download only videos uploaded on or after this date (i.e. inclusive)')
5fe18bdb
PH
301 selection.add_option(
302 '--min-views', metavar='COUNT', dest='min_views',
303 default=None, type=int,
304 help="Do not download any videos with less than COUNT views",)
305 selection.add_option(
306 '--max-views', metavar='COUNT', dest='max_views',
307 default=None, type=int,
308 help="Do not download any videos with more than COUNT views",)
47192f92 309 selection.add_option('--no-playlist', action='store_true', dest='noplaylist', help='download only the currently playing video', default=False)
8dbe9899
PH
310 selection.add_option('--age-limit', metavar='YEARS', dest='age_limit',
311 help='download only videos suitable for the given age',
312 default=None, type=int)
c1c9a79c
PH
313 selection.add_option('--download-archive', metavar='FILE',
314 dest='download_archive',
36a826a5 315 help='Download only videos not listed in the archive file. Record the IDs of all downloaded videos in it.')
7b0817e8
PH
316 selection.add_option(
317 '--include-ads', dest='include_ads',
318 action='store_true',
319 help='Download advertisements as well (experimental)')
8b1be5cd 320 selection.add_option(
4919603f
PH
321 '--youtube-include-dash-manifest', action='store_true',
322 dest='youtube_include_dash_manifest', default=False,
323 help='Try to download the DASH manifest on YouTube videos (experimental)')
9e982f9e 324
59ae15a5
PH
325 authentication.add_option('-u', '--username',
326 dest='username', metavar='USERNAME', help='account username')
327 authentication.add_option('-p', '--password',
328 dest='password', metavar='PASSWORD', help='account password')
329 authentication.add_option('-n', '--netrc',
330 action='store_true', dest='usenetrc', help='use .netrc authentication data', default=False)
c6c19746 331 authentication.add_option('--video-password',
67d28bff 332 dest='videopassword', metavar='PASSWORD', help='video password (vimeo, smotri)')
59ae15a5
PH
333
334
335 video_format.add_option('-f', '--format',
de3ef3ed 336 action='store', dest='format', metavar='FORMAT', default=None,
bc6d5978 337 help='video format code, specify the order of preference using slashes: "-f 22/17/18". "-f mp4" and "-f flv" are also supported. You can also use the special names "best", "bestvideo", "bestaudio", "worst", "worstvideo" and "worstaudio". By default, youtube-dl will pick the best quality.')
59ae15a5
PH
338 video_format.add_option('--all-formats',
339 action='store_const', dest='format', help='download all available video formats', const='all')
340 video_format.add_option('--prefer-free-formats',
341 action='store_true', dest='prefer_free_formats', default=False, help='prefer free video formats unless a specific one is requested')
342 video_format.add_option('--max-quality',
343 action='store', dest='format_limit', metavar='FORMAT', help='highest quality format to download')
344 video_format.add_option('-F', '--list-formats',
4950f308 345 action='store_true', dest='listformats', help='list all available formats')
505c28aa
IM
346
347 subtitles.add_option('--write-sub', '--write-srt',
59ae15a5 348 action='store_true', dest='writesubtitles',
953e32b2 349 help='write subtitle file', default=False)
505c28aa 350 subtitles.add_option('--write-auto-sub', '--write-automatic-sub',
b004821f 351 action='store_true', dest='writeautomaticsub',
953e32b2 352 help='write automatic subtitle file (youtube only)', default=False)
505c28aa 353 subtitles.add_option('--all-subs',
ae608b80 354 action='store_true', dest='allsubtitles',
953e32b2 355 help='downloads all the available subtitles of the video', default=False)
505c28aa 356 subtitles.add_option('--list-subs',
2a4093ea 357 action='store_true', dest='listsubtitles',
953e32b2 358 help='lists all available subtitles for the video', default=False)
505c28aa 359 subtitles.add_option('--sub-format',
c3ab8f86 360 action='store', dest='subtitlesformat', metavar='FORMAT',
953e32b2 361 help='subtitle format (default=srt) ([sbv/vtt] youtube only)', default='srt')
d6e203b3
IM
362 subtitles.add_option('--sub-lang', '--sub-langs', '--srt-lang',
363 action='callback', dest='subtitleslangs', metavar='LANGS', type='str',
364 default=[], callback=_comma_separated_values_options_callback,
365 help='languages of the subtitles to download (optional) separated by commas, use IETF language tags like \'en,pt\'')
59ae15a5 366
0beb3add 367 downloader.add_option('-r', '--rate-limit',
cd054fc4 368 dest='ratelimit', metavar='LIMIT', help='maximum download rate in bytes per second (e.g. 50K or 4.2M)')
0beb3add
PH
369 downloader.add_option('-R', '--retries',
370 dest='retries', metavar='RETRIES', help='number of retries (default is %default)', default=10)
371 downloader.add_option('--buffer-size',
cd054fc4 372 dest='buffersize', metavar='SIZE', help='size of download buffer (e.g. 1024 or 16K) (default is %default)', default="1024")
0beb3add
PH
373 downloader.add_option('--no-resize-buffer',
374 action='store_true', dest='noresizebuffer',
375 help='do not automatically adjust the buffer size. By default, the buffer size is automatically resized from an initial value of SIZE.', default=False)
376 downloader.add_option('--test', action='store_true', dest='test', default=False, help=optparse.SUPPRESS_HELP)
377
59ae15a5
PH
378 verbosity.add_option('-q', '--quiet',
379 action='store_true', dest='quiet', help='activates quiet mode', default=False)
ad8915b7
PH
380 verbosity.add_option(
381 '--no-warnings',
382 dest='no_warnings', action='store_true', default=False,
383 help='Ignore warnings')
59ae15a5
PH
384 verbosity.add_option('-s', '--simulate',
385 action='store_true', dest='simulate', help='do not download the video and do not write anything to disk', default=False)
386 verbosity.add_option('--skip-download',
387 action='store_true', dest='skip_download', help='do not download the video', default=False)
388 verbosity.add_option('-g', '--get-url',
389 action='store_true', dest='geturl', help='simulate, quiet but print URL', default=False)
390 verbosity.add_option('-e', '--get-title',
391 action='store_true', dest='gettitle', help='simulate, quiet but print title', default=False)
1a2adf3f 392 verbosity.add_option('--get-id',
393 action='store_true', dest='getid', help='simulate, quiet but print id', default=False)
59ae15a5
PH
394 verbosity.add_option('--get-thumbnail',
395 action='store_true', dest='getthumbnail',
396 help='simulate, quiet but print thumbnail URL', default=False)
397 verbosity.add_option('--get-description',
398 action='store_true', dest='getdescription',
399 help='simulate, quiet but print video description', default=False)
525ef922
PH
400 verbosity.add_option('--get-duration',
401 action='store_true', dest='getduration',
402 help='simulate, quiet but print video length', default=False)
59ae15a5
PH
403 verbosity.add_option('--get-filename',
404 action='store_true', dest='getfilename',
405 help='simulate, quiet but print output filename', default=False)
406 verbosity.add_option('--get-format',
407 action='store_true', dest='getformat',
408 help='simulate, quiet but print output format', default=False)
9d153818
MF
409 verbosity.add_option('-j', '--dump-json',
410 action='store_true', dest='dumpjson',
330edf2d 411 help='simulate, quiet but print JSON information. See --output for a description of available keys.', default=False)
7311fef8 412 verbosity.add_option('--newline',
5717d91a 413 action='store_true', dest='progress_with_newline', help='output progress bar as new lines', default=False)
59ae15a5
PH
414 verbosity.add_option('--no-progress',
415 action='store_true', dest='noprogress', help='do not print progress bar', default=False)
416 verbosity.add_option('--console-title',
417 action='store_true', dest='consoletitle',
418 help='display progress in console titlebar', default=False)
419 verbosity.add_option('-v', '--verbose',
420 action='store_true', dest='verbose', help='print various debugging information', default=False)
855703e5
PH
421 verbosity.add_option('--dump-intermediate-pages',
422 action='store_true', dest='dump_intermediate_pages', default=False,
67d28bff 423 help='print downloaded pages to debug problems (very verbose)')
d41e6efc
PH
424 verbosity.add_option('--write-pages',
425 action='store_true', dest='write_pages', default=False,
06dcbb71 426 help='Write downloaded intermediary pages to files in the current directory to debug problems')
edf3e38e
PH
427 verbosity.add_option('--youtube-print-sig-code',
428 action='store_true', dest='youtube_print_sig_code', default=False,
429 help=optparse.SUPPRESS_HELP)
a0ddb8a2
PH
430 verbosity.add_option('--print-traffic',
431 dest='debug_printtraffic', action='store_true', default=False,
4919603f
PH
432 help='Display sent and read HTTP traffic')
433
59ae15a5 434
59ae15a5 435 filesystem.add_option('-t', '--title',
08b2ac74 436 action='store_true', dest='usetitle', help='use title in file name (default)', default=False)
59ae15a5 437 filesystem.add_option('--id',
08b2ac74 438 action='store_true', dest='useid', help='use only video ID in file name', default=False)
59ae15a5
PH
439 filesystem.add_option('-l', '--literal',
440 action='store_true', dest='usetitle', help='[deprecated] alias of --title', default=False)
441 filesystem.add_option('-A', '--auto-number',
442 action='store_true', dest='autonumber',
443 help='number downloaded files starting from 00000', default=False)
444 filesystem.add_option('-o', '--output',
74e3452b
JMF
445 dest='outtmpl', metavar='TEMPLATE',
446 help=('output filename template. Use %(title)s to get the title, '
447 '%(uploader)s for the uploader name, %(uploader_id)s for the uploader nickname if different, '
448 '%(autonumber)s to get an automatically incremented number, '
fdefe96b 449 '%(ext)s for the filename extension, '
67d28bff 450 '%(format)s for the format description (like "22 - 1280x720" or "HD"), '
451 '%(format_id)s for the unique id of the format (like Youtube\'s itags: "137"), '
fdefe96b 452 '%(upload_date)s for the upload date (YYYYMMDD), '
74e3452b 453 '%(extractor)s for the provider (youtube, metacafe, etc), '
67d28bff 454 '%(id)s for the video id, %(playlist)s for the playlist the video is in, '
74e3452b 455 '%(playlist_index)s for the position in the playlist and %% for a literal percent. '
17b75c0d
PH
456 '%(height)s and %(width)s for the width and height of the video format. '
457 '%(resolution)s for a textual description of the resolution of the video format. '
74e3452b
JMF
458 'Use - to output to stdout. Can also be used to download to a different directory, '
459 'for example with -o \'/my/downloads/%(uploader)s/%(title)s-%(id)s.%(ext)s\' .'))
213c31ae
SK
460 filesystem.add_option('--autonumber-size',
461 dest='autonumber_size', metavar='NUMBER',
2a9e9b21 462 help='Specifies the number of digits in %(autonumber)s when it is present in output filename template or --auto-number option is given')
59ae15a5
PH
463 filesystem.add_option('--restrict-filenames',
464 action='store_true', dest='restrictfilenames',
465 help='Restrict filenames to only ASCII characters, and avoid "&" and spaces in filenames', default=False)
466 filesystem.add_option('-a', '--batch-file',
467 dest='batchfile', metavar='FILE', help='file containing URLs to download (\'-\' for stdin)')
1dcc4c0c
JMF
468 filesystem.add_option('--load-info',
469 dest='load_info_filename', metavar='FILE',
67d28bff 470 help='json file containing the video information (created with the "--write-json" option)')
59ae15a5
PH
471 filesystem.add_option('-w', '--no-overwrites',
472 action='store_true', dest='nooverwrites', help='do not overwrite files', default=False)
473 filesystem.add_option('-c', '--continue',
d4b7da84 474 action='store_true', dest='continue_dl', help='force resume of partially downloaded files. By default, youtube-dl will resume downloads if possible.', default=True)
59ae15a5
PH
475 filesystem.add_option('--no-continue',
476 action='store_false', dest='continue_dl',
477 help='do not resume partially downloaded files (restart from beginning)')
478 filesystem.add_option('--cookies',
479 dest='cookiefile', metavar='FILE', help='file to read cookies from and dump cookie jar in')
480 filesystem.add_option('--no-part',
481 action='store_true', dest='nopart', help='do not use .part files', default=False)
482 filesystem.add_option('--no-mtime',
483 action='store_false', dest='updatetime',
484 help='do not use the Last-modified header to set the file modification time', default=True)
485 filesystem.add_option('--write-description',
486 action='store_true', dest='writedescription',
487 help='write video description to a .description file', default=False)
488 filesystem.add_option('--write-info-json',
489 action='store_true', dest='writeinfojson',
490 help='write video metadata to a .info.json file', default=False)
1fb07d10
JG
491 filesystem.add_option('--write-annotations',
492 action='store_true', dest='writeannotations',
493 help='write video annotations to a .annotation file', default=False)
11d9224e
PH
494 filesystem.add_option('--write-thumbnail',
495 action='store_true', dest='writethumbnail',
496 help='write thumbnail image to disk', default=False)
59ae15a5
PH
497
498
499 postproc.add_option('-x', '--extract-audio', action='store_true', dest='extractaudio', default=False,
500 help='convert video files to audio-only files (requires ffmpeg or avconv and ffprobe or avprobe)')
501 postproc.add_option('--audio-format', metavar='FORMAT', dest='audioformat', default='best',
510e6f6d 502 help='"best", "aac", "vorbis", "mp3", "m4a", "opus", or "wav"; best by default')
59ae15a5
PH
503 postproc.add_option('--audio-quality', metavar='QUALITY', dest='audioquality', default='5',
504 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
505 postproc.add_option('--recode-video', metavar='FORMAT', dest='recodevideo', default=None,
506 help='Encode the video to another format if necessary (currently supported: mp4|flv|ogg|webm)')
59ae15a5
PH
507 postproc.add_option('-k', '--keep-video', action='store_true', dest='keepvideo', default=False,
508 help='keeps the video file on disk after the post-processing; the video is erased by default')
f0648fc1
BPG
509 postproc.add_option('--no-post-overwrites', action='store_true', dest='nopostoverwrites', default=False,
510 help='do not overwrite post-processed files; the post-processed files are overwritten by default')
d4051a8e
JMF
511 postproc.add_option('--embed-subs', action='store_true', dest='embedsubtitles', default=False,
512 help='embed subtitles in the video (only for mp4 videos)')
0c14e2fb 513 postproc.add_option('--embed-thumbnail', action='store_true', dest='embedthumbnail', default=False,
514 help='embed thumbnail in the audio as cover art')
bc4f2917 515 postproc.add_option('--add-metadata', action='store_true', dest='addmetadata', default=False,
e63fc1be 516 help='write metadata to the video file')
517 postproc.add_option('--xattrs', action='store_true', dest='xattrs', default=False,
518 help='write metadata to the video file\'s xattrs (using dublin core and xdg standards)')
76b1bd67
JMF
519 postproc.add_option('--prefer-avconv', action='store_false', dest='prefer_ffmpeg',
520 help='Prefer avconv over ffmpeg for running the postprocessors (default)')
521 postproc.add_option('--prefer-ffmpeg', action='store_true', dest='prefer_ffmpeg',
522 help='Prefer ffmpeg over avconv for running the postprocessors')
59ae15a5
PH
523
524
525 parser.add_option_group(general)
526 parser.add_option_group(selection)
0beb3add 527 parser.add_option_group(downloader)
59ae15a5
PH
528 parser.add_option_group(filesystem)
529 parser.add_option_group(verbosity)
530 parser.add_option_group(video_format)
505c28aa 531 parser.add_option_group(subtitles)
59ae15a5
PH
532 parser.add_option_group(authentication)
533 parser.add_option_group(postproc)
534
75b5c590
PH
535 if overrideArguments is not None:
536 opts, args = parser.parse_args(overrideArguments)
537 if opts.verbose:
7459e3a2 538 write_string(u'[debug] Override config: ' + repr(overrideArguments) + '\n')
59ae15a5 539 else:
1865ed31 540 commandLineConf = sys.argv[1:]
588128d0
PH
541 if '--ignore-config' in commandLineConf:
542 systemConf = []
543 userConf = []
544 else:
545 systemConf = _readOptions('/etc/youtube-dl.conf')
546 if '--ignore-config' in systemConf:
547 userConf = []
548 else:
549 userConf = _readUserConf()
75b5c590 550 argv = systemConf + userConf + commandLineConf
588128d0 551
75b5c590 552 opts, args = parser.parse_args(argv)
c76cb6d5 553 if opts.verbose:
7459e3a2
PH
554 write_string(u'[debug] System config: ' + repr(_hide_login_info(systemConf)) + '\n')
555 write_string(u'[debug] User config: ' + repr(_hide_login_info(userConf)) + '\n')
556 write_string(u'[debug] Command-line args: ' + repr(_hide_login_info(commandLineConf)) + '\n')
8c42c506 557
59ae15a5 558 return parser, opts, args
235b3ba4 559
e3946f98 560
b8ad4f02 561def _real_main(argv=None):
0d94f247
PH
562 # Compatibility fixes for Windows
563 if sys.platform == 'win32':
564 # https://github.com/rg3/youtube-dl/issues/820
565 codecs.register(lambda name: codecs.lookup('utf-8') if name == 'cp65001' else None)
566
e3946f98
PH
567 setproctitle(u'youtube-dl')
568
b8ad4f02 569 parser, opts, args = parseOpts(argv)
59ae15a5 570
59ae15a5
PH
571 # Set user agent
572 if opts.user_agent is not None:
573 std_headers['User-Agent'] = opts.user_agent
1865ed31 574
28535652
BH
575 # Set referer
576 if opts.referer is not None:
577 std_headers['Referer'] = opts.referer
59ae15a5 578
410afb20
AA
579 # Custom HTTP headers
580 if opts.headers is not None:
581 for h in opts.headers:
582 if h.find(':', 1) < 0:
583 parser.error(u'wrong header formatting, it should be key:value, not "%s"'%h)
584 key, value = h.split(':', 2)
585 if opts.verbose:
586 write_string(u'[debug] Adding header from command line option %s:%s\n'%(key, value))
587 std_headers[key] = value
588
59ae15a5
PH
589 # Dump user agent
590 if opts.dump_user_agent:
93eb15c5 591 compat_print(std_headers['User-Agent'])
59ae15a5
PH
592 sys.exit(0)
593
594 # Batch file verification
62e609ab 595 batch_urls = []
59ae15a5
PH
596 if opts.batchfile is not None:
597 try:
598 if opts.batchfile == '-':
599 batchfd = sys.stdin
600 else:
62e609ab
PH
601 batchfd = io.open(opts.batchfile, 'r', encoding='utf-8', errors='ignore')
602 batch_urls = read_batch_urls(batchfd)
05afc96b 603 if opts.verbose:
62e609ab 604 write_string(u'[debug] Batch file urls: ' + repr(batch_urls) + u'\n')
59ae15a5
PH
605 except IOError:
606 sys.exit(u'ERROR: batch file could not be read')
62e609ab 607 all_urls = batch_urls + args
59ae15a5 608 all_urls = [url.strip() for url in all_urls]
c774b3c6 609 _enc = preferredencoding()
41292a38 610 all_urls = [url.decode(_enc, 'ignore') if isinstance(url, bytes) else url for url in all_urls]
59ae15a5 611
59ae15a5
PH
612 extractors = gen_extractors()
613
614 if opts.list_extractors:
7dba9cd0 615 for ie in sorted(extractors, key=lambda ie: ie.IE_NAME.lower()):
93eb15c5 616 compat_print(ie.IE_NAME + (' (CURRENTLY BROKEN)' if not ie._WORKING else ''))
1a2c3c0f 617 matchedUrls = [url for url in all_urls if ie.suitable(url)]
59ae15a5 618 for mu in matchedUrls:
93eb15c5 619 compat_print(u' ' + mu)
59ae15a5 620 sys.exit(0)
0f818663
PH
621 if opts.list_extractor_descriptions:
622 for ie in sorted(extractors, key=lambda ie: ie.IE_NAME.lower()):
623 if not ie._WORKING:
624 continue
625 desc = getattr(ie, 'IE_DESC', ie.IE_NAME)
15870e90
PH
626 if desc is False:
627 continue
0f818663
PH
628 if hasattr(ie, 'SEARCH_KEY'):
629 _SEARCHES = (u'cute kittens', u'slithering pythons', u'falling cat', u'angry poodle', u'purple fish', u'running tortoise')
630 _COUNTS = (u'', u'5', u'10', u'all')
631 desc += u' (Example: "%s%s:%s" )' % (ie.SEARCH_KEY, random.choice(_COUNTS), random.choice(_SEARCHES))
632 compat_print(desc)
633 sys.exit(0)
634
59ae15a5
PH
635
636 # Conflicting, missing and erroneous options
637 if opts.usenetrc and (opts.username is not None or opts.password is not None):
638 parser.error(u'using .netrc conflicts with giving username/password')
639 if opts.password is not None and opts.username is None:
67d28bff 640 parser.error(u'account username missing\n')
59ae15a5
PH
641 if opts.outtmpl is not None and (opts.usetitle or opts.autonumber or opts.useid):
642 parser.error(u'using output template conflicts with using title, video ID or auto number')
643 if opts.usetitle and opts.useid:
644 parser.error(u'using title conflicts with using video ID')
645 if opts.username is not None and opts.password is None:
e68301af 646 opts.password = compat_getpass(u'Type account password and press [Return]: ')
59ae15a5
PH
647 if opts.ratelimit is not None:
648 numeric_limit = FileDownloader.parse_bytes(opts.ratelimit)
649 if numeric_limit is None:
650 parser.error(u'invalid rate limit specified')
651 opts.ratelimit = numeric_limit
9e982f9e
JC
652 if opts.min_filesize is not None:
653 numeric_limit = FileDownloader.parse_bytes(opts.min_filesize)
654 if numeric_limit is None:
655 parser.error(u'invalid min_filesize specified')
656 opts.min_filesize = numeric_limit
657 if opts.max_filesize is not None:
658 numeric_limit = FileDownloader.parse_bytes(opts.max_filesize)
659 if numeric_limit is None:
660 parser.error(u'invalid max_filesize specified')
661 opts.max_filesize = numeric_limit
59ae15a5
PH
662 if opts.retries is not None:
663 try:
664 opts.retries = int(opts.retries)
dca08720 665 except (TypeError, ValueError):
59ae15a5
PH
666 parser.error(u'invalid retry count specified')
667 if opts.buffersize is not None:
668 numeric_buffersize = FileDownloader.parse_bytes(opts.buffersize)
669 if numeric_buffersize is None:
670 parser.error(u'invalid buffer size specified')
671 opts.buffersize = numeric_buffersize
a19fd00c
PH
672 if opts.playliststart <= 0:
673 raise ValueError(u'Playlist start must be positive')
674 if opts.playlistend not in (-1, None) and opts.playlistend < opts.playliststart:
675 raise ValueError(u'Playlist end must be greater than playlist start')
59ae15a5 676 if opts.extractaudio:
510e6f6d 677 if opts.audioformat not in ['best', 'aac', 'mp3', 'm4a', 'opus', 'vorbis', 'wav']:
59ae15a5
PH
678 parser.error(u'invalid audio format specified')
679 if opts.audioquality:
680 opts.audioquality = opts.audioquality.strip('k').strip('K')
681 if not opts.audioquality.isdigit():
682 parser.error(u'invalid audio quality specified')
7851b379 683 if opts.recodevideo is not None:
b7d73595 684 if opts.recodevideo not in ['mp4', 'flv', 'webm', 'ogg', 'mkv']:
7851b379 685 parser.error(u'invalid video recode format specified')
bd558525
JMF
686 if opts.date is not None:
687 date = DateRange.day(opts.date)
688 else:
689 date = DateRange(opts.dateafter, opts.datebefore)
9c1fc022 690 if opts.default_search not in ('auto', 'auto_warning', None) and ':' not in opts.default_search:
04b4d394 691 parser.error(u'--default-search invalid; did you forget a colon (:) at the end?')
59ae15a5 692
de3ef3ed
PH
693 # Do not download videos when there are audio-only formats
694 if opts.extractaudio and not opts.keepvideo and opts.format is None:
695 opts.format = 'bestaudio/best'
696
0b7f3118
JMF
697 # --all-sub automatically sets --write-sub if --write-auto-sub is not given
698 # this was the old behaviour if only --all-sub was given.
699 if opts.allsubtitles and (opts.writeautomaticsub == False):
700 opts.writesubtitles = True
701
5cb9c312
PH
702 if sys.version_info < (3,):
703 # In Python 2, sys.argv is a bytestring (also note http://bugs.python.org/issue2128 for Windows systems)
0be41ec2
PH
704 if opts.outtmpl is not None:
705 opts.outtmpl = opts.outtmpl.decode(preferredencoding())
5cb9c312
PH
706 outtmpl =((opts.outtmpl is not None and opts.outtmpl)
707 or (opts.format == '-1' and opts.usetitle and u'%(title)s-%(id)s-%(format)s.%(ext)s')
708 or (opts.format == '-1' and u'%(id)s-%(format)s.%(ext)s')
709 or (opts.usetitle and opts.autonumber and u'%(autonumber)s-%(title)s-%(id)s.%(ext)s')
710 or (opts.usetitle and u'%(title)s-%(id)s.%(ext)s')
711 or (opts.useid and u'%(id)s.%(ext)s')
712 or (opts.autonumber and u'%(autonumber)s-%(id)s.%(ext)s')
acd69589 713 or DEFAULT_OUTTMPL)
dca02c80 714 if not os.path.splitext(outtmpl)[1] and opts.extractaudio:
b61067fa 715 parser.error(u'Cannot download a video and extract audio into the same'
dca02c80
JMF
716 u' file! Use "{0}.%(ext)s" instead of "{0}" as the output'
717 u' template'.format(outtmpl))
29c7a63d 718
525ef922 719 any_printing = opts.geturl or opts.gettitle or opts.getid or opts.getthumbnail or opts.getdescription or opts.getfilename or opts.getformat or opts.getduration or opts.dumpjson
17093b83 720 download_archive_fn = os.path.expanduser(opts.download_archive) if opts.download_archive is not None else opts.download_archive
525ef922 721
bdde425c 722 ydl_opts = {
59ae15a5
PH
723 'usenetrc': opts.usenetrc,
724 'username': opts.username,
725 'password': opts.password,
c6c19746 726 'videopassword': opts.videopassword,
525ef922 727 'quiet': (opts.quiet or any_printing),
ad8915b7 728 'no_warnings': opts.no_warnings,
59ae15a5
PH
729 'forceurl': opts.geturl,
730 'forcetitle': opts.gettitle,
1a2adf3f 731 'forceid': opts.getid,
59ae15a5
PH
732 'forcethumbnail': opts.getthumbnail,
733 'forcedescription': opts.getdescription,
525ef922 734 'forceduration': opts.getduration,
59ae15a5
PH
735 'forcefilename': opts.getfilename,
736 'forceformat': opts.getformat,
9d153818 737 'forcejson': opts.dumpjson,
59ae15a5 738 'simulate': opts.simulate,
525ef922 739 'skip_download': (opts.skip_download or opts.simulate or any_printing),
59ae15a5
PH
740 'format': opts.format,
741 'format_limit': opts.format_limit,
742 'listformats': opts.listformats,
5cb9c312 743 'outtmpl': outtmpl,
213c31ae 744 'autonumber_size': opts.autonumber_size,
59ae15a5
PH
745 'restrictfilenames': opts.restrictfilenames,
746 'ignoreerrors': opts.ignoreerrors,
747 'ratelimit': opts.ratelimit,
748 'nooverwrites': opts.nooverwrites,
749 'retries': opts.retries,
750 'buffersize': opts.buffersize,
751 'noresizebuffer': opts.noresizebuffer,
752 'continuedl': opts.continue_dl,
753 'noprogress': opts.noprogress,
5717d91a 754 'progress_with_newline': opts.progress_with_newline,
59ae15a5
PH
755 'playliststart': opts.playliststart,
756 'playlistend': opts.playlistend,
47192f92 757 'noplaylist': opts.noplaylist,
59ae15a5
PH
758 'logtostderr': opts.outtmpl == '-',
759 'consoletitle': opts.consoletitle,
760 'nopart': opts.nopart,
761 'updatetime': opts.updatetime,
762 'writedescription': opts.writedescription,
1fb07d10 763 'writeannotations': opts.writeannotations,
59ae15a5 764 'writeinfojson': opts.writeinfojson,
11d9224e 765 'writethumbnail': opts.writethumbnail,
59ae15a5 766 'writesubtitles': opts.writesubtitles,
b004821f 767 'writeautomaticsub': opts.writeautomaticsub,
ae608b80 768 'allsubtitles': opts.allsubtitles,
2a4093ea 769 'listsubtitles': opts.listsubtitles,
9e62bc44 770 'subtitlesformat': opts.subtitlesformat,
d6e203b3 771 'subtitleslangs': opts.subtitleslangs,
8271226a
PH
772 'matchtitle': decodeOption(opts.matchtitle),
773 'rejecttitle': decodeOption(opts.rejecttitle),
59ae15a5
PH
774 'max_downloads': opts.max_downloads,
775 'prefer_free_formats': opts.prefer_free_formats,
776 'verbose': opts.verbose,
855703e5 777 'dump_intermediate_pages': opts.dump_intermediate_pages,
d41e6efc 778 'write_pages': opts.write_pages,
8d5d3a5d 779 'test': opts.test,
7851b379 780 'keepvideo': opts.keepvideo,
9e982f9e 781 'min_filesize': opts.min_filesize,
bd558525 782 'max_filesize': opts.max_filesize,
5fe18bdb
PH
783 'min_views': opts.min_views,
784 'max_views': opts.max_views,
11d9224e 785 'daterange': date,
7f747732 786 'cachedir': opts.cachedir,
f8061589 787 'youtube_print_sig_code': opts.youtube_print_sig_code,
8dbe9899 788 'age_limit': opts.age_limit,
17093b83 789 'download_archive': download_archive_fn,
dca08720
PH
790 'cookiefile': opts.cookiefile,
791 'nocheckcertificate': opts.no_check_certificate,
7e8c0af0 792 'prefer_insecure': opts.prefer_insecure,
c2e52508 793 'proxy': opts.proxy,
6ad14cab 794 'socket_timeout': opts.socket_timeout,
0783b09b 795 'bidi_workaround': opts.bidi_workaround,
a0ddb8a2 796 'debug_printtraffic': opts.debug_printtraffic,
76b1bd67 797 'prefer_ffmpeg': opts.prefer_ffmpeg,
7b0817e8 798 'include_ads': opts.include_ads,
04b4d394 799 'default_search': opts.default_search,
4919603f 800 'youtube_include_dash_manifest': opts.youtube_include_dash_manifest,
62fec3b2 801 'encoding': opts.encoding,
bdde425c 802 }
59ae15a5 803
bdde425c 804 with YoutubeDL(ydl_opts) as ydl:
dca08720 805 ydl.print_debug_header()
bdde425c
PH
806 ydl.add_default_info_extractors()
807
808 # PostProcessors
809 # Add the metadata pp first, the other pps will copy it
810 if opts.addmetadata:
811 ydl.add_post_processor(FFmpegMetadataPP())
812 if opts.extractaudio:
813 ydl.add_post_processor(FFmpegExtractAudioPP(preferredcodec=opts.audioformat, preferredquality=opts.audioquality, nopostoverwrites=opts.nopostoverwrites))
814 if opts.recodevideo:
815 ydl.add_post_processor(FFmpegVideoConvertor(preferedformat=opts.recodevideo))
816 if opts.embedsubtitles:
817 ydl.add_post_processor(FFmpegEmbedSubtitlePP(subtitlesformat=opts.subtitlesformat))
e63fc1be 818 if opts.xattrs:
819 ydl.add_post_processor(XAttrMetadataPP())
0c14e2fb 820 if opts.embedthumbnail:
784763c5 821 if not opts.addmetadata:
822 ydl.add_post_processor(FFmpegAudioFixPP())
0c14e2fb 823 ydl.add_post_processor(AtomicParsleyPP())
bdde425c
PH
824
825 # Update version
826 if opts.update_self:
827 update_self(ydl.to_screen, opts.verbose)
828
829 # Maybe do nothing
1dcc4c0c 830 if (len(all_urls) < 1) and (opts.load_info_filename is None):
bdde425c
PH
831 if not opts.update_self:
832 parser.error(u'you must provide at least one URL')
833 else:
834 sys.exit()
59ae15a5 835
bdde425c 836 try:
1dcc4c0c
JMF
837 if opts.load_info_filename is not None:
838 retcode = ydl.download_with_info_file(opts.load_info_filename)
839 else:
840 retcode = ydl.download(all_urls)
bdde425c
PH
841 except MaxDownloadsReached:
842 ydl.to_screen(u'--max-download limit reached, aborting.')
843 retcode = 101
59ae15a5 844
59ae15a5 845 sys.exit(retcode)
235b3ba4 846
a27b9e8b 847
b8ad4f02 848def main(argv=None):
59ae15a5 849 try:
b8ad4f02 850 _real_main(argv)
59ae15a5
PH
851 except DownloadError:
852 sys.exit(1)
853 except SameFileError:
854 sys.exit(u'ERROR: fixed output name but more than one file to download')
855 except KeyboardInterrupt:
856 sys.exit(u'\nERROR: Interrupted by user')