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