]> jfr.im git - yt-dlp.git/blob - youtube_dl/__init__.py
Move the opener to the YoutubeDL object.
[yt-dlp.git] / youtube_dl / __init__.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 __authors__ = (
5 'Ricardo Garcia Gonzalez',
6 'Danny Colligan',
7 'Benjamin Johnson',
8 'Vasyl\' Vavrychuk',
9 'Witold Baryluk',
10 'Paweł Paprota',
11 'Gergely Imreh',
12 'Rogério Brito',
13 'Philipp Hagemeister',
14 'Sören Schulze',
15 'Kevin Ngo',
16 'Ori Avtalion',
17 'shizeeg',
18 'Filippo Valsorda',
19 'Christian Albrecht',
20 'Dave Vasilevsky',
21 'Jaime Marquínez Ferrándiz',
22 'Jeff Crouse',
23 'Osama Khalid',
24 'Michael Walter',
25 'M. Yasoob Ullah Khalid',
26 'Julien Fraichard',
27 'Johny Mo Swag',
28 'Axel Noack',
29 'Albert Kim',
30 'Pierre Rudloff',
31 'Huarong Huo',
32 'Ismael Mejía',
33 'Steffan \'Ruirize\' James',
34 'Andras Elso',
35 'Jelle van der Waa',
36 'Marcin Cieślak',
37 'Anton Larionov',
38 )
39
40 __license__ = 'Public Domain'
41
42 import codecs
43 import getpass
44 import optparse
45 import os
46 import random
47 import re
48 import shlex
49 import subprocess
50 import sys
51
52
53 from .utils import (
54 compat_print,
55 DateRange,
56 decodeOption,
57 determine_ext,
58 DownloadError,
59 get_cachedir,
60 MaxDownloadsReached,
61 preferredencoding,
62 SameFileError,
63 std_headers,
64 write_string,
65 )
66 from .update import update_self
67 from .FileDownloader import (
68 FileDownloader,
69 )
70 from .extractor import gen_extractors
71 from .version import __version__
72 from .YoutubeDL import YoutubeDL
73 from .PostProcessor import (
74 FFmpegMetadataPP,
75 FFmpegVideoConvertor,
76 FFmpegExtractAudioPP,
77 FFmpegEmbedSubtitlePP,
78 )
79
80
81 def parseOpts(overrideArguments=None):
82 def _readOptions(filename_bytes):
83 try:
84 optionf = open(filename_bytes)
85 except IOError:
86 return [] # silently skip if file is not present
87 try:
88 res = []
89 for l in optionf:
90 res += shlex.split(l, comments=True)
91 finally:
92 optionf.close()
93 return res
94
95 def _format_option_string(option):
96 ''' ('-o', '--option') -> -o, --format METAVAR'''
97
98 opts = []
99
100 if option._short_opts:
101 opts.append(option._short_opts[0])
102 if option._long_opts:
103 opts.append(option._long_opts[0])
104 if len(opts) > 1:
105 opts.insert(1, ', ')
106
107 if option.takes_value(): opts.append(' %s' % option.metavar)
108
109 return "".join(opts)
110
111 def _comma_separated_values_options_callback(option, opt_str, value, parser):
112 setattr(parser.values, option.dest, value.split(','))
113
114 def _find_term_columns():
115 columns = os.environ.get('COLUMNS', None)
116 if columns:
117 return int(columns)
118
119 try:
120 sp = subprocess.Popen(['stty', 'size'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
121 out,err = sp.communicate()
122 return int(out.split()[1])
123 except:
124 pass
125 return None
126
127 def _hide_login_info(opts):
128 opts = list(opts)
129 for private_opt in ['-p', '--password', '-u', '--username', '--video-password']:
130 try:
131 i = opts.index(private_opt)
132 opts[i+1] = '<PRIVATE>'
133 except ValueError:
134 pass
135 return opts
136
137 max_width = 80
138 max_help_position = 80
139
140 # No need to wrap help messages if we're on a wide console
141 columns = _find_term_columns()
142 if columns: max_width = columns
143
144 fmt = optparse.IndentedHelpFormatter(width=max_width, max_help_position=max_help_position)
145 fmt.format_option_strings = _format_option_string
146
147 kw = {
148 'version' : __version__,
149 'formatter' : fmt,
150 'usage' : '%prog [options] url [url...]',
151 'conflict_handler' : 'resolve',
152 }
153
154 parser = optparse.OptionParser(**kw)
155
156 # option groups
157 general = optparse.OptionGroup(parser, 'General Options')
158 selection = optparse.OptionGroup(parser, 'Video Selection')
159 authentication = optparse.OptionGroup(parser, 'Authentication Options')
160 video_format = optparse.OptionGroup(parser, 'Video Format Options')
161 subtitles = optparse.OptionGroup(parser, 'Subtitle Options')
162 downloader = optparse.OptionGroup(parser, 'Download Options')
163 postproc = optparse.OptionGroup(parser, 'Post-processing Options')
164 filesystem = optparse.OptionGroup(parser, 'Filesystem Options')
165 verbosity = optparse.OptionGroup(parser, 'Verbosity / Simulation Options')
166
167 general.add_option('-h', '--help',
168 action='help', help='print this help text and exit')
169 general.add_option('-v', '--version',
170 action='version', help='print program version and exit')
171 general.add_option('-U', '--update',
172 action='store_true', dest='update_self', help='update this program to latest version. Make sure that you have sufficient permissions (run with sudo if needed)')
173 general.add_option('-i', '--ignore-errors',
174 action='store_true', dest='ignoreerrors', help='continue on download errors, for example to to skip unavailable videos in a playlist', default=False)
175 general.add_option('--abort-on-error',
176 action='store_false', dest='ignoreerrors',
177 help='Abort downloading of further videos (in the playlist or the command line) if an error occurs')
178 general.add_option('--dump-user-agent',
179 action='store_true', dest='dump_user_agent',
180 help='display the current browser identification', default=False)
181 general.add_option('--user-agent',
182 dest='user_agent', help='specify a custom user agent', metavar='UA')
183 general.add_option('--referer',
184 dest='referer', help='specify a custom referer, use if the video access is restricted to one domain',
185 metavar='REF', default=None)
186 general.add_option('--list-extractors',
187 action='store_true', dest='list_extractors',
188 help='List all supported extractors and the URLs they would handle', default=False)
189 general.add_option('--extractor-descriptions',
190 action='store_true', dest='list_extractor_descriptions',
191 help='Output descriptions of all supported extractors', default=False)
192 general.add_option('--proxy', dest='proxy', default=None, help='Use the specified HTTP/HTTPS proxy', metavar='URL')
193 general.add_option('--no-check-certificate', action='store_true', dest='no_check_certificate', default=False, help='Suppress HTTPS certificate validation.')
194 general.add_option(
195 '--cache-dir', dest='cachedir', default=get_cachedir(), metavar='DIR',
196 help='Location in the filesystem where youtube-dl can store downloaded information permanently. By default $XDG_CACHE_HOME/youtube-dl or ~/.cache/youtube-dl .')
197 general.add_option(
198 '--no-cache-dir', action='store_const', const=None, dest='cachedir',
199 help='Disable filesystem caching')
200
201
202 selection.add_option('--playlist-start',
203 dest='playliststart', metavar='NUMBER', help='playlist video to start at (default is %default)', default=1)
204 selection.add_option('--playlist-end',
205 dest='playlistend', metavar='NUMBER', help='playlist video to end at (default is last)', default=-1)
206 selection.add_option('--match-title', dest='matchtitle', metavar='REGEX',help='download only matching titles (regex or caseless sub-string)')
207 selection.add_option('--reject-title', dest='rejecttitle', metavar='REGEX',help='skip download for matching titles (regex or caseless sub-string)')
208 selection.add_option('--max-downloads', metavar='NUMBER', dest='max_downloads', help='Abort after downloading NUMBER files', default=None)
209 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)
210 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)
211 selection.add_option('--date', metavar='DATE', dest='date', help='download only videos uploaded in this date', default=None)
212 selection.add_option('--datebefore', metavar='DATE', dest='datebefore', help='download only videos uploaded before this date', default=None)
213 selection.add_option('--dateafter', metavar='DATE', dest='dateafter', help='download only videos uploaded after this date', default=None)
214 selection.add_option('--no-playlist', action='store_true', dest='noplaylist', help='download only the currently playing video', default=False)
215 selection.add_option('--age-limit', metavar='YEARS', dest='age_limit',
216 help='download only videos suitable for the given age',
217 default=None, type=int)
218 selection.add_option('--download-archive', metavar='FILE',
219 dest='download_archive',
220 help='Download only videos not present in the archive file. Record all downloaded videos in it.')
221
222
223 authentication.add_option('-u', '--username',
224 dest='username', metavar='USERNAME', help='account username')
225 authentication.add_option('-p', '--password',
226 dest='password', metavar='PASSWORD', help='account password')
227 authentication.add_option('-n', '--netrc',
228 action='store_true', dest='usenetrc', help='use .netrc authentication data', default=False)
229 authentication.add_option('--video-password',
230 dest='videopassword', metavar='PASSWORD', help='video password (vimeo only)')
231
232
233 video_format.add_option('-f', '--format',
234 action='store', dest='format', metavar='FORMAT', default='best',
235 help='video format code, specifiy the order of preference using slashes: "-f 22/17/18". "-f mp4" and "-f flv" are also supported')
236 video_format.add_option('--all-formats',
237 action='store_const', dest='format', help='download all available video formats', const='all')
238 video_format.add_option('--prefer-free-formats',
239 action='store_true', dest='prefer_free_formats', default=False, help='prefer free video formats unless a specific one is requested')
240 video_format.add_option('--max-quality',
241 action='store', dest='format_limit', metavar='FORMAT', help='highest quality format to download')
242 video_format.add_option('-F', '--list-formats',
243 action='store_true', dest='listformats', help='list all available formats (currently youtube only)')
244
245 subtitles.add_option('--write-sub', '--write-srt',
246 action='store_true', dest='writesubtitles',
247 help='write subtitle file', default=False)
248 subtitles.add_option('--write-auto-sub', '--write-automatic-sub',
249 action='store_true', dest='writeautomaticsub',
250 help='write automatic subtitle file (youtube only)', default=False)
251 subtitles.add_option('--all-subs',
252 action='store_true', dest='allsubtitles',
253 help='downloads all the available subtitles of the video', default=False)
254 subtitles.add_option('--list-subs',
255 action='store_true', dest='listsubtitles',
256 help='lists all available subtitles for the video', default=False)
257 subtitles.add_option('--sub-format',
258 action='store', dest='subtitlesformat', metavar='FORMAT',
259 help='subtitle format (default=srt) ([sbv/vtt] youtube only)', default='srt')
260 subtitles.add_option('--sub-lang', '--sub-langs', '--srt-lang',
261 action='callback', dest='subtitleslangs', metavar='LANGS', type='str',
262 default=[], callback=_comma_separated_values_options_callback,
263 help='languages of the subtitles to download (optional) separated by commas, use IETF language tags like \'en,pt\'')
264
265 downloader.add_option('-r', '--rate-limit',
266 dest='ratelimit', metavar='LIMIT', help='maximum download rate in bytes per second (e.g. 50K or 4.2M)')
267 downloader.add_option('-R', '--retries',
268 dest='retries', metavar='RETRIES', help='number of retries (default is %default)', default=10)
269 downloader.add_option('--buffer-size',
270 dest='buffersize', metavar='SIZE', help='size of download buffer (e.g. 1024 or 16K) (default is %default)', default="1024")
271 downloader.add_option('--no-resize-buffer',
272 action='store_true', dest='noresizebuffer',
273 help='do not automatically adjust the buffer size. By default, the buffer size is automatically resized from an initial value of SIZE.', default=False)
274 downloader.add_option('--test', action='store_true', dest='test', default=False, help=optparse.SUPPRESS_HELP)
275
276 verbosity.add_option('-q', '--quiet',
277 action='store_true', dest='quiet', help='activates quiet mode', default=False)
278 verbosity.add_option('-s', '--simulate',
279 action='store_true', dest='simulate', help='do not download the video and do not write anything to disk', default=False)
280 verbosity.add_option('--skip-download',
281 action='store_true', dest='skip_download', help='do not download the video', default=False)
282 verbosity.add_option('-g', '--get-url',
283 action='store_true', dest='geturl', help='simulate, quiet but print URL', default=False)
284 verbosity.add_option('-e', '--get-title',
285 action='store_true', dest='gettitle', help='simulate, quiet but print title', default=False)
286 verbosity.add_option('--get-id',
287 action='store_true', dest='getid', help='simulate, quiet but print id', default=False)
288 verbosity.add_option('--get-thumbnail',
289 action='store_true', dest='getthumbnail',
290 help='simulate, quiet but print thumbnail URL', default=False)
291 verbosity.add_option('--get-description',
292 action='store_true', dest='getdescription',
293 help='simulate, quiet but print video description', default=False)
294 verbosity.add_option('--get-filename',
295 action='store_true', dest='getfilename',
296 help='simulate, quiet but print output filename', default=False)
297 verbosity.add_option('--get-format',
298 action='store_true', dest='getformat',
299 help='simulate, quiet but print output format', default=False)
300 verbosity.add_option('-j', '--dump-json',
301 action='store_true', dest='dumpjson',
302 help='simulate, quiet but print JSON information', default=False)
303 verbosity.add_option('--newline',
304 action='store_true', dest='progress_with_newline', help='output progress bar as new lines', default=False)
305 verbosity.add_option('--no-progress',
306 action='store_true', dest='noprogress', help='do not print progress bar', default=False)
307 verbosity.add_option('--console-title',
308 action='store_true', dest='consoletitle',
309 help='display progress in console titlebar', default=False)
310 verbosity.add_option('-v', '--verbose',
311 action='store_true', dest='verbose', help='print various debugging information', default=False)
312 verbosity.add_option('--dump-intermediate-pages',
313 action='store_true', dest='dump_intermediate_pages', default=False,
314 help='print downloaded pages to debug problems(very verbose)')
315 verbosity.add_option('--write-pages',
316 action='store_true', dest='write_pages', default=False,
317 help='Write downloaded pages to files in the current directory')
318 verbosity.add_option('--youtube-print-sig-code',
319 action='store_true', dest='youtube_print_sig_code', default=False,
320 help=optparse.SUPPRESS_HELP)
321
322
323 filesystem.add_option('-t', '--title',
324 action='store_true', dest='usetitle', help='use title in file name (default)', default=False)
325 filesystem.add_option('--id',
326 action='store_true', dest='useid', help='use only video ID in file name', default=False)
327 filesystem.add_option('-l', '--literal',
328 action='store_true', dest='usetitle', help='[deprecated] alias of --title', default=False)
329 filesystem.add_option('-A', '--auto-number',
330 action='store_true', dest='autonumber',
331 help='number downloaded files starting from 00000', default=False)
332 filesystem.add_option('-o', '--output',
333 dest='outtmpl', metavar='TEMPLATE',
334 help=('output filename template. Use %(title)s to get the title, '
335 '%(uploader)s for the uploader name, %(uploader_id)s for the uploader nickname if different, '
336 '%(autonumber)s to get an automatically incremented number, '
337 '%(ext)s for the filename extension, '
338 '%(format)s for the format description (like "22 - 1280x720" or "HD"),'
339 '%(format_id)s for the unique id of the format (like Youtube\'s itags: "137"),'
340 '%(upload_date)s for the upload date (YYYYMMDD), '
341 '%(extractor)s for the provider (youtube, metacafe, etc), '
342 '%(id)s for the video id , %(playlist)s for the playlist the video is in, '
343 '%(playlist_index)s for the position in the playlist and %% for a literal percent. '
344 'Use - to output to stdout. Can also be used to download to a different directory, '
345 'for example with -o \'/my/downloads/%(uploader)s/%(title)s-%(id)s.%(ext)s\' .'))
346 filesystem.add_option('--autonumber-size',
347 dest='autonumber_size', metavar='NUMBER',
348 help='Specifies the number of digits in %(autonumber)s when it is present in output filename template or --auto-number option is given')
349 filesystem.add_option('--restrict-filenames',
350 action='store_true', dest='restrictfilenames',
351 help='Restrict filenames to only ASCII characters, and avoid "&" and spaces in filenames', default=False)
352 filesystem.add_option('-a', '--batch-file',
353 dest='batchfile', metavar='FILE', help='file containing URLs to download (\'-\' for stdin)')
354 filesystem.add_option('-w', '--no-overwrites',
355 action='store_true', dest='nooverwrites', help='do not overwrite files', default=False)
356 filesystem.add_option('-c', '--continue',
357 action='store_true', dest='continue_dl', help='force resume of partially downloaded files. By default, youtube-dl will resume downloads if possible.', default=True)
358 filesystem.add_option('--no-continue',
359 action='store_false', dest='continue_dl',
360 help='do not resume partially downloaded files (restart from beginning)')
361 filesystem.add_option('--cookies',
362 dest='cookiefile', metavar='FILE', help='file to read cookies from and dump cookie jar in')
363 filesystem.add_option('--no-part',
364 action='store_true', dest='nopart', help='do not use .part files', default=False)
365 filesystem.add_option('--no-mtime',
366 action='store_false', dest='updatetime',
367 help='do not use the Last-modified header to set the file modification time', default=True)
368 filesystem.add_option('--write-description',
369 action='store_true', dest='writedescription',
370 help='write video description to a .description file', default=False)
371 filesystem.add_option('--write-info-json',
372 action='store_true', dest='writeinfojson',
373 help='write video metadata to a .info.json file', default=False)
374 filesystem.add_option('--write-annotations',
375 action='store_true', dest='writeannotations',
376 help='write video annotations to a .annotation file', default=False)
377 filesystem.add_option('--write-thumbnail',
378 action='store_true', dest='writethumbnail',
379 help='write thumbnail image to disk', default=False)
380
381
382 postproc.add_option('-x', '--extract-audio', action='store_true', dest='extractaudio', default=False,
383 help='convert video files to audio-only files (requires ffmpeg or avconv and ffprobe or avprobe)')
384 postproc.add_option('--audio-format', metavar='FORMAT', dest='audioformat', default='best',
385 help='"best", "aac", "vorbis", "mp3", "m4a", "opus", or "wav"; best by default')
386 postproc.add_option('--audio-quality', metavar='QUALITY', dest='audioquality', default='5',
387 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)')
388 postproc.add_option('--recode-video', metavar='FORMAT', dest='recodevideo', default=None,
389 help='Encode the video to another format if necessary (currently supported: mp4|flv|ogg|webm)')
390 postproc.add_option('-k', '--keep-video', action='store_true', dest='keepvideo', default=False,
391 help='keeps the video file on disk after the post-processing; the video is erased by default')
392 postproc.add_option('--no-post-overwrites', action='store_true', dest='nopostoverwrites', default=False,
393 help='do not overwrite post-processed files; the post-processed files are overwritten by default')
394 postproc.add_option('--embed-subs', action='store_true', dest='embedsubtitles', default=False,
395 help='embed subtitles in the video (only for mp4 videos)')
396 postproc.add_option('--add-metadata', action='store_true', dest='addmetadata', default=False,
397 help='add metadata to the files')
398
399
400 parser.add_option_group(general)
401 parser.add_option_group(selection)
402 parser.add_option_group(downloader)
403 parser.add_option_group(filesystem)
404 parser.add_option_group(verbosity)
405 parser.add_option_group(video_format)
406 parser.add_option_group(subtitles)
407 parser.add_option_group(authentication)
408 parser.add_option_group(postproc)
409
410 if overrideArguments is not None:
411 opts, args = parser.parse_args(overrideArguments)
412 if opts.verbose:
413 write_string(u'[debug] Override config: ' + repr(overrideArguments) + '\n')
414 else:
415 xdg_config_home = os.environ.get('XDG_CONFIG_HOME')
416 if xdg_config_home:
417 userConfFile = os.path.join(xdg_config_home, 'youtube-dl', 'config')
418 if not os.path.isfile(userConfFile):
419 userConfFile = os.path.join(xdg_config_home, 'youtube-dl.conf')
420 else:
421 userConfFile = os.path.join(os.path.expanduser('~'), '.config', 'youtube-dl', 'config')
422 if not os.path.isfile(userConfFile):
423 userConfFile = os.path.join(os.path.expanduser('~'), '.config', 'youtube-dl.conf')
424 systemConf = _readOptions('/etc/youtube-dl.conf')
425 userConf = _readOptions(userConfFile)
426 commandLineConf = sys.argv[1:]
427 argv = systemConf + userConf + commandLineConf
428 opts, args = parser.parse_args(argv)
429 if opts.verbose:
430 write_string(u'[debug] System config: ' + repr(_hide_login_info(systemConf)) + '\n')
431 write_string(u'[debug] User config: ' + repr(_hide_login_info(userConf)) + '\n')
432 write_string(u'[debug] Command-line args: ' + repr(_hide_login_info(commandLineConf)) + '\n')
433
434 return parser, opts, args
435
436 def _real_main(argv=None):
437 # Compatibility fixes for Windows
438 if sys.platform == 'win32':
439 # https://github.com/rg3/youtube-dl/issues/820
440 codecs.register(lambda name: codecs.lookup('utf-8') if name == 'cp65001' else None)
441
442 parser, opts, args = parseOpts(argv)
443
444 # Set user agent
445 if opts.user_agent is not None:
446 std_headers['User-Agent'] = opts.user_agent
447
448 # Set referer
449 if opts.referer is not None:
450 std_headers['Referer'] = opts.referer
451
452 # Dump user agent
453 if opts.dump_user_agent:
454 compat_print(std_headers['User-Agent'])
455 sys.exit(0)
456
457 # Batch file verification
458 batchurls = []
459 if opts.batchfile is not None:
460 try:
461 if opts.batchfile == '-':
462 batchfd = sys.stdin
463 else:
464 batchfd = open(opts.batchfile, 'r')
465 batchurls = batchfd.readlines()
466 batchurls = [x.strip() for x in batchurls]
467 batchurls = [x for x in batchurls if len(x) > 0 and not re.search(r'^[#/;]', x)]
468 if opts.verbose:
469 write_string(u'[debug] Batch file urls: ' + repr(batchurls) + u'\n')
470 except IOError:
471 sys.exit(u'ERROR: batch file could not be read')
472 all_urls = batchurls + args
473 all_urls = [url.strip() for url in all_urls]
474
475 extractors = gen_extractors()
476
477 if opts.list_extractors:
478 for ie in sorted(extractors, key=lambda ie: ie.IE_NAME.lower()):
479 compat_print(ie.IE_NAME + (' (CURRENTLY BROKEN)' if not ie._WORKING else ''))
480 matchedUrls = [url for url in all_urls if ie.suitable(url)]
481 all_urls = [url for url in all_urls if url not in matchedUrls]
482 for mu in matchedUrls:
483 compat_print(u' ' + mu)
484 sys.exit(0)
485 if opts.list_extractor_descriptions:
486 for ie in sorted(extractors, key=lambda ie: ie.IE_NAME.lower()):
487 if not ie._WORKING:
488 continue
489 desc = getattr(ie, 'IE_DESC', ie.IE_NAME)
490 if desc is False:
491 continue
492 if hasattr(ie, 'SEARCH_KEY'):
493 _SEARCHES = (u'cute kittens', u'slithering pythons', u'falling cat', u'angry poodle', u'purple fish', u'running tortoise')
494 _COUNTS = (u'', u'5', u'10', u'all')
495 desc += u' (Example: "%s%s:%s" )' % (ie.SEARCH_KEY, random.choice(_COUNTS), random.choice(_SEARCHES))
496 compat_print(desc)
497 sys.exit(0)
498
499
500 # Conflicting, missing and erroneous options
501 if opts.usenetrc and (opts.username is not None or opts.password is not None):
502 parser.error(u'using .netrc conflicts with giving username/password')
503 if opts.password is not None and opts.username is None:
504 parser.error(u' account username missing\n')
505 if opts.outtmpl is not None and (opts.usetitle or opts.autonumber or opts.useid):
506 parser.error(u'using output template conflicts with using title, video ID or auto number')
507 if opts.usetitle and opts.useid:
508 parser.error(u'using title conflicts with using video ID')
509 if opts.username is not None and opts.password is None:
510 opts.password = getpass.getpass(u'Type account password and press return:')
511 if opts.ratelimit is not None:
512 numeric_limit = FileDownloader.parse_bytes(opts.ratelimit)
513 if numeric_limit is None:
514 parser.error(u'invalid rate limit specified')
515 opts.ratelimit = numeric_limit
516 if opts.min_filesize is not None:
517 numeric_limit = FileDownloader.parse_bytes(opts.min_filesize)
518 if numeric_limit is None:
519 parser.error(u'invalid min_filesize specified')
520 opts.min_filesize = numeric_limit
521 if opts.max_filesize is not None:
522 numeric_limit = FileDownloader.parse_bytes(opts.max_filesize)
523 if numeric_limit is None:
524 parser.error(u'invalid max_filesize specified')
525 opts.max_filesize = numeric_limit
526 if opts.retries is not None:
527 try:
528 opts.retries = int(opts.retries)
529 except (TypeError, ValueError):
530 parser.error(u'invalid retry count specified')
531 if opts.buffersize is not None:
532 numeric_buffersize = FileDownloader.parse_bytes(opts.buffersize)
533 if numeric_buffersize is None:
534 parser.error(u'invalid buffer size specified')
535 opts.buffersize = numeric_buffersize
536 try:
537 opts.playliststart = int(opts.playliststart)
538 if opts.playliststart <= 0:
539 raise ValueError(u'Playlist start must be positive')
540 except (TypeError, ValueError):
541 parser.error(u'invalid playlist start number specified')
542 try:
543 opts.playlistend = int(opts.playlistend)
544 if opts.playlistend != -1 and (opts.playlistend <= 0 or opts.playlistend < opts.playliststart):
545 raise ValueError(u'Playlist end must be greater than playlist start')
546 except (TypeError, ValueError):
547 parser.error(u'invalid playlist end number specified')
548 if opts.extractaudio:
549 if opts.audioformat not in ['best', 'aac', 'mp3', 'm4a', 'opus', 'vorbis', 'wav']:
550 parser.error(u'invalid audio format specified')
551 if opts.audioquality:
552 opts.audioquality = opts.audioquality.strip('k').strip('K')
553 if not opts.audioquality.isdigit():
554 parser.error(u'invalid audio quality specified')
555 if opts.recodevideo is not None:
556 if opts.recodevideo not in ['mp4', 'flv', 'webm', 'ogg']:
557 parser.error(u'invalid video recode format specified')
558 if opts.date is not None:
559 date = DateRange.day(opts.date)
560 else:
561 date = DateRange(opts.dateafter, opts.datebefore)
562
563 # --all-sub automatically sets --write-sub if --write-auto-sub is not given
564 # this was the old behaviour if only --all-sub was given.
565 if opts.allsubtitles and (opts.writeautomaticsub == False):
566 opts.writesubtitles = True
567
568 if sys.version_info < (3,):
569 # In Python 2, sys.argv is a bytestring (also note http://bugs.python.org/issue2128 for Windows systems)
570 if opts.outtmpl is not None:
571 opts.outtmpl = opts.outtmpl.decode(preferredencoding())
572 outtmpl =((opts.outtmpl is not None and opts.outtmpl)
573 or (opts.format == '-1' and opts.usetitle and u'%(title)s-%(id)s-%(format)s.%(ext)s')
574 or (opts.format == '-1' and u'%(id)s-%(format)s.%(ext)s')
575 or (opts.usetitle and opts.autonumber and u'%(autonumber)s-%(title)s-%(id)s.%(ext)s')
576 or (opts.usetitle and u'%(title)s-%(id)s.%(ext)s')
577 or (opts.useid and u'%(id)s.%(ext)s')
578 or (opts.autonumber and u'%(autonumber)s-%(id)s.%(ext)s')
579 or u'%(title)s-%(id)s.%(ext)s')
580 if '%(ext)s' not in outtmpl and opts.extractaudio:
581 parser.error(u'Cannot download a video and extract audio into the same'
582 u' file! Use "%%(ext)s" instead of %r' %
583 determine_ext(outtmpl, u''))
584
585 ydl_opts = {
586 'usenetrc': opts.usenetrc,
587 'username': opts.username,
588 'password': opts.password,
589 'videopassword': opts.videopassword,
590 'quiet': (opts.quiet or opts.geturl or opts.gettitle or opts.getid or opts.getthumbnail or opts.getdescription or opts.getfilename or opts.getformat or opts.dumpjson),
591 'forceurl': opts.geturl,
592 'forcetitle': opts.gettitle,
593 'forceid': opts.getid,
594 'forcethumbnail': opts.getthumbnail,
595 'forcedescription': opts.getdescription,
596 'forcefilename': opts.getfilename,
597 'forceformat': opts.getformat,
598 'forcejson': opts.dumpjson,
599 'simulate': opts.simulate,
600 'skip_download': (opts.skip_download or opts.simulate or opts.geturl or opts.gettitle or opts.getid or opts.getthumbnail or opts.getdescription or opts.getfilename or opts.getformat or opts.dumpjson),
601 'format': opts.format,
602 'format_limit': opts.format_limit,
603 'listformats': opts.listformats,
604 'outtmpl': outtmpl,
605 'autonumber_size': opts.autonumber_size,
606 'restrictfilenames': opts.restrictfilenames,
607 'ignoreerrors': opts.ignoreerrors,
608 'ratelimit': opts.ratelimit,
609 'nooverwrites': opts.nooverwrites,
610 'retries': opts.retries,
611 'buffersize': opts.buffersize,
612 'noresizebuffer': opts.noresizebuffer,
613 'continuedl': opts.continue_dl,
614 'noprogress': opts.noprogress,
615 'progress_with_newline': opts.progress_with_newline,
616 'playliststart': opts.playliststart,
617 'playlistend': opts.playlistend,
618 'noplaylist': opts.noplaylist,
619 'logtostderr': opts.outtmpl == '-',
620 'consoletitle': opts.consoletitle,
621 'nopart': opts.nopart,
622 'updatetime': opts.updatetime,
623 'writedescription': opts.writedescription,
624 'writeannotations': opts.writeannotations,
625 'writeinfojson': opts.writeinfojson,
626 'writethumbnail': opts.writethumbnail,
627 'writesubtitles': opts.writesubtitles,
628 'writeautomaticsub': opts.writeautomaticsub,
629 'allsubtitles': opts.allsubtitles,
630 'listsubtitles': opts.listsubtitles,
631 'subtitlesformat': opts.subtitlesformat,
632 'subtitleslangs': opts.subtitleslangs,
633 'matchtitle': decodeOption(opts.matchtitle),
634 'rejecttitle': decodeOption(opts.rejecttitle),
635 'max_downloads': opts.max_downloads,
636 'prefer_free_formats': opts.prefer_free_formats,
637 'verbose': opts.verbose,
638 'dump_intermediate_pages': opts.dump_intermediate_pages,
639 'write_pages': opts.write_pages,
640 'test': opts.test,
641 'keepvideo': opts.keepvideo,
642 'min_filesize': opts.min_filesize,
643 'max_filesize': opts.max_filesize,
644 'daterange': date,
645 'cachedir': opts.cachedir,
646 'youtube_print_sig_code': opts.youtube_print_sig_code,
647 'age_limit': opts.age_limit,
648 'download_archive': opts.download_archive,
649 'cookiefile': opts.cookiefile,
650 'nocheckcertificate': opts.no_check_certificate,
651 }
652
653 with YoutubeDL(ydl_opts) as ydl:
654 ydl.print_debug_header()
655 ydl.add_default_info_extractors()
656
657 # PostProcessors
658 # Add the metadata pp first, the other pps will copy it
659 if opts.addmetadata:
660 ydl.add_post_processor(FFmpegMetadataPP())
661 if opts.extractaudio:
662 ydl.add_post_processor(FFmpegExtractAudioPP(preferredcodec=opts.audioformat, preferredquality=opts.audioquality, nopostoverwrites=opts.nopostoverwrites))
663 if opts.recodevideo:
664 ydl.add_post_processor(FFmpegVideoConvertor(preferedformat=opts.recodevideo))
665 if opts.embedsubtitles:
666 ydl.add_post_processor(FFmpegEmbedSubtitlePP(subtitlesformat=opts.subtitlesformat))
667
668 # Update version
669 if opts.update_self:
670 update_self(ydl.to_screen, opts.verbose)
671
672 # Maybe do nothing
673 if len(all_urls) < 1:
674 if not opts.update_self:
675 parser.error(u'you must provide at least one URL')
676 else:
677 sys.exit()
678
679 try:
680 retcode = ydl.download(all_urls)
681 except MaxDownloadsReached:
682 ydl.to_screen(u'--max-download limit reached, aborting.')
683 retcode = 101
684
685 sys.exit(retcode)
686
687
688 def main(argv=None):
689 try:
690 _real_main(argv)
691 except DownloadError:
692 sys.exit(1)
693 except SameFileError:
694 sys.exit(u'ERROR: fixed output name but more than one file to download')
695 except KeyboardInterrupt:
696 sys.exit(u'\nERROR: Interrupted by user')