]> jfr.im git - yt-dlp.git/blame - youtube_dl/__init__.py
release 2013.04.31
[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
75b5c590 50def parseOpts(overrideArguments=None):
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')
28535652 143 general.add_option('--referer',
3820df01
JMF
144 dest='referer', help='specify a custom referer, use if the video access is restricted to one domain',
145 metavar='REF', default=None)
59ae15a5
PH
146 general.add_option('--list-extractors',
147 action='store_true', dest='list_extractors',
148 help='List all supported extractors and the URLs they would handle', default=False)
dbc50fdf 149 general.add_option('--proxy', dest='proxy', default=None, help='Use the specified HTTP/HTTPS proxy', metavar='URL')
8d5d3a5d 150 general.add_option('--test', action='store_true', dest='test', default=False, help=optparse.SUPPRESS_HELP)
59ae15a5
PH
151
152 selection.add_option('--playlist-start',
153 dest='playliststart', metavar='NUMBER', help='playlist video to start at (default is %default)', default=1)
154 selection.add_option('--playlist-end',
155 dest='playlistend', metavar='NUMBER', help='playlist video to end at (default is last)', default=-1)
156 selection.add_option('--match-title', dest='matchtitle', metavar='REGEX',help='download only matching titles (regex or caseless sub-string)')
157 selection.add_option('--reject-title', dest='rejecttitle', metavar='REGEX',help='skip download for matching titles (regex or caseless sub-string)')
158 selection.add_option('--max-downloads', metavar='NUMBER', dest='max_downloads', help='Abort after downloading NUMBER files', default=None)
dbf2ba3d
PH
159 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)
160 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
161 selection.add_option('--date', metavar='DATE', dest='date', help='download only videos uploaded in this date', default=None)
162 selection.add_option('--datebefore', metavar='DATE', dest='datebefore', help='download only videos uploaded before this date', default=None)
163 selection.add_option('--dateafter', metavar='DATE', dest='dateafter', help='download only videos uploaded after this date', default=None)
9e982f9e
JC
164
165
59ae15a5
PH
166 authentication.add_option('-u', '--username',
167 dest='username', metavar='USERNAME', help='account username')
168 authentication.add_option('-p', '--password',
169 dest='password', metavar='PASSWORD', help='account password')
170 authentication.add_option('-n', '--netrc',
171 action='store_true', dest='usenetrc', help='use .netrc authentication data', default=False)
172
173
174 video_format.add_option('-f', '--format',
f4b659f7
JMF
175 action='store', dest='format', metavar='FORMAT',
176 help='video format code, specifiy the order of preference using slashes: "-f 22/17/18"')
59ae15a5
PH
177 video_format.add_option('--all-formats',
178 action='store_const', dest='format', help='download all available video formats', const='all')
179 video_format.add_option('--prefer-free-formats',
180 action='store_true', dest='prefer_free_formats', default=False, help='prefer free video formats unless a specific one is requested')
181 video_format.add_option('--max-quality',
182 action='store', dest='format_limit', metavar='FORMAT', help='highest quality format to download')
183 video_format.add_option('-F', '--list-formats',
184 action='store_true', dest='listformats', help='list all available formats (currently youtube only)')
b9fc4284 185 video_format.add_option('--write-sub', '--write-srt',
59ae15a5 186 action='store_true', dest='writesubtitles',
553d0974
IM
187 help='write subtitle file (currently youtube only)', default=False)
188 video_format.add_option('--only-sub',
cdb130b0 189 action='store_true', dest='onlysubtitles',
553d0974
IM
190 help='downloads only the subtitles (no video)', default=False)
191 video_format.add_option('--all-subs',
ae608b80
IM
192 action='store_true', dest='allsubtitles',
193 help='downloads all the available subtitles of the video (currently youtube only)', default=False)
2a4093ea
IM
194 video_format.add_option('--list-subs',
195 action='store_true', dest='listsubtitles',
196 help='lists all available subtitles for the video (currently youtube only)', default=False)
9e62bc44
IM
197 video_format.add_option('--sub-format',
198 action='store', dest='subtitlesformat', metavar='LANG',
199 help='subtitle format [srt/sbv] (default=srt) (currently youtube only)', default='srt')
b9fc4284 200 video_format.add_option('--sub-lang', '--srt-lang',
59ae15a5 201 action='store', dest='subtitleslang', metavar='LANG',
553d0974 202 help='language of the subtitles to download (optional) use IETF language tags like \'en\'')
59ae15a5 203
59ae15a5
PH
204 verbosity.add_option('-q', '--quiet',
205 action='store_true', dest='quiet', help='activates quiet mode', default=False)
206 verbosity.add_option('-s', '--simulate',
207 action='store_true', dest='simulate', help='do not download the video and do not write anything to disk', default=False)
208 verbosity.add_option('--skip-download',
209 action='store_true', dest='skip_download', help='do not download the video', default=False)
210 verbosity.add_option('-g', '--get-url',
211 action='store_true', dest='geturl', help='simulate, quiet but print URL', default=False)
212 verbosity.add_option('-e', '--get-title',
213 action='store_true', dest='gettitle', help='simulate, quiet but print title', default=False)
214 verbosity.add_option('--get-thumbnail',
215 action='store_true', dest='getthumbnail',
216 help='simulate, quiet but print thumbnail URL', default=False)
217 verbosity.add_option('--get-description',
218 action='store_true', dest='getdescription',
219 help='simulate, quiet but print video description', default=False)
220 verbosity.add_option('--get-filename',
221 action='store_true', dest='getfilename',
222 help='simulate, quiet but print output filename', default=False)
223 verbosity.add_option('--get-format',
224 action='store_true', dest='getformat',
225 help='simulate, quiet but print output format', default=False)
7311fef8 226 verbosity.add_option('--newline',
5717d91a 227 action='store_true', dest='progress_with_newline', help='output progress bar as new lines', default=False)
59ae15a5
PH
228 verbosity.add_option('--no-progress',
229 action='store_true', dest='noprogress', help='do not print progress bar', default=False)
230 verbosity.add_option('--console-title',
231 action='store_true', dest='consoletitle',
232 help='display progress in console titlebar', default=False)
233 verbosity.add_option('-v', '--verbose',
234 action='store_true', dest='verbose', help='print various debugging information', default=False)
855703e5
PH
235 verbosity.add_option('--dump-intermediate-pages',
236 action='store_true', dest='dump_intermediate_pages', default=False,
237 help='print downloaded pages to debug problems(very verbose)')
59ae15a5 238
59ae15a5 239 filesystem.add_option('-t', '--title',
08b2ac74 240 action='store_true', dest='usetitle', help='use title in file name (default)', default=False)
59ae15a5 241 filesystem.add_option('--id',
08b2ac74 242 action='store_true', dest='useid', help='use only video ID in file name', default=False)
59ae15a5
PH
243 filesystem.add_option('-l', '--literal',
244 action='store_true', dest='usetitle', help='[deprecated] alias of --title', default=False)
245 filesystem.add_option('-A', '--auto-number',
246 action='store_true', dest='autonumber',
247 help='number downloaded files starting from 00000', default=False)
248 filesystem.add_option('-o', '--output',
74e3452b
JMF
249 dest='outtmpl', metavar='TEMPLATE',
250 help=('output filename template. Use %(title)s to get the title, '
251 '%(uploader)s for the uploader name, %(uploader_id)s for the uploader nickname if different, '
252 '%(autonumber)s to get an automatically incremented number, '
253 '%(ext)s for the filename extension, %(upload_date)s for the upload date (YYYYMMDD), '
254 '%(extractor)s for the provider (youtube, metacafe, etc), '
255 '%(id)s for the video id , %(playlist)s for the playlist the video is in, '
256 '%(playlist_index)s for the position in the playlist and %% for a literal percent. '
257 'Use - to output to stdout. Can also be used to download to a different directory, '
258 'for example with -o \'/my/downloads/%(uploader)s/%(title)s-%(id)s.%(ext)s\' .'))
213c31ae
SK
259 filesystem.add_option('--autonumber-size',
260 dest='autonumber_size', metavar='NUMBER',
261 help='Specifies the number of digits in %(autonumber)s when it is present in output filename template or --autonumber option is given')
59ae15a5
PH
262 filesystem.add_option('--restrict-filenames',
263 action='store_true', dest='restrictfilenames',
264 help='Restrict filenames to only ASCII characters, and avoid "&" and spaces in filenames', default=False)
265 filesystem.add_option('-a', '--batch-file',
266 dest='batchfile', metavar='FILE', help='file containing URLs to download (\'-\' for stdin)')
267 filesystem.add_option('-w', '--no-overwrites',
268 action='store_true', dest='nooverwrites', help='do not overwrite files', default=False)
269 filesystem.add_option('-c', '--continue',
270 action='store_true', dest='continue_dl', help='resume partially downloaded files', default=True)
271 filesystem.add_option('--no-continue',
272 action='store_false', dest='continue_dl',
273 help='do not resume partially downloaded files (restart from beginning)')
274 filesystem.add_option('--cookies',
275 dest='cookiefile', metavar='FILE', help='file to read cookies from and dump cookie jar in')
276 filesystem.add_option('--no-part',
277 action='store_true', dest='nopart', help='do not use .part files', default=False)
278 filesystem.add_option('--no-mtime',
279 action='store_false', dest='updatetime',
280 help='do not use the Last-modified header to set the file modification time', default=True)
281 filesystem.add_option('--write-description',
282 action='store_true', dest='writedescription',
283 help='write video description to a .description file', default=False)
284 filesystem.add_option('--write-info-json',
285 action='store_true', dest='writeinfojson',
286 help='write video metadata to a .info.json file', default=False)
287
288
289 postproc.add_option('-x', '--extract-audio', action='store_true', dest='extractaudio', default=False,
290 help='convert video files to audio-only files (requires ffmpeg or avconv and ffprobe or avprobe)')
291 postproc.add_option('--audio-format', metavar='FORMAT', dest='audioformat', default='best',
510e6f6d 292 help='"best", "aac", "vorbis", "mp3", "m4a", "opus", or "wav"; best by default')
59ae15a5
PH
293 postproc.add_option('--audio-quality', metavar='QUALITY', dest='audioquality', default='5',
294 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
295 postproc.add_option('--recode-video', metavar='FORMAT', dest='recodevideo', default=None,
296 help='Encode the video to another format if necessary (currently supported: mp4|flv|ogg|webm)')
59ae15a5
PH
297 postproc.add_option('-k', '--keep-video', action='store_true', dest='keepvideo', default=False,
298 help='keeps the video file on disk after the post-processing; the video is erased by default')
f0648fc1
BPG
299 postproc.add_option('--no-post-overwrites', action='store_true', dest='nopostoverwrites', default=False,
300 help='do not overwrite post-processed files; the post-processed files are overwritten by default')
59ae15a5
PH
301
302
303 parser.add_option_group(general)
304 parser.add_option_group(selection)
305 parser.add_option_group(filesystem)
306 parser.add_option_group(verbosity)
307 parser.add_option_group(video_format)
308 parser.add_option_group(authentication)
309 parser.add_option_group(postproc)
310
75b5c590
PH
311 if overrideArguments is not None:
312 opts, args = parser.parse_args(overrideArguments)
313 if opts.verbose:
314 print(u'[debug] Override config: ' + repr(overrideArguments))
59ae15a5 315 else:
75b5c590
PH
316 xdg_config_home = os.environ.get('XDG_CONFIG_HOME')
317 if xdg_config_home:
318 userConfFile = os.path.join(xdg_config_home, 'youtube-dl.conf')
319 else:
320 userConfFile = os.path.join(os.path.expanduser('~'), '.config', 'youtube-dl.conf')
321 systemConf = _readOptions('/etc/youtube-dl.conf')
322 userConf = _readOptions(userConfFile)
323 commandLineConf = sys.argv[1:]
324 argv = systemConf + userConf + commandLineConf
325 opts, args = parser.parse_args(argv)
c76cb6d5
PH
326 if opts.verbose:
327 print(u'[debug] System config: ' + repr(systemConf))
328 print(u'[debug] User config: ' + repr(userConf))
329 print(u'[debug] Command-line args: ' + repr(commandLineConf))
8c42c506 330
59ae15a5 331 return parser, opts, args
235b3ba4 332
b8ad4f02
FP
333def _real_main(argv=None):
334 parser, opts, args = parseOpts(argv)
59ae15a5
PH
335
336 # Open appropriate CookieJar
337 if opts.cookiefile is None:
338 jar = compat_cookiejar.CookieJar()
339 else:
340 try:
341 jar = compat_cookiejar.MozillaCookieJar(opts.cookiefile)
229cac75 342 if os.access(opts.cookiefile, os.R_OK):
59ae15a5
PH
343 jar.load()
344 except (IOError, OSError) as err:
229cac75
PH
345 if opts.verbose:
346 traceback.print_exc()
347 sys.stderr.write(u'ERROR: unable to open cookie file\n')
348 sys.exit(101)
59ae15a5
PH
349 # Set user agent
350 if opts.user_agent is not None:
351 std_headers['User-Agent'] = opts.user_agent
28535652
BH
352
353 # Set referer
354 if opts.referer is not None:
355 std_headers['Referer'] = opts.referer
59ae15a5
PH
356
357 # Dump user agent
358 if opts.dump_user_agent:
359 print(std_headers['User-Agent'])
360 sys.exit(0)
361
362 # Batch file verification
363 batchurls = []
364 if opts.batchfile is not None:
365 try:
366 if opts.batchfile == '-':
367 batchfd = sys.stdin
368 else:
369 batchfd = open(opts.batchfile, 'r')
370 batchurls = batchfd.readlines()
371 batchurls = [x.strip() for x in batchurls]
372 batchurls = [x for x in batchurls if len(x) > 0 and not re.search(r'^[#/;]', x)]
373 except IOError:
374 sys.exit(u'ERROR: batch file could not be read')
375 all_urls = batchurls + args
376 all_urls = [url.strip() for url in all_urls]
377
378 # General configuration
379 cookie_processor = compat_urllib_request.HTTPCookieProcessor(jar)
5fb16555
PH
380 if opts.proxy:
381 proxies = {'http': opts.proxy, 'https': opts.proxy}
382 else:
383 proxies = compat_urllib_request.getproxies()
384 # Set HTTPS proxy to HTTP one if given (https://github.com/rg3/youtube-dl/issues/805)
385 if 'http' in proxies and 'https' not in proxies:
386 proxies['https'] = proxies['http']
434aca5b 387 proxy_handler = compat_urllib_request.ProxyHandler(proxies)
59ae15a5
PH
388 opener = compat_urllib_request.build_opener(proxy_handler, cookie_processor, YoutubeDLHandler())
389 compat_urllib_request.install_opener(opener)
390 socket.setdefaulttimeout(300) # 5 minutes should be enough (famous last words)
391
392 extractors = gen_extractors()
393
394 if opts.list_extractors:
395 for ie in extractors:
b08e09c3 396 print(ie.IE_NAME + (' (CURRENTLY BROKEN)' if not ie._WORKING else ''))
1a2c3c0f
FV
397 matchedUrls = [url for url in all_urls if ie.suitable(url)]
398 all_urls = [url for url in all_urls if url not in matchedUrls]
59ae15a5
PH
399 for mu in matchedUrls:
400 print(u' ' + mu)
401 sys.exit(0)
402
403 # Conflicting, missing and erroneous options
404 if opts.usenetrc and (opts.username is not None or opts.password is not None):
405 parser.error(u'using .netrc conflicts with giving username/password')
406 if opts.password is not None and opts.username is None:
407 parser.error(u'account username missing')
408 if opts.outtmpl is not None and (opts.usetitle or opts.autonumber or opts.useid):
409 parser.error(u'using output template conflicts with using title, video ID or auto number')
410 if opts.usetitle and opts.useid:
411 parser.error(u'using title conflicts with using video ID')
412 if opts.username is not None and opts.password is None:
413 opts.password = getpass.getpass(u'Type account password and press return:')
414 if opts.ratelimit is not None:
415 numeric_limit = FileDownloader.parse_bytes(opts.ratelimit)
416 if numeric_limit is None:
417 parser.error(u'invalid rate limit specified')
418 opts.ratelimit = numeric_limit
9e982f9e
JC
419 if opts.min_filesize is not None:
420 numeric_limit = FileDownloader.parse_bytes(opts.min_filesize)
421 if numeric_limit is None:
422 parser.error(u'invalid min_filesize specified')
423 opts.min_filesize = numeric_limit
424 if opts.max_filesize is not None:
425 numeric_limit = FileDownloader.parse_bytes(opts.max_filesize)
426 if numeric_limit is None:
427 parser.error(u'invalid max_filesize specified')
428 opts.max_filesize = numeric_limit
59ae15a5
PH
429 if opts.retries is not None:
430 try:
431 opts.retries = int(opts.retries)
432 except (TypeError, ValueError) as err:
433 parser.error(u'invalid retry count specified')
434 if opts.buffersize is not None:
435 numeric_buffersize = FileDownloader.parse_bytes(opts.buffersize)
436 if numeric_buffersize is None:
437 parser.error(u'invalid buffer size specified')
438 opts.buffersize = numeric_buffersize
439 try:
440 opts.playliststart = int(opts.playliststart)
441 if opts.playliststart <= 0:
442 raise ValueError(u'Playlist start must be positive')
443 except (TypeError, ValueError) as err:
444 parser.error(u'invalid playlist start number specified')
445 try:
446 opts.playlistend = int(opts.playlistend)
447 if opts.playlistend != -1 and (opts.playlistend <= 0 or opts.playlistend < opts.playliststart):
448 raise ValueError(u'Playlist end must be greater than playlist start')
449 except (TypeError, ValueError) as err:
450 parser.error(u'invalid playlist end number specified')
451 if opts.extractaudio:
510e6f6d 452 if opts.audioformat not in ['best', 'aac', 'mp3', 'm4a', 'opus', 'vorbis', 'wav']:
59ae15a5
PH
453 parser.error(u'invalid audio format specified')
454 if opts.audioquality:
455 opts.audioquality = opts.audioquality.strip('k').strip('K')
456 if not opts.audioquality.isdigit():
457 parser.error(u'invalid audio quality specified')
7851b379
PH
458 if opts.recodevideo is not None:
459 if opts.recodevideo not in ['mp4', 'flv', 'webm', 'ogg']:
460 parser.error(u'invalid video recode format specified')
bd558525
JMF
461 if opts.date is not None:
462 date = DateRange.day(opts.date)
463 else:
464 date = DateRange(opts.dateafter, opts.datebefore)
59ae15a5 465
5cb9c312
PH
466 if sys.version_info < (3,):
467 # In Python 2, sys.argv is a bytestring (also note http://bugs.python.org/issue2128 for Windows systems)
0be41ec2
PH
468 if opts.outtmpl is not None:
469 opts.outtmpl = opts.outtmpl.decode(preferredencoding())
5cb9c312
PH
470 outtmpl =((opts.outtmpl is not None and opts.outtmpl)
471 or (opts.format == '-1' and opts.usetitle and u'%(title)s-%(id)s-%(format)s.%(ext)s')
472 or (opts.format == '-1' and u'%(id)s-%(format)s.%(ext)s')
473 or (opts.usetitle and opts.autonumber and u'%(autonumber)s-%(title)s-%(id)s.%(ext)s')
474 or (opts.usetitle and u'%(title)s-%(id)s.%(ext)s')
475 or (opts.useid and u'%(id)s.%(ext)s')
476 or (opts.autonumber and u'%(autonumber)s-%(id)s.%(ext)s')
08b2ac74 477 or u'%(title)s-%(id)s.%(ext)s')
8271226a 478
59ae15a5
PH
479 # File downloader
480 fd = FileDownloader({
481 'usenetrc': opts.usenetrc,
482 'username': opts.username,
483 'password': opts.password,
484 'quiet': (opts.quiet or opts.geturl or opts.gettitle or opts.getthumbnail or opts.getdescription or opts.getfilename or opts.getformat),
485 'forceurl': opts.geturl,
486 'forcetitle': opts.gettitle,
487 'forcethumbnail': opts.getthumbnail,
488 'forcedescription': opts.getdescription,
489 'forcefilename': opts.getfilename,
490 'forceformat': opts.getformat,
491 'simulate': opts.simulate,
492 '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),
493 'format': opts.format,
494 'format_limit': opts.format_limit,
495 'listformats': opts.listformats,
5cb9c312 496 'outtmpl': outtmpl,
213c31ae 497 'autonumber_size': opts.autonumber_size,
59ae15a5
PH
498 'restrictfilenames': opts.restrictfilenames,
499 'ignoreerrors': opts.ignoreerrors,
500 'ratelimit': opts.ratelimit,
501 'nooverwrites': opts.nooverwrites,
502 'retries': opts.retries,
503 'buffersize': opts.buffersize,
504 'noresizebuffer': opts.noresizebuffer,
505 'continuedl': opts.continue_dl,
506 'noprogress': opts.noprogress,
5717d91a 507 'progress_with_newline': opts.progress_with_newline,
59ae15a5
PH
508 'playliststart': opts.playliststart,
509 'playlistend': opts.playlistend,
510 'logtostderr': opts.outtmpl == '-',
511 'consoletitle': opts.consoletitle,
512 'nopart': opts.nopart,
513 'updatetime': opts.updatetime,
514 'writedescription': opts.writedescription,
515 'writeinfojson': opts.writeinfojson,
516 'writesubtitles': opts.writesubtitles,
cdb130b0 517 'onlysubtitles': opts.onlysubtitles,
ae608b80 518 'allsubtitles': opts.allsubtitles,
2a4093ea 519 'listsubtitles': opts.listsubtitles,
9e62bc44 520 'subtitlesformat': opts.subtitlesformat,
59ae15a5 521 'subtitleslang': opts.subtitleslang,
8271226a
PH
522 'matchtitle': decodeOption(opts.matchtitle),
523 'rejecttitle': decodeOption(opts.rejecttitle),
59ae15a5
PH
524 'max_downloads': opts.max_downloads,
525 'prefer_free_formats': opts.prefer_free_formats,
526 'verbose': opts.verbose,
855703e5 527 'dump_intermediate_pages': opts.dump_intermediate_pages,
8d5d3a5d 528 'test': opts.test,
7851b379 529 'keepvideo': opts.keepvideo,
9e982f9e 530 'min_filesize': opts.min_filesize,
bd558525
JMF
531 'max_filesize': opts.max_filesize,
532 'daterange': date
59ae15a5
PH
533 })
534
535 if opts.verbose:
f427df17 536 fd.to_screen(u'[debug] youtube-dl version ' + __version__)
4e38899e 537 try:
f427df17
FV
538 sp = subprocess.Popen(['git', 'rev-parse', '--short', 'HEAD'], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
539 cwd=os.path.dirname(os.path.abspath(__file__)))
4e38899e
FV
540 out, err = sp.communicate()
541 out = out.decode().strip()
542 if re.match('[0-9a-f]+', out):
543 fd.to_screen(u'[debug] Git HEAD: ' + out)
544 except:
545 pass
546 fd.to_screen(u'[debug] Python version %s - %s' %(platform.python_version(), platform.platform()))
59ae15a5
PH
547 fd.to_screen(u'[debug] Proxy map: ' + str(proxy_handler.proxies))
548
549 for extractor in extractors:
550 fd.add_info_extractor(extractor)
551
552 # PostProcessors
553 if opts.extractaudio:
7851b379
PH
554 fd.add_post_processor(FFmpegExtractAudioPP(preferredcodec=opts.audioformat, preferredquality=opts.audioquality, nopostoverwrites=opts.nopostoverwrites))
555 if opts.recodevideo:
556 fd.add_post_processor(FFmpegVideoConvertor(preferedformat=opts.recodevideo))
59ae15a5 557
67353612
PH
558 # Update version
559 if opts.update_self:
560 update_self(fd.to_screen, opts.verbose, sys.argv[0])
561
59ae15a5
PH
562 # Maybe do nothing
563 if len(all_urls) < 1:
564 if not opts.update_self:
565 parser.error(u'you must provide at least one URL')
566 else:
567 sys.exit()
568
569 try:
570 retcode = fd.download(all_urls)
571 except MaxDownloadsReached:
572 fd.to_screen(u'--max-download limit reached, aborting.')
573 retcode = 101
574
575 # Dump cookie jar if requested
576 if opts.cookiefile is not None:
577 try:
578 jar.save()
579 except (IOError, OSError) as err:
580 sys.exit(u'ERROR: unable to save cookie jar')
581
582 sys.exit(retcode)
235b3ba4 583
b8ad4f02 584def main(argv=None):
59ae15a5 585 try:
b8ad4f02 586 _real_main(argv)
59ae15a5
PH
587 except DownloadError:
588 sys.exit(1)
589 except SameFileError:
590 sys.exit(u'ERROR: fixed output name but more than one file to download')
591 except KeyboardInterrupt:
592 sys.exit(u'\nERROR: Interrupted by user')