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