]> jfr.im git - yt-dlp.git/blame - youtube_dl/__init__.py
Simplify WorldStarHipHop
[yt-dlp.git] / youtube_dl / __init__.py
CommitLineData
235b3ba4
PH
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
02b324a2 4from __future__ import with_statement
9e8056d5 5from __future__ import absolute_import
02b324a2 6
3906e6ce 7__authors__ = (
59ae15a5
PH
8 'Ricardo Garcia Gonzalez',
9 'Danny Colligan',
10 'Benjamin Johnson',
11 'Vasyl\' Vavrychuk',
12 'Witold Baryluk',
13 'Paweł Paprota',
14 'Gergely Imreh',
15 'Rogério Brito',
16 'Philipp Hagemeister',
17 'Sören Schulze',
18 'Kevin Ngo',
19 'Ori Avtalion',
20 'shizeeg',
21 'Filippo Valsorda',
22 'Christian Albrecht',
88f6c78b 23 'Dave Vasilevsky',
2069acc6 24 'Jaime Marquínez Ferrándiz',
fffec3b9 25 'Jeff Crouse',
6aabe820 26 'Osama Khalid',
e8600d69 27 'Michael Walter',
95464f14 28 'M. Yasoob Ullah Khalid',
59ae15a5 29 )
235b3ba4
PH
30
31__license__ = 'Public Domain'
235b3ba4 32
0d94f247 33import codecs
c9ed14e6 34import getpass
c9ed14e6 35import optparse
235b3ba4 36import os
235b3ba4 37import re
c9ed14e6 38import shlex
235b3ba4 39import socket
235b3ba4
PH
40import subprocess
41import sys
235b3ba4 42import warnings
4e38899e 43import platform
235b3ba4 44
9e8056d5 45from .utils import *
d5ed35b6 46from .update import update_self
f427df17 47from .version import __version__
9e8056d5 48from .FileDownloader import *
4aeae91f 49from .InfoExtractors import gen_extractors
9e8056d5 50from .PostProcessor import *
235b3ba4 51
75b5c590 52def parseOpts(overrideArguments=None):
59ae15a5
PH
53 def _readOptions(filename_bytes):
54 try:
55 optionf = open(filename_bytes)
56 except IOError:
57 return [] # silently skip if file is not present
58 try:
59 res = []
60 for l in optionf:
61 res += shlex.split(l, comments=True)
62 finally:
63 optionf.close()
64 return res
65
66 def _format_option_string(option):
67 ''' ('-o', '--option') -> -o, --format METAVAR'''
68
69 opts = []
70
71 if option._short_opts:
72 opts.append(option._short_opts[0])
73 if option._long_opts:
74 opts.append(option._long_opts[0])
75 if len(opts) > 1:
76 opts.insert(1, ', ')
77
78 if option.takes_value(): opts.append(' %s' % option.metavar)
79
80 return "".join(opts)
81
82 def _find_term_columns():
83 columns = os.environ.get('COLUMNS', None)
84 if columns:
85 return int(columns)
86
87 try:
88 sp = subprocess.Popen(['stty', 'size'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
89 out,err = sp.communicate()
90 return int(out.split()[1])
91 except:
92 pass
93 return None
94
95 max_width = 80
96 max_help_position = 80
97
98 # No need to wrap help messages if we're on a wide console
99 columns = _find_term_columns()
100 if columns: max_width = columns
101
102 fmt = optparse.IndentedHelpFormatter(width=max_width, max_help_position=max_help_position)
103 fmt.format_option_strings = _format_option_string
104
105 kw = {
106 'version' : __version__,
107 'formatter' : fmt,
108 'usage' : '%prog [options] url [url...]',
109 'conflict_handler' : 'resolve',
110 }
111
112 parser = optparse.OptionParser(**kw)
113
114 # option groups
115 general = optparse.OptionGroup(parser, 'General Options')
116 selection = optparse.OptionGroup(parser, 'Video Selection')
117 authentication = optparse.OptionGroup(parser, 'Authentication Options')
118 video_format = optparse.OptionGroup(parser, 'Video Format Options')
119 postproc = optparse.OptionGroup(parser, 'Post-processing Options')
120 filesystem = optparse.OptionGroup(parser, 'Filesystem Options')
121 verbosity = optparse.OptionGroup(parser, 'Verbosity / Simulation Options')
122
123 general.add_option('-h', '--help',
124 action='help', help='print this help text and exit')
125 general.add_option('-v', '--version',
126 action='version', help='print program version and exit')
127 general.add_option('-U', '--update',
128 action='store_true', dest='update_self', help='update this program to latest version')
129 general.add_option('-i', '--ignore-errors',
130 action='store_true', dest='ignoreerrors', help='continue on download errors', default=False)
131 general.add_option('-r', '--rate-limit',
f918ec7e 132 dest='ratelimit', metavar='LIMIT', help='maximum download rate (e.g. 50k or 44.6m)')
59ae15a5
PH
133 general.add_option('-R', '--retries',
134 dest='retries', metavar='RETRIES', help='number of retries (default is %default)', default=10)
135 general.add_option('--buffer-size',
136 dest='buffersize', metavar='SIZE', help='size of download buffer (e.g. 1024 or 16k) (default is %default)', default="1024")
137 general.add_option('--no-resize-buffer',
138 action='store_true', dest='noresizebuffer',
139 help='do not automatically adjust the buffer size. By default, the buffer size is automatically resized from an initial value of SIZE.', default=False)
140 general.add_option('--dump-user-agent',
141 action='store_true', dest='dump_user_agent',
142 help='display the current browser identification', default=False)
143 general.add_option('--user-agent',
144 dest='user_agent', help='specify a custom user agent', metavar='UA')
28535652 145 general.add_option('--referer',
3820df01
JMF
146 dest='referer', help='specify a custom referer, use if the video access is restricted to one domain',
147 metavar='REF', default=None)
59ae15a5
PH
148 general.add_option('--list-extractors',
149 action='store_true', dest='list_extractors',
150 help='List all supported extractors and the URLs they would handle', default=False)
dbc50fdf 151 general.add_option('--proxy', dest='proxy', default=None, help='Use the specified HTTP/HTTPS proxy', metavar='URL')
8d5d3a5d 152 general.add_option('--test', action='store_true', dest='test', default=False, help=optparse.SUPPRESS_HELP)
59ae15a5
PH
153
154 selection.add_option('--playlist-start',
155 dest='playliststart', metavar='NUMBER', help='playlist video to start at (default is %default)', default=1)
156 selection.add_option('--playlist-end',
157 dest='playlistend', metavar='NUMBER', help='playlist video to end at (default is last)', default=-1)
158 selection.add_option('--match-title', dest='matchtitle', metavar='REGEX',help='download only matching titles (regex or caseless sub-string)')
159 selection.add_option('--reject-title', dest='rejecttitle', metavar='REGEX',help='skip download for matching titles (regex or caseless sub-string)')
160 selection.add_option('--max-downloads', metavar='NUMBER', dest='max_downloads', help='Abort after downloading NUMBER files', default=None)
dbf2ba3d
PH
161 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)
162 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
163 selection.add_option('--date', metavar='DATE', dest='date', help='download only videos uploaded in this date', default=None)
164 selection.add_option('--datebefore', metavar='DATE', dest='datebefore', help='download only videos uploaded before this date', default=None)
165 selection.add_option('--dateafter', metavar='DATE', dest='dateafter', help='download only videos uploaded after this date', default=None)
9e982f9e
JC
166
167
59ae15a5
PH
168 authentication.add_option('-u', '--username',
169 dest='username', metavar='USERNAME', help='account username')
170 authentication.add_option('-p', '--password',
171 dest='password', metavar='PASSWORD', help='account password')
172 authentication.add_option('-n', '--netrc',
173 action='store_true', dest='usenetrc', help='use .netrc authentication data', default=False)
174
175
176 video_format.add_option('-f', '--format',
f4b659f7
JMF
177 action='store', dest='format', metavar='FORMAT',
178 help='video format code, specifiy the order of preference using slashes: "-f 22/17/18"')
59ae15a5
PH
179 video_format.add_option('--all-formats',
180 action='store_const', dest='format', help='download all available video formats', const='all')
181 video_format.add_option('--prefer-free-formats',
182 action='store_true', dest='prefer_free_formats', default=False, help='prefer free video formats unless a specific one is requested')
183 video_format.add_option('--max-quality',
184 action='store', dest='format_limit', metavar='FORMAT', help='highest quality format to download')
185 video_format.add_option('-F', '--list-formats',
186 action='store_true', dest='listformats', help='list all available formats (currently youtube only)')
b9fc4284 187 video_format.add_option('--write-sub', '--write-srt',
59ae15a5 188 action='store_true', dest='writesubtitles',
553d0974
IM
189 help='write subtitle file (currently youtube only)', default=False)
190 video_format.add_option('--only-sub',
cdb130b0 191 action='store_true', dest='onlysubtitles',
553d0974
IM
192 help='downloads only the subtitles (no video)', default=False)
193 video_format.add_option('--all-subs',
ae608b80
IM
194 action='store_true', dest='allsubtitles',
195 help='downloads all the available subtitles of the video (currently youtube only)', default=False)
2a4093ea
IM
196 video_format.add_option('--list-subs',
197 action='store_true', dest='listsubtitles',
198 help='lists all available subtitles for the video (currently youtube only)', default=False)
9e62bc44
IM
199 video_format.add_option('--sub-format',
200 action='store', dest='subtitlesformat', metavar='LANG',
201 help='subtitle format [srt/sbv] (default=srt) (currently youtube only)', default='srt')
b9fc4284 202 video_format.add_option('--sub-lang', '--srt-lang',
59ae15a5 203 action='store', dest='subtitleslang', metavar='LANG',
553d0974 204 help='language of the subtitles to download (optional) use IETF language tags like \'en\'')
59ae15a5 205
59ae15a5
PH
206 verbosity.add_option('-q', '--quiet',
207 action='store_true', dest='quiet', help='activates quiet mode', default=False)
208 verbosity.add_option('-s', '--simulate',
209 action='store_true', dest='simulate', help='do not download the video and do not write anything to disk', default=False)
210 verbosity.add_option('--skip-download',
211 action='store_true', dest='skip_download', help='do not download the video', default=False)
212 verbosity.add_option('-g', '--get-url',
213 action='store_true', dest='geturl', help='simulate, quiet but print URL', default=False)
214 verbosity.add_option('-e', '--get-title',
215 action='store_true', dest='gettitle', help='simulate, quiet but print title', default=False)
216 verbosity.add_option('--get-thumbnail',
217 action='store_true', dest='getthumbnail',
218 help='simulate, quiet but print thumbnail URL', default=False)
219 verbosity.add_option('--get-description',
220 action='store_true', dest='getdescription',
221 help='simulate, quiet but print video description', default=False)
222 verbosity.add_option('--get-filename',
223 action='store_true', dest='getfilename',
224 help='simulate, quiet but print output filename', default=False)
225 verbosity.add_option('--get-format',
226 action='store_true', dest='getformat',
227 help='simulate, quiet but print output format', default=False)
7311fef8 228 verbosity.add_option('--newline',
5717d91a 229 action='store_true', dest='progress_with_newline', help='output progress bar as new lines', default=False)
59ae15a5
PH
230 verbosity.add_option('--no-progress',
231 action='store_true', dest='noprogress', help='do not print progress bar', default=False)
232 verbosity.add_option('--console-title',
233 action='store_true', dest='consoletitle',
234 help='display progress in console titlebar', default=False)
235 verbosity.add_option('-v', '--verbose',
236 action='store_true', dest='verbose', help='print various debugging information', default=False)
855703e5
PH
237 verbosity.add_option('--dump-intermediate-pages',
238 action='store_true', dest='dump_intermediate_pages', default=False,
239 help='print downloaded pages to debug problems(very verbose)')
59ae15a5 240
59ae15a5 241 filesystem.add_option('-t', '--title',
08b2ac74 242 action='store_true', dest='usetitle', help='use title in file name (default)', default=False)
59ae15a5 243 filesystem.add_option('--id',
08b2ac74 244 action='store_true', dest='useid', help='use only video ID in file name', default=False)
59ae15a5
PH
245 filesystem.add_option('-l', '--literal',
246 action='store_true', dest='usetitle', help='[deprecated] alias of --title', default=False)
247 filesystem.add_option('-A', '--auto-number',
248 action='store_true', dest='autonumber',
249 help='number downloaded files starting from 00000', default=False)
250 filesystem.add_option('-o', '--output',
74e3452b
JMF
251 dest='outtmpl', metavar='TEMPLATE',
252 help=('output filename template. Use %(title)s to get the title, '
253 '%(uploader)s for the uploader name, %(uploader_id)s for the uploader nickname if different, '
254 '%(autonumber)s to get an automatically incremented number, '
255 '%(ext)s for the filename extension, %(upload_date)s for the upload date (YYYYMMDD), '
256 '%(extractor)s for the provider (youtube, metacafe, etc), '
257 '%(id)s for the video id , %(playlist)s for the playlist the video is in, '
258 '%(playlist_index)s for the position in the playlist and %% for a literal percent. '
259 'Use - to output to stdout. Can also be used to download to a different directory, '
260 'for example with -o \'/my/downloads/%(uploader)s/%(title)s-%(id)s.%(ext)s\' .'))
213c31ae
SK
261 filesystem.add_option('--autonumber-size',
262 dest='autonumber_size', metavar='NUMBER',
263 help='Specifies the number of digits in %(autonumber)s when it is present in output filename template or --autonumber option is given')
59ae15a5
PH
264 filesystem.add_option('--restrict-filenames',
265 action='store_true', dest='restrictfilenames',
266 help='Restrict filenames to only ASCII characters, and avoid "&" and spaces in filenames', default=False)
267 filesystem.add_option('-a', '--batch-file',
268 dest='batchfile', metavar='FILE', help='file containing URLs to download (\'-\' for stdin)')
269 filesystem.add_option('-w', '--no-overwrites',
270 action='store_true', dest='nooverwrites', help='do not overwrite files', default=False)
271 filesystem.add_option('-c', '--continue',
272 action='store_true', dest='continue_dl', help='resume partially downloaded files', default=True)
273 filesystem.add_option('--no-continue',
274 action='store_false', dest='continue_dl',
275 help='do not resume partially downloaded files (restart from beginning)')
276 filesystem.add_option('--cookies',
277 dest='cookiefile', metavar='FILE', help='file to read cookies from and dump cookie jar in')
278 filesystem.add_option('--no-part',
279 action='store_true', dest='nopart', help='do not use .part files', default=False)
280 filesystem.add_option('--no-mtime',
281 action='store_false', dest='updatetime',
282 help='do not use the Last-modified header to set the file modification time', default=True)
283 filesystem.add_option('--write-description',
284 action='store_true', dest='writedescription',
285 help='write video description to a .description file', default=False)
286 filesystem.add_option('--write-info-json',
287 action='store_true', dest='writeinfojson',
288 help='write video metadata to a .info.json file', default=False)
11d9224e
PH
289 filesystem.add_option('--write-thumbnail',
290 action='store_true', dest='writethumbnail',
291 help='write thumbnail image to disk', default=False)
59ae15a5
PH
292
293
294 postproc.add_option('-x', '--extract-audio', action='store_true', dest='extractaudio', default=False,
295 help='convert video files to audio-only files (requires ffmpeg or avconv and ffprobe or avprobe)')
296 postproc.add_option('--audio-format', metavar='FORMAT', dest='audioformat', default='best',
510e6f6d 297 help='"best", "aac", "vorbis", "mp3", "m4a", "opus", or "wav"; best by default')
59ae15a5
PH
298 postproc.add_option('--audio-quality', metavar='QUALITY', dest='audioquality', default='5',
299 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
300 postproc.add_option('--recode-video', metavar='FORMAT', dest='recodevideo', default=None,
301 help='Encode the video to another format if necessary (currently supported: mp4|flv|ogg|webm)')
59ae15a5
PH
302 postproc.add_option('-k', '--keep-video', action='store_true', dest='keepvideo', default=False,
303 help='keeps the video file on disk after the post-processing; the video is erased by default')
f0648fc1
BPG
304 postproc.add_option('--no-post-overwrites', action='store_true', dest='nopostoverwrites', default=False,
305 help='do not overwrite post-processed files; the post-processed files are overwritten by default')
59ae15a5
PH
306
307
308 parser.add_option_group(general)
309 parser.add_option_group(selection)
310 parser.add_option_group(filesystem)
311 parser.add_option_group(verbosity)
312 parser.add_option_group(video_format)
313 parser.add_option_group(authentication)
314 parser.add_option_group(postproc)
315
75b5c590
PH
316 if overrideArguments is not None:
317 opts, args = parser.parse_args(overrideArguments)
318 if opts.verbose:
319 print(u'[debug] Override config: ' + repr(overrideArguments))
59ae15a5 320 else:
75b5c590
PH
321 xdg_config_home = os.environ.get('XDG_CONFIG_HOME')
322 if xdg_config_home:
323 userConfFile = os.path.join(xdg_config_home, 'youtube-dl.conf')
324 else:
325 userConfFile = os.path.join(os.path.expanduser('~'), '.config', 'youtube-dl.conf')
326 systemConf = _readOptions('/etc/youtube-dl.conf')
327 userConf = _readOptions(userConfFile)
328 commandLineConf = sys.argv[1:]
329 argv = systemConf + userConf + commandLineConf
330 opts, args = parser.parse_args(argv)
c76cb6d5
PH
331 if opts.verbose:
332 print(u'[debug] System config: ' + repr(systemConf))
333 print(u'[debug] User config: ' + repr(userConf))
334 print(u'[debug] Command-line args: ' + repr(commandLineConf))
8c42c506 335
59ae15a5 336 return parser, opts, args
235b3ba4 337
b8ad4f02 338def _real_main(argv=None):
0d94f247
PH
339 # Compatibility fixes for Windows
340 if sys.platform == 'win32':
341 # https://github.com/rg3/youtube-dl/issues/820
342 codecs.register(lambda name: codecs.lookup('utf-8') if name == 'cp65001' else None)
343
b8ad4f02 344 parser, opts, args = parseOpts(argv)
59ae15a5
PH
345
346 # Open appropriate CookieJar
347 if opts.cookiefile is None:
348 jar = compat_cookiejar.CookieJar()
349 else:
350 try:
351 jar = compat_cookiejar.MozillaCookieJar(opts.cookiefile)
229cac75 352 if os.access(opts.cookiefile, os.R_OK):
59ae15a5
PH
353 jar.load()
354 except (IOError, OSError) as err:
229cac75
PH
355 if opts.verbose:
356 traceback.print_exc()
357 sys.stderr.write(u'ERROR: unable to open cookie file\n')
358 sys.exit(101)
59ae15a5
PH
359 # Set user agent
360 if opts.user_agent is not None:
361 std_headers['User-Agent'] = opts.user_agent
28535652
BH
362
363 # Set referer
364 if opts.referer is not None:
365 std_headers['Referer'] = opts.referer
59ae15a5
PH
366
367 # Dump user agent
368 if opts.dump_user_agent:
369 print(std_headers['User-Agent'])
370 sys.exit(0)
371
372 # Batch file verification
373 batchurls = []
374 if opts.batchfile is not None:
375 try:
376 if opts.batchfile == '-':
377 batchfd = sys.stdin
378 else:
379 batchfd = open(opts.batchfile, 'r')
380 batchurls = batchfd.readlines()
381 batchurls = [x.strip() for x in batchurls]
382 batchurls = [x for x in batchurls if len(x) > 0 and not re.search(r'^[#/;]', x)]
383 except IOError:
384 sys.exit(u'ERROR: batch file could not be read')
385 all_urls = batchurls + args
386 all_urls = [url.strip() for url in all_urls]
387
388 # General configuration
389 cookie_processor = compat_urllib_request.HTTPCookieProcessor(jar)
5fb16555
PH
390 if opts.proxy:
391 proxies = {'http': opts.proxy, 'https': opts.proxy}
392 else:
393 proxies = compat_urllib_request.getproxies()
394 # Set HTTPS proxy to HTTP one if given (https://github.com/rg3/youtube-dl/issues/805)
395 if 'http' in proxies and 'https' not in proxies:
396 proxies['https'] = proxies['http']
434aca5b 397 proxy_handler = compat_urllib_request.ProxyHandler(proxies)
c34407d1
PH
398 https_handler = compat_urllib_request.HTTPSHandler()
399 opener = compat_urllib_request.build_opener(https_handler, proxy_handler, cookie_processor, YoutubeDLHandler())
59ae15a5
PH
400 compat_urllib_request.install_opener(opener)
401 socket.setdefaulttimeout(300) # 5 minutes should be enough (famous last words)
402
403 extractors = gen_extractors()
404
405 if opts.list_extractors:
406 for ie in extractors:
b08e09c3 407 print(ie.IE_NAME + (' (CURRENTLY BROKEN)' if not ie._WORKING else ''))
1a2c3c0f
FV
408 matchedUrls = [url for url in all_urls if ie.suitable(url)]
409 all_urls = [url for url in all_urls if url not in matchedUrls]
59ae15a5
PH
410 for mu in matchedUrls:
411 print(u' ' + mu)
412 sys.exit(0)
413
414 # Conflicting, missing and erroneous options
415 if opts.usenetrc and (opts.username is not None or opts.password is not None):
416 parser.error(u'using .netrc conflicts with giving username/password')
417 if opts.password is not None and opts.username is None:
418 parser.error(u'account username missing')
419 if opts.outtmpl is not None and (opts.usetitle or opts.autonumber or opts.useid):
420 parser.error(u'using output template conflicts with using title, video ID or auto number')
421 if opts.usetitle and opts.useid:
422 parser.error(u'using title conflicts with using video ID')
423 if opts.username is not None and opts.password is None:
424 opts.password = getpass.getpass(u'Type account password and press return:')
425 if opts.ratelimit is not None:
426 numeric_limit = FileDownloader.parse_bytes(opts.ratelimit)
427 if numeric_limit is None:
428 parser.error(u'invalid rate limit specified')
429 opts.ratelimit = numeric_limit
9e982f9e
JC
430 if opts.min_filesize is not None:
431 numeric_limit = FileDownloader.parse_bytes(opts.min_filesize)
432 if numeric_limit is None:
433 parser.error(u'invalid min_filesize specified')
434 opts.min_filesize = numeric_limit
435 if opts.max_filesize is not None:
436 numeric_limit = FileDownloader.parse_bytes(opts.max_filesize)
437 if numeric_limit is None:
438 parser.error(u'invalid max_filesize specified')
439 opts.max_filesize = numeric_limit
59ae15a5
PH
440 if opts.retries is not None:
441 try:
442 opts.retries = int(opts.retries)
443 except (TypeError, ValueError) as err:
444 parser.error(u'invalid retry count specified')
445 if opts.buffersize is not None:
446 numeric_buffersize = FileDownloader.parse_bytes(opts.buffersize)
447 if numeric_buffersize is None:
448 parser.error(u'invalid buffer size specified')
449 opts.buffersize = numeric_buffersize
450 try:
451 opts.playliststart = int(opts.playliststart)
452 if opts.playliststart <= 0:
453 raise ValueError(u'Playlist start must be positive')
454 except (TypeError, ValueError) as err:
455 parser.error(u'invalid playlist start number specified')
456 try:
457 opts.playlistend = int(opts.playlistend)
458 if opts.playlistend != -1 and (opts.playlistend <= 0 or opts.playlistend < opts.playliststart):
459 raise ValueError(u'Playlist end must be greater than playlist start')
460 except (TypeError, ValueError) as err:
461 parser.error(u'invalid playlist end number specified')
462 if opts.extractaudio:
510e6f6d 463 if opts.audioformat not in ['best', 'aac', 'mp3', 'm4a', 'opus', 'vorbis', 'wav']:
59ae15a5
PH
464 parser.error(u'invalid audio format specified')
465 if opts.audioquality:
466 opts.audioquality = opts.audioquality.strip('k').strip('K')
467 if not opts.audioquality.isdigit():
468 parser.error(u'invalid audio quality specified')
7851b379
PH
469 if opts.recodevideo is not None:
470 if opts.recodevideo not in ['mp4', 'flv', 'webm', 'ogg']:
471 parser.error(u'invalid video recode format specified')
bd558525
JMF
472 if opts.date is not None:
473 date = DateRange.day(opts.date)
474 else:
475 date = DateRange(opts.dateafter, opts.datebefore)
59ae15a5 476
5cb9c312
PH
477 if sys.version_info < (3,):
478 # In Python 2, sys.argv is a bytestring (also note http://bugs.python.org/issue2128 for Windows systems)
0be41ec2
PH
479 if opts.outtmpl is not None:
480 opts.outtmpl = opts.outtmpl.decode(preferredencoding())
5cb9c312
PH
481 outtmpl =((opts.outtmpl is not None and opts.outtmpl)
482 or (opts.format == '-1' and opts.usetitle and u'%(title)s-%(id)s-%(format)s.%(ext)s')
483 or (opts.format == '-1' and u'%(id)s-%(format)s.%(ext)s')
484 or (opts.usetitle and opts.autonumber and u'%(autonumber)s-%(title)s-%(id)s.%(ext)s')
485 or (opts.usetitle and u'%(title)s-%(id)s.%(ext)s')
486 or (opts.useid and u'%(id)s.%(ext)s')
487 or (opts.autonumber and u'%(autonumber)s-%(id)s.%(ext)s')
08b2ac74 488 or u'%(title)s-%(id)s.%(ext)s')
8271226a 489
59ae15a5
PH
490 # File downloader
491 fd = FileDownloader({
492 'usenetrc': opts.usenetrc,
493 'username': opts.username,
494 'password': opts.password,
495 'quiet': (opts.quiet or opts.geturl or opts.gettitle or opts.getthumbnail or opts.getdescription or opts.getfilename or opts.getformat),
496 'forceurl': opts.geturl,
497 'forcetitle': opts.gettitle,
498 'forcethumbnail': opts.getthumbnail,
499 'forcedescription': opts.getdescription,
500 'forcefilename': opts.getfilename,
501 'forceformat': opts.getformat,
502 'simulate': opts.simulate,
503 'skip_download': (opts.skip_download or opts.simulate or opts.geturl or opts.gettitle or opts.getthumbnail or opts.getdescription or opts.getfilename or opts.getformat),
504 'format': opts.format,
505 'format_limit': opts.format_limit,
506 'listformats': opts.listformats,
5cb9c312 507 'outtmpl': outtmpl,
213c31ae 508 'autonumber_size': opts.autonumber_size,
59ae15a5
PH
509 'restrictfilenames': opts.restrictfilenames,
510 'ignoreerrors': opts.ignoreerrors,
511 'ratelimit': opts.ratelimit,
512 'nooverwrites': opts.nooverwrites,
513 'retries': opts.retries,
514 'buffersize': opts.buffersize,
515 'noresizebuffer': opts.noresizebuffer,
516 'continuedl': opts.continue_dl,
517 'noprogress': opts.noprogress,
5717d91a 518 'progress_with_newline': opts.progress_with_newline,
59ae15a5
PH
519 'playliststart': opts.playliststart,
520 'playlistend': opts.playlistend,
521 'logtostderr': opts.outtmpl == '-',
522 'consoletitle': opts.consoletitle,
523 'nopart': opts.nopart,
524 'updatetime': opts.updatetime,
525 'writedescription': opts.writedescription,
526 'writeinfojson': opts.writeinfojson,
11d9224e 527 'writethumbnail': opts.writethumbnail,
59ae15a5 528 'writesubtitles': opts.writesubtitles,
cdb130b0 529 'onlysubtitles': opts.onlysubtitles,
ae608b80 530 'allsubtitles': opts.allsubtitles,
2a4093ea 531 'listsubtitles': opts.listsubtitles,
9e62bc44 532 'subtitlesformat': opts.subtitlesformat,
59ae15a5 533 'subtitleslang': opts.subtitleslang,
8271226a
PH
534 'matchtitle': decodeOption(opts.matchtitle),
535 'rejecttitle': decodeOption(opts.rejecttitle),
59ae15a5
PH
536 'max_downloads': opts.max_downloads,
537 'prefer_free_formats': opts.prefer_free_formats,
538 'verbose': opts.verbose,
855703e5 539 'dump_intermediate_pages': opts.dump_intermediate_pages,
8d5d3a5d 540 'test': opts.test,
7851b379 541 'keepvideo': opts.keepvideo,
9e982f9e 542 'min_filesize': opts.min_filesize,
bd558525 543 'max_filesize': opts.max_filesize,
11d9224e 544 'daterange': date,
59ae15a5
PH
545 })
546
547 if opts.verbose:
f427df17 548 fd.to_screen(u'[debug] youtube-dl version ' + __version__)
4e38899e 549 try:
f427df17
FV
550 sp = subprocess.Popen(['git', 'rev-parse', '--short', 'HEAD'], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
551 cwd=os.path.dirname(os.path.abspath(__file__)))
4e38899e
FV
552 out, err = sp.communicate()
553 out = out.decode().strip()
554 if re.match('[0-9a-f]+', out):
555 fd.to_screen(u'[debug] Git HEAD: ' + out)
556 except:
557 pass
558 fd.to_screen(u'[debug] Python version %s - %s' %(platform.python_version(), platform.platform()))
59ae15a5
PH
559 fd.to_screen(u'[debug] Proxy map: ' + str(proxy_handler.proxies))
560
561 for extractor in extractors:
562 fd.add_info_extractor(extractor)
563
564 # PostProcessors
565 if opts.extractaudio:
7851b379
PH
566 fd.add_post_processor(FFmpegExtractAudioPP(preferredcodec=opts.audioformat, preferredquality=opts.audioquality, nopostoverwrites=opts.nopostoverwrites))
567 if opts.recodevideo:
568 fd.add_post_processor(FFmpegVideoConvertor(preferedformat=opts.recodevideo))
59ae15a5 569
67353612
PH
570 # Update version
571 if opts.update_self:
572 update_self(fd.to_screen, opts.verbose, sys.argv[0])
573
59ae15a5
PH
574 # Maybe do nothing
575 if len(all_urls) < 1:
576 if not opts.update_self:
577 parser.error(u'you must provide at least one URL')
578 else:
579 sys.exit()
580
581 try:
582 retcode = fd.download(all_urls)
583 except MaxDownloadsReached:
584 fd.to_screen(u'--max-download limit reached, aborting.')
585 retcode = 101
586
587 # Dump cookie jar if requested
588 if opts.cookiefile is not None:
589 try:
590 jar.save()
591 except (IOError, OSError) as err:
592 sys.exit(u'ERROR: unable to save cookie jar')
593
594 sys.exit(retcode)
235b3ba4 595
b8ad4f02 596def main(argv=None):
59ae15a5 597 try:
b8ad4f02 598 _real_main(argv)
59ae15a5
PH
599 except DownloadError:
600 sys.exit(1)
601 except SameFileError:
602 sys.exit(u'ERROR: fixed output name but more than one file to download')
603 except KeyboardInterrupt:
604 sys.exit(u'\nERROR: Interrupted by user')