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