]> jfr.im git - yt-dlp.git/blame - youtube_dl/__init__.py
Added new option '--all-srt' to download all 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)
ae608b80
IM
182 video_format.add_option('--all-srt',
183 action='store_true', dest='allsubtitles',
184 help='downloads all the available subtitles of the video (currently youtube only)', default=False)
59ae15a5
PH
185 video_format.add_option('--srt-lang',
186 action='store', dest='subtitleslang', metavar='LANG',
187 help='language of the closed captions to download (optional) use IETF language tags like \'en\'')
188
59ae15a5
PH
189 verbosity.add_option('-q', '--quiet',
190 action='store_true', dest='quiet', help='activates quiet mode', default=False)
191 verbosity.add_option('-s', '--simulate',
192 action='store_true', dest='simulate', help='do not download the video and do not write anything to disk', default=False)
193 verbosity.add_option('--skip-download',
194 action='store_true', dest='skip_download', help='do not download the video', default=False)
195 verbosity.add_option('-g', '--get-url',
196 action='store_true', dest='geturl', help='simulate, quiet but print URL', default=False)
197 verbosity.add_option('-e', '--get-title',
198 action='store_true', dest='gettitle', help='simulate, quiet but print title', default=False)
199 verbosity.add_option('--get-thumbnail',
200 action='store_true', dest='getthumbnail',
201 help='simulate, quiet but print thumbnail URL', default=False)
202 verbosity.add_option('--get-description',
203 action='store_true', dest='getdescription',
204 help='simulate, quiet but print video description', default=False)
205 verbosity.add_option('--get-filename',
206 action='store_true', dest='getfilename',
207 help='simulate, quiet but print output filename', default=False)
208 verbosity.add_option('--get-format',
209 action='store_true', dest='getformat',
210 help='simulate, quiet but print output format', default=False)
7311fef8 211 verbosity.add_option('--newline',
5717d91a 212 action='store_true', dest='progress_with_newline', help='output progress bar as new lines', default=False)
59ae15a5
PH
213 verbosity.add_option('--no-progress',
214 action='store_true', dest='noprogress', help='do not print progress bar', default=False)
215 verbosity.add_option('--console-title',
216 action='store_true', dest='consoletitle',
217 help='display progress in console titlebar', default=False)
218 verbosity.add_option('-v', '--verbose',
219 action='store_true', dest='verbose', help='print various debugging information', default=False)
220
59ae15a5
PH
221 filesystem.add_option('-t', '--title',
222 action='store_true', dest='usetitle', help='use title in file name', default=False)
223 filesystem.add_option('--id',
224 action='store_true', dest='useid', help='use video ID in file name', default=False)
225 filesystem.add_option('-l', '--literal',
226 action='store_true', dest='usetitle', help='[deprecated] alias of --title', default=False)
227 filesystem.add_option('-A', '--auto-number',
228 action='store_true', dest='autonumber',
229 help='number downloaded files starting from 00000', default=False)
230 filesystem.add_option('-o', '--output',
77c4beab 231 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
232 filesystem.add_option('--restrict-filenames',
233 action='store_true', dest='restrictfilenames',
234 help='Restrict filenames to only ASCII characters, and avoid "&" and spaces in filenames', default=False)
235 filesystem.add_option('-a', '--batch-file',
236 dest='batchfile', metavar='FILE', help='file containing URLs to download (\'-\' for stdin)')
237 filesystem.add_option('-w', '--no-overwrites',
238 action='store_true', dest='nooverwrites', help='do not overwrite files', default=False)
239 filesystem.add_option('-c', '--continue',
240 action='store_true', dest='continue_dl', help='resume partially downloaded files', default=True)
241 filesystem.add_option('--no-continue',
242 action='store_false', dest='continue_dl',
243 help='do not resume partially downloaded files (restart from beginning)')
244 filesystem.add_option('--cookies',
245 dest='cookiefile', metavar='FILE', help='file to read cookies from and dump cookie jar in')
246 filesystem.add_option('--no-part',
247 action='store_true', dest='nopart', help='do not use .part files', default=False)
248 filesystem.add_option('--no-mtime',
249 action='store_false', dest='updatetime',
250 help='do not use the Last-modified header to set the file modification time', default=True)
251 filesystem.add_option('--write-description',
252 action='store_true', dest='writedescription',
253 help='write video description to a .description file', default=False)
254 filesystem.add_option('--write-info-json',
255 action='store_true', dest='writeinfojson',
256 help='write video metadata to a .info.json file', default=False)
257
258
259 postproc.add_option('-x', '--extract-audio', action='store_true', dest='extractaudio', default=False,
260 help='convert video files to audio-only files (requires ffmpeg or avconv and ffprobe or avprobe)')
261 postproc.add_option('--audio-format', metavar='FORMAT', dest='audioformat', default='best',
510e6f6d 262 help='"best", "aac", "vorbis", "mp3", "m4a", "opus", or "wav"; best by default')
59ae15a5
PH
263 postproc.add_option('--audio-quality', metavar='QUALITY', dest='audioquality', default='5',
264 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
265 postproc.add_option('--recode-video', metavar='FORMAT', dest='recodevideo', default=None,
266 help='Encode the video to another format if necessary (currently supported: mp4|flv|ogg|webm)')
59ae15a5
PH
267 postproc.add_option('-k', '--keep-video', action='store_true', dest='keepvideo', default=False,
268 help='keeps the video file on disk after the post-processing; the video is erased by default')
f0648fc1
BPG
269 postproc.add_option('--no-post-overwrites', action='store_true', dest='nopostoverwrites', default=False,
270 help='do not overwrite post-processed files; the post-processed files are overwritten by default')
59ae15a5
PH
271
272
273 parser.add_option_group(general)
274 parser.add_option_group(selection)
275 parser.add_option_group(filesystem)
276 parser.add_option_group(verbosity)
277 parser.add_option_group(video_format)
278 parser.add_option_group(authentication)
279 parser.add_option_group(postproc)
280
281 xdg_config_home = os.environ.get('XDG_CONFIG_HOME')
282 if xdg_config_home:
283 userConf = os.path.join(xdg_config_home, 'youtube-dl.conf')
284 else:
285 userConf = os.path.join(os.path.expanduser('~'), '.config', 'youtube-dl.conf')
286 argv = _readOptions('/etc/youtube-dl.conf') + _readOptions(userConf) + sys.argv[1:]
287 opts, args = parser.parse_args(argv)
288
289 return parser, opts, args
235b3ba4 290
235b3ba4 291def _real_main():
59ae15a5
PH
292 parser, opts, args = parseOpts()
293
294 # Open appropriate CookieJar
295 if opts.cookiefile is None:
296 jar = compat_cookiejar.CookieJar()
297 else:
298 try:
299 jar = compat_cookiejar.MozillaCookieJar(opts.cookiefile)
229cac75 300 if os.access(opts.cookiefile, os.R_OK):
59ae15a5
PH
301 jar.load()
302 except (IOError, OSError) as err:
229cac75
PH
303 if opts.verbose:
304 traceback.print_exc()
305 sys.stderr.write(u'ERROR: unable to open cookie file\n')
306 sys.exit(101)
59ae15a5
PH
307 # Set user agent
308 if opts.user_agent is not None:
309 std_headers['User-Agent'] = opts.user_agent
310
311 # Dump user agent
312 if opts.dump_user_agent:
313 print(std_headers['User-Agent'])
314 sys.exit(0)
315
316 # Batch file verification
317 batchurls = []
318 if opts.batchfile is not None:
319 try:
320 if opts.batchfile == '-':
321 batchfd = sys.stdin
322 else:
323 batchfd = open(opts.batchfile, 'r')
324 batchurls = batchfd.readlines()
325 batchurls = [x.strip() for x in batchurls]
326 batchurls = [x for x in batchurls if len(x) > 0 and not re.search(r'^[#/;]', x)]
327 except IOError:
328 sys.exit(u'ERROR: batch file could not be read')
329 all_urls = batchurls + args
330 all_urls = [url.strip() for url in all_urls]
331
332 # General configuration
333 cookie_processor = compat_urllib_request.HTTPCookieProcessor(jar)
334 proxy_handler = compat_urllib_request.ProxyHandler()
335 opener = compat_urllib_request.build_opener(proxy_handler, cookie_processor, YoutubeDLHandler())
336 compat_urllib_request.install_opener(opener)
337 socket.setdefaulttimeout(300) # 5 minutes should be enough (famous last words)
338
339 extractors = gen_extractors()
340
341 if opts.list_extractors:
342 for ie in extractors:
b08e09c3 343 print(ie.IE_NAME + (' (CURRENTLY BROKEN)' if not ie._WORKING else ''))
1a2c3c0f
FV
344 matchedUrls = [url for url in all_urls if ie.suitable(url)]
345 all_urls = [url for url in all_urls if url not in matchedUrls]
59ae15a5
PH
346 for mu in matchedUrls:
347 print(u' ' + mu)
348 sys.exit(0)
349
350 # Conflicting, missing and erroneous options
351 if opts.usenetrc and (opts.username is not None or opts.password is not None):
352 parser.error(u'using .netrc conflicts with giving username/password')
353 if opts.password is not None and opts.username is None:
354 parser.error(u'account username missing')
355 if opts.outtmpl is not None and (opts.usetitle or opts.autonumber or opts.useid):
356 parser.error(u'using output template conflicts with using title, video ID or auto number')
357 if opts.usetitle and opts.useid:
358 parser.error(u'using title conflicts with using video ID')
359 if opts.username is not None and opts.password is None:
360 opts.password = getpass.getpass(u'Type account password and press return:')
361 if opts.ratelimit is not None:
362 numeric_limit = FileDownloader.parse_bytes(opts.ratelimit)
363 if numeric_limit is None:
364 parser.error(u'invalid rate limit specified')
365 opts.ratelimit = numeric_limit
9e982f9e
JC
366 if opts.min_filesize is not None:
367 numeric_limit = FileDownloader.parse_bytes(opts.min_filesize)
368 if numeric_limit is None:
369 parser.error(u'invalid min_filesize specified')
370 opts.min_filesize = numeric_limit
371 if opts.max_filesize is not None:
372 numeric_limit = FileDownloader.parse_bytes(opts.max_filesize)
373 if numeric_limit is None:
374 parser.error(u'invalid max_filesize specified')
375 opts.max_filesize = numeric_limit
59ae15a5
PH
376 if opts.retries is not None:
377 try:
378 opts.retries = int(opts.retries)
379 except (TypeError, ValueError) as err:
380 parser.error(u'invalid retry count specified')
381 if opts.buffersize is not None:
382 numeric_buffersize = FileDownloader.parse_bytes(opts.buffersize)
383 if numeric_buffersize is None:
384 parser.error(u'invalid buffer size specified')
385 opts.buffersize = numeric_buffersize
386 try:
387 opts.playliststart = int(opts.playliststart)
388 if opts.playliststart <= 0:
389 raise ValueError(u'Playlist start must be positive')
390 except (TypeError, ValueError) as err:
391 parser.error(u'invalid playlist start number specified')
392 try:
393 opts.playlistend = int(opts.playlistend)
394 if opts.playlistend != -1 and (opts.playlistend <= 0 or opts.playlistend < opts.playliststart):
395 raise ValueError(u'Playlist end must be greater than playlist start')
396 except (TypeError, ValueError) as err:
397 parser.error(u'invalid playlist end number specified')
398 if opts.extractaudio:
510e6f6d 399 if opts.audioformat not in ['best', 'aac', 'mp3', 'm4a', 'opus', 'vorbis', 'wav']:
59ae15a5
PH
400 parser.error(u'invalid audio format specified')
401 if opts.audioquality:
402 opts.audioquality = opts.audioquality.strip('k').strip('K')
403 if not opts.audioquality.isdigit():
404 parser.error(u'invalid audio quality specified')
7851b379
PH
405 if opts.recodevideo is not None:
406 if opts.recodevideo not in ['mp4', 'flv', 'webm', 'ogg']:
407 parser.error(u'invalid video recode format specified')
59ae15a5 408
5cb9c312
PH
409 if sys.version_info < (3,):
410 # In Python 2, sys.argv is a bytestring (also note http://bugs.python.org/issue2128 for Windows systems)
0be41ec2
PH
411 if opts.outtmpl is not None:
412 opts.outtmpl = opts.outtmpl.decode(preferredencoding())
5cb9c312
PH
413 outtmpl =((opts.outtmpl is not None and opts.outtmpl)
414 or (opts.format == '-1' and opts.usetitle and u'%(title)s-%(id)s-%(format)s.%(ext)s')
415 or (opts.format == '-1' and u'%(id)s-%(format)s.%(ext)s')
416 or (opts.usetitle and opts.autonumber and u'%(autonumber)s-%(title)s-%(id)s.%(ext)s')
417 or (opts.usetitle and u'%(title)s-%(id)s.%(ext)s')
418 or (opts.useid and u'%(id)s.%(ext)s')
419 or (opts.autonumber and u'%(autonumber)s-%(id)s.%(ext)s')
420 or u'%(id)s.%(ext)s')
8271226a 421
59ae15a5
PH
422 # File downloader
423 fd = FileDownloader({
424 'usenetrc': opts.usenetrc,
425 'username': opts.username,
426 'password': opts.password,
427 'quiet': (opts.quiet or opts.geturl or opts.gettitle or opts.getthumbnail or opts.getdescription or opts.getfilename or opts.getformat),
428 'forceurl': opts.geturl,
429 'forcetitle': opts.gettitle,
430 'forcethumbnail': opts.getthumbnail,
431 'forcedescription': opts.getdescription,
432 'forcefilename': opts.getfilename,
433 'forceformat': opts.getformat,
434 'simulate': opts.simulate,
435 '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),
436 'format': opts.format,
437 'format_limit': opts.format_limit,
438 'listformats': opts.listformats,
5cb9c312 439 'outtmpl': outtmpl,
59ae15a5
PH
440 'restrictfilenames': opts.restrictfilenames,
441 'ignoreerrors': opts.ignoreerrors,
442 'ratelimit': opts.ratelimit,
443 'nooverwrites': opts.nooverwrites,
444 'retries': opts.retries,
445 'buffersize': opts.buffersize,
446 'noresizebuffer': opts.noresizebuffer,
447 'continuedl': opts.continue_dl,
448 'noprogress': opts.noprogress,
5717d91a 449 'progress_with_newline': opts.progress_with_newline,
59ae15a5
PH
450 'playliststart': opts.playliststart,
451 'playlistend': opts.playlistend,
452 'logtostderr': opts.outtmpl == '-',
453 'consoletitle': opts.consoletitle,
454 'nopart': opts.nopart,
455 'updatetime': opts.updatetime,
456 'writedescription': opts.writedescription,
457 'writeinfojson': opts.writeinfojson,
458 'writesubtitles': opts.writesubtitles,
cdb130b0 459 'onlysubtitles': opts.onlysubtitles,
ae608b80 460 'allsubtitles': opts.allsubtitles,
59ae15a5 461 'subtitleslang': opts.subtitleslang,
8271226a
PH
462 'matchtitle': decodeOption(opts.matchtitle),
463 'rejecttitle': decodeOption(opts.rejecttitle),
59ae15a5
PH
464 'max_downloads': opts.max_downloads,
465 'prefer_free_formats': opts.prefer_free_formats,
466 'verbose': opts.verbose,
8d5d3a5d 467 'test': opts.test,
7851b379 468 'keepvideo': opts.keepvideo,
9e982f9e
JC
469 'min_filesize': opts.min_filesize,
470 'max_filesize': opts.max_filesize
59ae15a5
PH
471 })
472
473 if opts.verbose:
f427df17 474 fd.to_screen(u'[debug] youtube-dl version ' + __version__)
4e38899e 475 try:
f427df17
FV
476 sp = subprocess.Popen(['git', 'rev-parse', '--short', 'HEAD'], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
477 cwd=os.path.dirname(os.path.abspath(__file__)))
4e38899e
FV
478 out, err = sp.communicate()
479 out = out.decode().strip()
480 if re.match('[0-9a-f]+', out):
481 fd.to_screen(u'[debug] Git HEAD: ' + out)
482 except:
483 pass
484 fd.to_screen(u'[debug] Python version %s - %s' %(platform.python_version(), platform.platform()))
59ae15a5
PH
485 fd.to_screen(u'[debug] Proxy map: ' + str(proxy_handler.proxies))
486
487 for extractor in extractors:
488 fd.add_info_extractor(extractor)
489
490 # PostProcessors
491 if opts.extractaudio:
7851b379
PH
492 fd.add_post_processor(FFmpegExtractAudioPP(preferredcodec=opts.audioformat, preferredquality=opts.audioquality, nopostoverwrites=opts.nopostoverwrites))
493 if opts.recodevideo:
494 fd.add_post_processor(FFmpegVideoConvertor(preferedformat=opts.recodevideo))
59ae15a5 495
67353612
PH
496 # Update version
497 if opts.update_self:
498 update_self(fd.to_screen, opts.verbose, sys.argv[0])
499
59ae15a5
PH
500 # Maybe do nothing
501 if len(all_urls) < 1:
502 if not opts.update_self:
503 parser.error(u'you must provide at least one URL')
504 else:
505 sys.exit()
506
507 try:
508 retcode = fd.download(all_urls)
509 except MaxDownloadsReached:
510 fd.to_screen(u'--max-download limit reached, aborting.')
511 retcode = 101
512
513 # Dump cookie jar if requested
514 if opts.cookiefile is not None:
515 try:
516 jar.save()
517 except (IOError, OSError) as err:
518 sys.exit(u'ERROR: unable to save cookie jar')
519
520 sys.exit(retcode)
235b3ba4
PH
521
522def main():
59ae15a5
PH
523 try:
524 _real_main()
525 except DownloadError:
526 sys.exit(1)
527 except SameFileError:
528 sys.exit(u'ERROR: fixed output name but more than one file to download')
529 except KeyboardInterrupt:
530 sys.exit(u'\nERROR: Interrupted by user')