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