Add --no-warnings option (Fixes #2630)
[youtube-dl] / youtube_dl / __init__.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 __authors__  = (
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',
20     'Dave Vasilevsky',
21     'Jaime Marquínez Ferrándiz',
22     'Jeff Crouse',
23     'Osama Khalid',
24     'Michael Walter',
25     'M. Yasoob Ullah Khalid',
26     'Julien Fraichard',
27     'Johny Mo Swag',
28     'Axel Noack',
29     'Albert Kim',
30     'Pierre Rudloff',
31     'Huarong Huo',
32     'Ismael Mejía',
33     'Steffan \'Ruirize\' James',
34     'Andras Elso',
35     'Jelle van der Waa',
36     'Marcin Cieślak',
37     'Anton Larionov',
38     'Takuya Tsuchida',
39     'Sergey M.',
40     'Michael Orlitzky',
41     'Chris Gahan',
42     'Saimadhav Heblikar',
43     'Mike Col',
44     'Oleg Prutz',
45     'pulpe',
46     'Andreas Schmitz',
47     'Michael Kaiser',
48     'Niklas Laxström',
49     'David Triendl',
50     'Anthony Weems',
51     'David Wagner',
52     'Juan C. Olivares',
53     'Mattias Harrysson',
54 )
55
56 __license__ = 'Public Domain'
57
58 import codecs
59 import io
60 import locale
61 import optparse
62 import os
63 import random
64 import re
65 import shlex
66 import sys
67
68
69 from .utils import (
70     compat_getpass,
71     compat_print,
72     DateRange,
73     decodeOption,
74     get_term_width,
75     DownloadError,
76     get_cachedir,
77     MaxDownloadsReached,
78     preferredencoding,
79     read_batch_urls,
80     SameFileError,
81     setproctitle,
82     std_headers,
83     write_string,
84 )
85 from .update import update_self
86 from .FileDownloader import (
87     FileDownloader,
88 )
89 from .extractor import gen_extractors
90 from .version import __version__
91 from .YoutubeDL import YoutubeDL
92 from .postprocessor import (
93     FFmpegMetadataPP,
94     FFmpegVideoConvertor,
95     FFmpegExtractAudioPP,
96     FFmpegEmbedSubtitlePP,
97     XAttrMetadataPP,
98 )
99
100
101 def parseOpts(overrideArguments=None):
102     def _readOptions(filename_bytes, default=[]):
103         try:
104             optionf = open(filename_bytes)
105         except IOError:
106             return default  # silently skip if file is not present
107         try:
108             res = []
109             for l in optionf:
110                 res += shlex.split(l, comments=True)
111         finally:
112             optionf.close()
113         return res
114
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
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
168     def _comma_separated_values_options_callback(option, opt_str, value, parser):
169         setattr(parser.values, option.dest, value.split(','))
170
171     def _hide_login_info(opts):
172         opts = list(opts)
173         for private_opt in ['-p', '--password', '-u', '--username', '--video-password']:
174             try:
175                 i = opts.index(private_opt)
176                 opts[i+1] = '<PRIVATE>'
177             except ValueError:
178                 pass
179         return opts
180
181     max_width = 80
182     max_help_position = 80
183
184     # No need to wrap help messages if we're on a wide console
185     columns = get_term_width()
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')
205     subtitles      = optparse.OptionGroup(parser, 'Subtitle Options')
206     downloader     = optparse.OptionGroup(parser, 'Download Options')
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',
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)')
217     general.add_option('-i', '--ignore-errors',
218             action='store_true', dest='ignoreerrors', help='continue on download errors, for example to skip unavailable videos in a playlist', default=False)
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')
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')
227     general.add_option('--referer',
228             dest='referer', help='specify a custom referer, use if the video access is restricted to one domain',
229             metavar='REF', default=None)
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')
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)
236     general.add_option('--extractor-descriptions',
237             action='store_true', dest='list_extractor_descriptions',
238             help='Output descriptions of all supported extractors', default=False)
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')
242     general.add_option('--no-check-certificate', action='store_true', dest='no_check_certificate', default=False, help='Suppress HTTPS certificate validation.')
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)')
246     general.add_option(
247         '--cache-dir', dest='cachedir', default=get_cachedir(), metavar='DIR',
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.')
249     general.add_option(
250         '--no-cache-dir', action='store_const', const=None, dest='cachedir',
251         help='Disable filesystem caching')
252     general.add_option(
253         '--socket-timeout', dest='socket_timeout',
254         type=float, default=None, help=u'Time to wait before giving up, in seconds')
255     general.add_option(
256         '--bidi-workaround', dest='bidi_workaround', action='store_true',
257         help=u'Work around terminals that lack bidirectional text support. Requires bidiv or fribidi executable in PATH')
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.')
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
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)')
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)')
276     selection.add_option('--max-downloads', metavar='NUMBER',
277                          dest='max_downloads', type=int, default=None,
278                          help='Abort after downloading NUMBER files')
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)
281     selection.add_option('--date', metavar='DATE', dest='date', help='download only videos uploaded in this date', default=None)
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)')
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",)
296     selection.add_option('--no-playlist', action='store_true', dest='noplaylist', help='download only the currently playing video', default=False)
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)
300     selection.add_option('--download-archive', metavar='FILE',
301                          dest='download_archive',
302                          help='Download only videos not listed in the archive file. Record the IDs of all downloaded videos in it.')
303     selection.add_option(
304         '--include-ads', dest='include_ads',
305         action='store_true',
306         help='Download advertisements as well (experimental)')
307     selection.add_option(
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)')
311
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)
318     authentication.add_option('--video-password',
319             dest='videopassword', metavar='PASSWORD', help='video password (vimeo, smotri)')
320
321
322     video_format.add_option('-f', '--format',
323             action='store', dest='format', metavar='FORMAT', default=None,
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.')
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',
332             action='store_true', dest='listformats', help='list all available formats')
333
334     subtitles.add_option('--write-sub', '--write-srt',
335             action='store_true', dest='writesubtitles',
336             help='write subtitle file', default=False)
337     subtitles.add_option('--write-auto-sub', '--write-automatic-sub',
338             action='store_true', dest='writeautomaticsub',
339             help='write automatic subtitle file (youtube only)', default=False)
340     subtitles.add_option('--all-subs',
341             action='store_true', dest='allsubtitles',
342             help='downloads all the available subtitles of the video', default=False)
343     subtitles.add_option('--list-subs',
344             action='store_true', dest='listsubtitles',
345             help='lists all available subtitles for the video', default=False)
346     subtitles.add_option('--sub-format',
347             action='store', dest='subtitlesformat', metavar='FORMAT',
348             help='subtitle format (default=srt) ([sbv/vtt] youtube only)', default='srt')
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\'')
353
354     downloader.add_option('-r', '--rate-limit',
355             dest='ratelimit', metavar='LIMIT', help='maximum download rate in bytes per second (e.g. 50K or 4.2M)')
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',
359             dest='buffersize', metavar='SIZE', help='size of download buffer (e.g. 1024 or 16K) (default is %default)', default="1024")
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
365     verbosity.add_option('-q', '--quiet',
366             action='store_true', dest='quiet', help='activates quiet mode', default=False)
367     verbosity.add_option(
368         '--no-warnings',
369         dest='no_warnings', action='store_true', default=False,
370         help='Ignore warnings')
371     verbosity.add_option('-s', '--simulate',
372             action='store_true', dest='simulate', help='do not download the video and do not write anything to disk', default=False)
373     verbosity.add_option('--skip-download',
374             action='store_true', dest='skip_download', help='do not download the video', default=False)
375     verbosity.add_option('-g', '--get-url',
376             action='store_true', dest='geturl', help='simulate, quiet but print URL', default=False)
377     verbosity.add_option('-e', '--get-title',
378             action='store_true', dest='gettitle', help='simulate, quiet but print title', default=False)
379     verbosity.add_option('--get-id',
380             action='store_true', dest='getid', help='simulate, quiet but print id', default=False)
381     verbosity.add_option('--get-thumbnail',
382             action='store_true', dest='getthumbnail',
383             help='simulate, quiet but print thumbnail URL', default=False)
384     verbosity.add_option('--get-description',
385             action='store_true', dest='getdescription',
386             help='simulate, quiet but print video description', default=False)
387     verbosity.add_option('--get-duration',
388             action='store_true', dest='getduration',
389             help='simulate, quiet but print video length', default=False)
390     verbosity.add_option('--get-filename',
391             action='store_true', dest='getfilename',
392             help='simulate, quiet but print output filename', default=False)
393     verbosity.add_option('--get-format',
394             action='store_true', dest='getformat',
395             help='simulate, quiet but print output format', default=False)
396     verbosity.add_option('-j', '--dump-json',
397             action='store_true', dest='dumpjson',
398             help='simulate, quiet but print JSON information', default=False)
399     verbosity.add_option('--newline',
400             action='store_true', dest='progress_with_newline', help='output progress bar as new lines', default=False)
401     verbosity.add_option('--no-progress',
402             action='store_true', dest='noprogress', help='do not print progress bar', default=False)
403     verbosity.add_option('--console-title',
404             action='store_true', dest='consoletitle',
405             help='display progress in console titlebar', default=False)
406     verbosity.add_option('-v', '--verbose',
407             action='store_true', dest='verbose', help='print various debugging information', default=False)
408     verbosity.add_option('--dump-intermediate-pages',
409             action='store_true', dest='dump_intermediate_pages', default=False,
410             help='print downloaded pages to debug problems (very verbose)')
411     verbosity.add_option('--write-pages',
412             action='store_true', dest='write_pages', default=False,
413             help='Write downloaded intermediary pages to files in the current directory to debug problems')
414     verbosity.add_option('--youtube-print-sig-code',
415             action='store_true', dest='youtube_print_sig_code', default=False,
416             help=optparse.SUPPRESS_HELP)
417     verbosity.add_option('--print-traffic',
418             dest='debug_printtraffic', action='store_true', default=False,
419             help='Display sent and read HTTP traffic')
420
421
422     filesystem.add_option('-t', '--title',
423             action='store_true', dest='usetitle', help='use title in file name (default)', default=False)
424     filesystem.add_option('--id',
425             action='store_true', dest='useid', help='use only video ID in file name', default=False)
426     filesystem.add_option('-l', '--literal',
427             action='store_true', dest='usetitle', help='[deprecated] alias of --title', default=False)
428     filesystem.add_option('-A', '--auto-number',
429             action='store_true', dest='autonumber',
430             help='number downloaded files starting from 00000', default=False)
431     filesystem.add_option('-o', '--output',
432             dest='outtmpl', metavar='TEMPLATE',
433             help=('output filename template. Use %(title)s to get the title, '
434                   '%(uploader)s for the uploader name, %(uploader_id)s for the uploader nickname if different, '
435                   '%(autonumber)s to get an automatically incremented number, '
436                   '%(ext)s for the filename extension, '
437                   '%(format)s for the format description (like "22 - 1280x720" or "HD"), '
438                   '%(format_id)s for the unique id of the format (like Youtube\'s itags: "137"), '
439                   '%(upload_date)s for the upload date (YYYYMMDD), '
440                   '%(extractor)s for the provider (youtube, metacafe, etc), '
441                   '%(id)s for the video id, %(playlist)s for the playlist the video is in, '
442                   '%(playlist_index)s for the position in the playlist and %% for a literal percent. '
443                   '%(height)s and %(width)s for the width and height of the video format. '
444                   '%(resolution)s for a textual description of the resolution of the video format. '
445                   'Use - to output to stdout. Can also be used to download to a different directory, '
446                   'for example with -o \'/my/downloads/%(uploader)s/%(title)s-%(id)s.%(ext)s\' .'))
447     filesystem.add_option('--autonumber-size',
448             dest='autonumber_size', metavar='NUMBER',
449             help='Specifies the number of digits in %(autonumber)s when it is present in output filename template or --auto-number option is given')
450     filesystem.add_option('--restrict-filenames',
451             action='store_true', dest='restrictfilenames',
452             help='Restrict filenames to only ASCII characters, and avoid "&" and spaces in filenames', default=False)
453     filesystem.add_option('-a', '--batch-file',
454             dest='batchfile', metavar='FILE', help='file containing URLs to download (\'-\' for stdin)')
455     filesystem.add_option('--load-info',
456             dest='load_info_filename', metavar='FILE',
457             help='json file containing the video information (created with the "--write-json" option)')
458     filesystem.add_option('-w', '--no-overwrites',
459             action='store_true', dest='nooverwrites', help='do not overwrite files', default=False)
460     filesystem.add_option('-c', '--continue',
461             action='store_true', dest='continue_dl', help='force resume of partially downloaded files. By default, youtube-dl will resume downloads if possible.', default=True)
462     filesystem.add_option('--no-continue',
463             action='store_false', dest='continue_dl',
464             help='do not resume partially downloaded files (restart from beginning)')
465     filesystem.add_option('--cookies',
466             dest='cookiefile', metavar='FILE', help='file to read cookies from and dump cookie jar in')
467     filesystem.add_option('--no-part',
468             action='store_true', dest='nopart', help='do not use .part files', default=False)
469     filesystem.add_option('--no-mtime',
470             action='store_false', dest='updatetime',
471             help='do not use the Last-modified header to set the file modification time', default=True)
472     filesystem.add_option('--write-description',
473             action='store_true', dest='writedescription',
474             help='write video description to a .description file', default=False)
475     filesystem.add_option('--write-info-json',
476             action='store_true', dest='writeinfojson',
477             help='write video metadata to a .info.json file', default=False)
478     filesystem.add_option('--write-annotations',
479             action='store_true', dest='writeannotations',
480             help='write video annotations to a .annotation file', default=False)
481     filesystem.add_option('--write-thumbnail',
482             action='store_true', dest='writethumbnail',
483             help='write thumbnail image to disk', default=False)
484
485
486     postproc.add_option('-x', '--extract-audio', action='store_true', dest='extractaudio', default=False,
487             help='convert video files to audio-only files (requires ffmpeg or avconv and ffprobe or avprobe)')
488     postproc.add_option('--audio-format', metavar='FORMAT', dest='audioformat', default='best',
489             help='"best", "aac", "vorbis", "mp3", "m4a", "opus", or "wav"; best by default')
490     postproc.add_option('--audio-quality', metavar='QUALITY', dest='audioquality', default='5',
491             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)')
492     postproc.add_option('--recode-video', metavar='FORMAT', dest='recodevideo', default=None,
493             help='Encode the video to another format if necessary (currently supported: mp4|flv|ogg|webm)')
494     postproc.add_option('-k', '--keep-video', action='store_true', dest='keepvideo', default=False,
495             help='keeps the video file on disk after the post-processing; the video is erased by default')
496     postproc.add_option('--no-post-overwrites', action='store_true', dest='nopostoverwrites', default=False,
497             help='do not overwrite post-processed files; the post-processed files are overwritten by default')
498     postproc.add_option('--embed-subs', action='store_true', dest='embedsubtitles', default=False,
499             help='embed subtitles in the video (only for mp4 videos)')
500     postproc.add_option('--add-metadata', action='store_true', dest='addmetadata', default=False,
501             help='write metadata to the video file')
502     postproc.add_option('--xattrs', action='store_true', dest='xattrs', default=False,
503             help='write metadata to the video file\'s xattrs (using dublin core and xdg standards)')
504     postproc.add_option('--prefer-avconv', action='store_false', dest='prefer_ffmpeg',
505         help='Prefer avconv over ffmpeg for running the postprocessors (default)')
506     postproc.add_option('--prefer-ffmpeg', action='store_true', dest='prefer_ffmpeg',
507         help='Prefer ffmpeg over avconv for running the postprocessors')
508
509
510     parser.add_option_group(general)
511     parser.add_option_group(selection)
512     parser.add_option_group(downloader)
513     parser.add_option_group(filesystem)
514     parser.add_option_group(verbosity)
515     parser.add_option_group(video_format)
516     parser.add_option_group(subtitles)
517     parser.add_option_group(authentication)
518     parser.add_option_group(postproc)
519
520     if overrideArguments is not None:
521         opts, args = parser.parse_args(overrideArguments)
522         if opts.verbose:
523             write_string(u'[debug] Override config: ' + repr(overrideArguments) + '\n')
524     else:
525         commandLineConf = sys.argv[1:]
526         if '--ignore-config' in commandLineConf:
527             systemConf = []
528             userConf = []
529         else:
530             systemConf = _readOptions('/etc/youtube-dl.conf')
531             if '--ignore-config' in systemConf:
532                 userConf = []
533             else:
534                 userConf = _readUserConf()
535         argv = systemConf + userConf + commandLineConf
536
537         opts, args = parser.parse_args(argv)
538         if opts.verbose:
539             write_string(u'[debug] System config: ' + repr(_hide_login_info(systemConf)) + '\n')
540             write_string(u'[debug] User config: ' + repr(_hide_login_info(userConf)) + '\n')
541             write_string(u'[debug] Command-line args: ' + repr(_hide_login_info(commandLineConf)) + '\n')
542             write_string(u'[debug] Encodings: locale %r, fs %r, out %r, pref: %r\n' %
543                          (locale.getpreferredencoding(), sys.getfilesystemencoding(), sys.stdout.encoding, preferredencoding()))
544
545     return parser, opts, args
546
547
548 def _real_main(argv=None):
549     # Compatibility fixes for Windows
550     if sys.platform == 'win32':
551         # https://github.com/rg3/youtube-dl/issues/820
552         codecs.register(lambda name: codecs.lookup('utf-8') if name == 'cp65001' else None)
553
554     setproctitle(u'youtube-dl')
555
556     parser, opts, args = parseOpts(argv)
557
558     # Set user agent
559     if opts.user_agent is not None:
560         std_headers['User-Agent'] = opts.user_agent
561
562     # Set referer
563     if opts.referer is not None:
564         std_headers['Referer'] = opts.referer
565
566     # Custom HTTP headers
567     if opts.headers is not None:
568         for h in opts.headers:
569             if h.find(':', 1) < 0:
570                 parser.error(u'wrong header formatting, it should be key:value, not "%s"'%h)
571             key, value = h.split(':', 2)
572             if opts.verbose:
573                 write_string(u'[debug] Adding header from command line option %s:%s\n'%(key, value))
574             std_headers[key] = value
575
576     # Dump user agent
577     if opts.dump_user_agent:
578         compat_print(std_headers['User-Agent'])
579         sys.exit(0)
580
581     # Batch file verification
582     batch_urls = []
583     if opts.batchfile is not None:
584         try:
585             if opts.batchfile == '-':
586                 batchfd = sys.stdin
587             else:
588                 batchfd = io.open(opts.batchfile, 'r', encoding='utf-8', errors='ignore')
589             batch_urls = read_batch_urls(batchfd)
590             if opts.verbose:
591                 write_string(u'[debug] Batch file urls: ' + repr(batch_urls) + u'\n')
592         except IOError:
593             sys.exit(u'ERROR: batch file could not be read')
594     all_urls = batch_urls + args
595     all_urls = [url.strip() for url in all_urls]
596     _enc = preferredencoding()
597     all_urls = [url.decode(_enc, 'ignore') if isinstance(url, bytes) else url for url in all_urls]
598
599     extractors = gen_extractors()
600
601     if opts.list_extractors:
602         for ie in sorted(extractors, key=lambda ie: ie.IE_NAME.lower()):
603             compat_print(ie.IE_NAME + (' (CURRENTLY BROKEN)' if not ie._WORKING else ''))
604             matchedUrls = [url for url in all_urls if ie.suitable(url)]
605             for mu in matchedUrls:
606                 compat_print(u'  ' + mu)
607         sys.exit(0)
608     if opts.list_extractor_descriptions:
609         for ie in sorted(extractors, key=lambda ie: ie.IE_NAME.lower()):
610             if not ie._WORKING:
611                 continue
612             desc = getattr(ie, 'IE_DESC', ie.IE_NAME)
613             if desc is False:
614                 continue
615             if hasattr(ie, 'SEARCH_KEY'):
616                 _SEARCHES = (u'cute kittens', u'slithering pythons', u'falling cat', u'angry poodle', u'purple fish', u'running tortoise')
617                 _COUNTS = (u'', u'5', u'10', u'all')
618                 desc += u' (Example: "%s%s:%s" )' % (ie.SEARCH_KEY, random.choice(_COUNTS), random.choice(_SEARCHES))
619             compat_print(desc)
620         sys.exit(0)
621
622
623     # Conflicting, missing and erroneous options
624     if opts.usenetrc and (opts.username is not None or opts.password is not None):
625         parser.error(u'using .netrc conflicts with giving username/password')
626     if opts.password is not None and opts.username is None:
627         parser.error(u'account username missing\n')
628     if opts.outtmpl is not None and (opts.usetitle or opts.autonumber or opts.useid):
629         parser.error(u'using output template conflicts with using title, video ID or auto number')
630     if opts.usetitle and opts.useid:
631         parser.error(u'using title conflicts with using video ID')
632     if opts.username is not None and opts.password is None:
633         opts.password = compat_getpass(u'Type account password and press [Return]: ')
634     if opts.ratelimit is not None:
635         numeric_limit = FileDownloader.parse_bytes(opts.ratelimit)
636         if numeric_limit is None:
637             parser.error(u'invalid rate limit specified')
638         opts.ratelimit = numeric_limit
639     if opts.min_filesize is not None:
640         numeric_limit = FileDownloader.parse_bytes(opts.min_filesize)
641         if numeric_limit is None:
642             parser.error(u'invalid min_filesize specified')
643         opts.min_filesize = numeric_limit
644     if opts.max_filesize is not None:
645         numeric_limit = FileDownloader.parse_bytes(opts.max_filesize)
646         if numeric_limit is None:
647             parser.error(u'invalid max_filesize specified')
648         opts.max_filesize = numeric_limit
649     if opts.retries is not None:
650         try:
651             opts.retries = int(opts.retries)
652         except (TypeError, ValueError):
653             parser.error(u'invalid retry count specified')
654     if opts.buffersize is not None:
655         numeric_buffersize = FileDownloader.parse_bytes(opts.buffersize)
656         if numeric_buffersize is None:
657             parser.error(u'invalid buffer size specified')
658         opts.buffersize = numeric_buffersize
659     if opts.playliststart <= 0:
660         raise ValueError(u'Playlist start must be positive')
661     if opts.playlistend not in (-1, None) and opts.playlistend < opts.playliststart:
662         raise ValueError(u'Playlist end must be greater than playlist start')
663     if opts.extractaudio:
664         if opts.audioformat not in ['best', 'aac', 'mp3', 'm4a', 'opus', 'vorbis', 'wav']:
665             parser.error(u'invalid audio format specified')
666     if opts.audioquality:
667         opts.audioquality = opts.audioquality.strip('k').strip('K')
668         if not opts.audioquality.isdigit():
669             parser.error(u'invalid audio quality specified')
670     if opts.recodevideo is not None:
671         if opts.recodevideo not in ['mp4', 'flv', 'webm', 'ogg']:
672             parser.error(u'invalid video recode format specified')
673     if opts.date is not None:
674         date = DateRange.day(opts.date)
675     else:
676         date = DateRange(opts.dateafter, opts.datebefore)
677     if opts.default_search not in ('auto', None) and ':' not in opts.default_search:
678         parser.error(u'--default-search invalid; did you forget a colon (:) at the end?')
679
680     # Do not download videos when there are audio-only formats
681     if opts.extractaudio and not opts.keepvideo and opts.format is None:
682         opts.format = 'bestaudio/best'
683
684     # --all-sub automatically sets --write-sub if --write-auto-sub is not given
685     # this was the old behaviour if only --all-sub was given.
686     if opts.allsubtitles and (opts.writeautomaticsub == False):
687         opts.writesubtitles = True
688
689     if sys.version_info < (3,):
690         # In Python 2, sys.argv is a bytestring (also note http://bugs.python.org/issue2128 for Windows systems)
691         if opts.outtmpl is not None:
692             opts.outtmpl = opts.outtmpl.decode(preferredencoding())
693     outtmpl =((opts.outtmpl is not None and opts.outtmpl)
694             or (opts.format == '-1' and opts.usetitle and u'%(title)s-%(id)s-%(format)s.%(ext)s')
695             or (opts.format == '-1' and u'%(id)s-%(format)s.%(ext)s')
696             or (opts.usetitle and opts.autonumber and u'%(autonumber)s-%(title)s-%(id)s.%(ext)s')
697             or (opts.usetitle and u'%(title)s-%(id)s.%(ext)s')
698             or (opts.useid and u'%(id)s.%(ext)s')
699             or (opts.autonumber and u'%(autonumber)s-%(id)s.%(ext)s')
700             or u'%(title)s-%(id)s.%(ext)s')
701     if not os.path.splitext(outtmpl)[1] and opts.extractaudio:
702         parser.error(u'Cannot download a video and extract audio into the same'
703                      u' file! Use "{0}.%(ext)s" instead of "{0}" as the output'
704                      u' template'.format(outtmpl))
705
706     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
707     download_archive_fn = os.path.expanduser(opts.download_archive) if opts.download_archive is not None else opts.download_archive
708
709     ydl_opts = {
710         'usenetrc': opts.usenetrc,
711         'username': opts.username,
712         'password': opts.password,
713         'videopassword': opts.videopassword,
714         'quiet': (opts.quiet or any_printing),
715         'no_warnings': opts.no_warnings,
716         'forceurl': opts.geturl,
717         'forcetitle': opts.gettitle,
718         'forceid': opts.getid,
719         'forcethumbnail': opts.getthumbnail,
720         'forcedescription': opts.getdescription,
721         'forceduration': opts.getduration,
722         'forcefilename': opts.getfilename,
723         'forceformat': opts.getformat,
724         'forcejson': opts.dumpjson,
725         'simulate': opts.simulate,
726         'skip_download': (opts.skip_download or opts.simulate or any_printing),
727         'format': opts.format,
728         'format_limit': opts.format_limit,
729         'listformats': opts.listformats,
730         'outtmpl': outtmpl,
731         'autonumber_size': opts.autonumber_size,
732         'restrictfilenames': opts.restrictfilenames,
733         'ignoreerrors': opts.ignoreerrors,
734         'ratelimit': opts.ratelimit,
735         'nooverwrites': opts.nooverwrites,
736         'retries': opts.retries,
737         'buffersize': opts.buffersize,
738         'noresizebuffer': opts.noresizebuffer,
739         'continuedl': opts.continue_dl,
740         'noprogress': opts.noprogress,
741         'progress_with_newline': opts.progress_with_newline,
742         'playliststart': opts.playliststart,
743         'playlistend': opts.playlistend,
744         'noplaylist': opts.noplaylist,
745         'logtostderr': opts.outtmpl == '-',
746         'consoletitle': opts.consoletitle,
747         'nopart': opts.nopart,
748         'updatetime': opts.updatetime,
749         'writedescription': opts.writedescription,
750         'writeannotations': opts.writeannotations,
751         'writeinfojson': opts.writeinfojson,
752         'writethumbnail': opts.writethumbnail,
753         'writesubtitles': opts.writesubtitles,
754         'writeautomaticsub': opts.writeautomaticsub,
755         'allsubtitles': opts.allsubtitles,
756         'listsubtitles': opts.listsubtitles,
757         'subtitlesformat': opts.subtitlesformat,
758         'subtitleslangs': opts.subtitleslangs,
759         'matchtitle': decodeOption(opts.matchtitle),
760         'rejecttitle': decodeOption(opts.rejecttitle),
761         'max_downloads': opts.max_downloads,
762         'prefer_free_formats': opts.prefer_free_formats,
763         'verbose': opts.verbose,
764         'dump_intermediate_pages': opts.dump_intermediate_pages,
765         'write_pages': opts.write_pages,
766         'test': opts.test,
767         'keepvideo': opts.keepvideo,
768         'min_filesize': opts.min_filesize,
769         'max_filesize': opts.max_filesize,
770         'min_views': opts.min_views,
771         'max_views': opts.max_views,
772         'daterange': date,
773         'cachedir': opts.cachedir,
774         'youtube_print_sig_code': opts.youtube_print_sig_code,
775         'age_limit': opts.age_limit,
776         'download_archive': download_archive_fn,
777         'cookiefile': opts.cookiefile,
778         'nocheckcertificate': opts.no_check_certificate,
779         'prefer_insecure': opts.prefer_insecure,
780         'proxy': opts.proxy,
781         'socket_timeout': opts.socket_timeout,
782         'bidi_workaround': opts.bidi_workaround,
783         'debug_printtraffic': opts.debug_printtraffic,
784         'prefer_ffmpeg': opts.prefer_ffmpeg,
785         'include_ads': opts.include_ads,
786         'default_search': opts.default_search,
787         'youtube_include_dash_manifest': opts.youtube_include_dash_manifest,
788     }
789
790     with YoutubeDL(ydl_opts) as ydl:
791         ydl.print_debug_header()
792         ydl.add_default_info_extractors()
793
794         # PostProcessors
795         # Add the metadata pp first, the other pps will copy it
796         if opts.addmetadata:
797             ydl.add_post_processor(FFmpegMetadataPP())
798         if opts.extractaudio:
799             ydl.add_post_processor(FFmpegExtractAudioPP(preferredcodec=opts.audioformat, preferredquality=opts.audioquality, nopostoverwrites=opts.nopostoverwrites))
800         if opts.recodevideo:
801             ydl.add_post_processor(FFmpegVideoConvertor(preferedformat=opts.recodevideo))
802         if opts.embedsubtitles:
803             ydl.add_post_processor(FFmpegEmbedSubtitlePP(subtitlesformat=opts.subtitlesformat))
804         if opts.xattrs:
805             ydl.add_post_processor(XAttrMetadataPP())
806
807         # Update version
808         if opts.update_self:
809             update_self(ydl.to_screen, opts.verbose)
810
811         # Maybe do nothing
812         if (len(all_urls) < 1) and (opts.load_info_filename is None):
813             if not opts.update_self:
814                 parser.error(u'you must provide at least one URL')
815             else:
816                 sys.exit()
817
818         try:
819             if opts.load_info_filename is not None:
820                 retcode = ydl.download_with_info_file(opts.load_info_filename)
821             else:
822                 retcode = ydl.download(all_urls)
823         except MaxDownloadsReached:
824             ydl.to_screen(u'--max-download limit reached, aborting.')
825             retcode = 101
826
827     sys.exit(retcode)
828
829
830 def main(argv=None):
831     try:
832         _real_main(argv)
833     except DownloadError:
834         sys.exit(1)
835     except SameFileError:
836         sys.exit(u'ERROR: fixed output name but more than one file to download')
837     except KeyboardInterrupt:
838         sys.exit(u'\nERROR: Interrupted by user')