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