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