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