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