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