]> jfr.im git - yt-dlp.git/blob - youtube_dl/__init__.py
Merge branch 'cliphunter' of https://github.com/pornophage/youtube-dl
[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 'Takuya Tsuchida',
39 'Sergey M.',
40 'Michael Orlitzky',
41 'Chris Gahan',
42 'Saimadhav Heblikar',
43 'Mike Col',
44 )
45
46 __license__ = 'Public Domain'
47
48 import codecs
49 import getpass
50 import locale
51 import optparse
52 import os
53 import random
54 import re
55 import shlex
56 import sys
57
58
59 from .utils import (
60 compat_print,
61 DateRange,
62 decodeOption,
63 get_term_width,
64 DownloadError,
65 get_cachedir,
66 MaxDownloadsReached,
67 preferredencoding,
68 SameFileError,
69 setproctitle,
70 std_headers,
71 write_string,
72 )
73 from .update import update_self
74 from .FileDownloader import (
75 FileDownloader,
76 )
77 from .extractor import gen_extractors
78 from .version import __version__
79 from .YoutubeDL import YoutubeDL
80 from .postprocessor import (
81 FFmpegMetadataPP,
82 FFmpegVideoConvertor,
83 FFmpegExtractAudioPP,
84 FFmpegEmbedSubtitlePP,
85 XAttrMetadataPP,
86 )
87
88
89 def parseOpts(overrideArguments=None):
90 def _readOptions(filename_bytes, default=[]):
91 try:
92 optionf = open(filename_bytes)
93 except IOError:
94 return default # silently skip if file is not present
95 try:
96 res = []
97 for l in optionf:
98 res += shlex.split(l, comments=True)
99 finally:
100 optionf.close()
101 return res
102
103 def _format_option_string(option):
104 ''' ('-o', '--option') -> -o, --format METAVAR'''
105
106 opts = []
107
108 if option._short_opts:
109 opts.append(option._short_opts[0])
110 if option._long_opts:
111 opts.append(option._long_opts[0])
112 if len(opts) > 1:
113 opts.insert(1, ', ')
114
115 if option.takes_value(): opts.append(' %s' % option.metavar)
116
117 return "".join(opts)
118
119 def _comma_separated_values_options_callback(option, opt_str, value, parser):
120 setattr(parser.values, option.dest, value.split(','))
121
122 def _hide_login_info(opts):
123 opts = list(opts)
124 for private_opt in ['-p', '--password', '-u', '--username', '--video-password']:
125 try:
126 i = opts.index(private_opt)
127 opts[i+1] = '<PRIVATE>'
128 except ValueError:
129 pass
130 return opts
131
132 max_width = 80
133 max_help_position = 80
134
135 # No need to wrap help messages if we're on a wide console
136 columns = get_term_width()
137 if columns: max_width = columns
138
139 fmt = optparse.IndentedHelpFormatter(width=max_width, max_help_position=max_help_position)
140 fmt.format_option_strings = _format_option_string
141
142 kw = {
143 'version' : __version__,
144 'formatter' : fmt,
145 'usage' : '%prog [options] url [url...]',
146 'conflict_handler' : 'resolve',
147 }
148
149 parser = optparse.OptionParser(**kw)
150
151 # option groups
152 general = optparse.OptionGroup(parser, 'General Options')
153 selection = optparse.OptionGroup(parser, 'Video Selection')
154 authentication = optparse.OptionGroup(parser, 'Authentication Options')
155 video_format = optparse.OptionGroup(parser, 'Video Format Options')
156 subtitles = optparse.OptionGroup(parser, 'Subtitle Options')
157 downloader = optparse.OptionGroup(parser, 'Download Options')
158 postproc = optparse.OptionGroup(parser, 'Post-processing Options')
159 filesystem = optparse.OptionGroup(parser, 'Filesystem Options')
160 verbosity = optparse.OptionGroup(parser, 'Verbosity / Simulation Options')
161
162 general.add_option('-h', '--help',
163 action='help', help='print this help text and exit')
164 general.add_option('-v', '--version',
165 action='version', help='print program version and exit')
166 general.add_option('-U', '--update',
167 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)')
168 general.add_option('-i', '--ignore-errors',
169 action='store_true', dest='ignoreerrors', help='continue on download errors, for example to to skip unavailable videos in a playlist', default=False)
170 general.add_option('--abort-on-error',
171 action='store_false', dest='ignoreerrors',
172 help='Abort downloading of further videos (in the playlist or the command line) if an error occurs')
173 general.add_option('--dump-user-agent',
174 action='store_true', dest='dump_user_agent',
175 help='display the current browser identification', default=False)
176 general.add_option('--user-agent',
177 dest='user_agent', help='specify a custom user agent', metavar='UA')
178 general.add_option('--referer',
179 dest='referer', help='specify a custom referer, use if the video access is restricted to one domain',
180 metavar='REF', default=None)
181 general.add_option('--list-extractors',
182 action='store_true', dest='list_extractors',
183 help='List all supported extractors and the URLs they would handle', default=False)
184 general.add_option('--extractor-descriptions',
185 action='store_true', dest='list_extractor_descriptions',
186 help='Output descriptions of all supported extractors', default=False)
187 general.add_option(
188 '--proxy', dest='proxy', default=None, metavar='URL',
189 help='Use the specified HTTP/HTTPS proxy. Pass in an empty string (--proxy "") for direct connection')
190 general.add_option('--no-check-certificate', action='store_true', dest='no_check_certificate', default=False, help='Suppress HTTPS certificate validation.')
191 general.add_option(
192 '--cache-dir', dest='cachedir', default=get_cachedir(), metavar='DIR',
193 help='Location in the filesystem where youtube-dl can store some downloaded information permanently. By default $XDG_CACHE_HOME/youtube-dl or ~/.cache/youtube-dl . At the moment, only YouTube player files (for videos with obfuscated signatures) are cached, but that may change.')
194 general.add_option(
195 '--no-cache-dir', action='store_const', const=None, dest='cachedir',
196 help='Disable filesystem caching')
197 general.add_option(
198 '--socket-timeout', dest='socket_timeout',
199 type=float, default=None, help=u'Time to wait before giving up, in seconds')
200 general.add_option(
201 '--bidi-workaround', dest='bidi_workaround', action='store_true',
202 help=u'Work around terminals that lack bidirectional text support. Requires bidiv or fribidi executable in PATH')
203 general.add_option('--default-search',
204 dest='default_search', metavar='PREFIX',
205 help='Use this prefix for unqualified URLs. For example "gvsearch2:" downloads two videos from google videos for youtube-dl "large apple". By default (with value "auto") youtube-dl guesses.')
206
207 selection.add_option(
208 '--playlist-start',
209 dest='playliststart', metavar='NUMBER', default=1, type=int,
210 help='playlist video to start at (default is %default)')
211 selection.add_option(
212 '--playlist-end',
213 dest='playlistend', metavar='NUMBER', default=None, type=int,
214 help='playlist video to end at (default is last)')
215 selection.add_option('--match-title', dest='matchtitle', metavar='REGEX',help='download only matching titles (regex or caseless sub-string)')
216 selection.add_option('--reject-title', dest='rejecttitle', metavar='REGEX',help='skip download for matching titles (regex or caseless sub-string)')
217 selection.add_option('--max-downloads', metavar='NUMBER',
218 dest='max_downloads', type=int, default=None,
219 help='Abort after downloading NUMBER files')
220 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)
221 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)
222 selection.add_option('--date', metavar='DATE', dest='date', help='download only videos uploaded in this date', default=None)
223 selection.add_option(
224 '--datebefore', metavar='DATE', dest='datebefore', default=None,
225 help='download only videos uploaded on or before this date (i.e. inclusive)')
226 selection.add_option(
227 '--dateafter', metavar='DATE', dest='dateafter', default=None,
228 help='download only videos uploaded on or after this date (i.e. inclusive)')
229 selection.add_option(
230 '--min-views', metavar='COUNT', dest='min_views',
231 default=None, type=int,
232 help="Do not download any videos with less than COUNT views",)
233 selection.add_option(
234 '--max-views', metavar='COUNT', dest='max_views',
235 default=None, type=int,
236 help="Do not download any videos with more than COUNT views",)
237 selection.add_option('--no-playlist', action='store_true', dest='noplaylist', help='download only the currently playing video', default=False)
238 selection.add_option('--age-limit', metavar='YEARS', dest='age_limit',
239 help='download only videos suitable for the given age',
240 default=None, type=int)
241 selection.add_option('--download-archive', metavar='FILE',
242 dest='download_archive',
243 help='Download only videos not listed in the archive file. Record the IDs of all downloaded videos in it.')
244 selection.add_option(
245 '--include-ads', dest='include_ads',
246 action='store_true',
247 help='Download advertisements as well (experimental)')
248 selection.add_option(
249 '--youtube-include-dash-manifest', action='store_true',
250 dest='youtube_include_dash_manifest', default=False,
251 help='Try to download the DASH manifest on YouTube videos (experimental)')
252
253 authentication.add_option('-u', '--username',
254 dest='username', metavar='USERNAME', help='account username')
255 authentication.add_option('-p', '--password',
256 dest='password', metavar='PASSWORD', help='account password')
257 authentication.add_option('-n', '--netrc',
258 action='store_true', dest='usenetrc', help='use .netrc authentication data', default=False)
259 authentication.add_option('--video-password',
260 dest='videopassword', metavar='PASSWORD', help='video password (vimeo, smotri)')
261
262
263 video_format.add_option('-f', '--format',
264 action='store', dest='format', metavar='FORMAT', default=None,
265 help='video format code, specify the order of preference using slashes: "-f 22/17/18". "-f mp4" and "-f flv" are also supported. You can also use the special names "best", "bestaudio", "worst", and "worstaudio". By default, youtube-dl will pick the best quality.')
266 video_format.add_option('--all-formats',
267 action='store_const', dest='format', help='download all available video formats', const='all')
268 video_format.add_option('--prefer-free-formats',
269 action='store_true', dest='prefer_free_formats', default=False, help='prefer free video formats unless a specific one is requested')
270 video_format.add_option('--max-quality',
271 action='store', dest='format_limit', metavar='FORMAT', help='highest quality format to download')
272 video_format.add_option('-F', '--list-formats',
273 action='store_true', dest='listformats', help='list all available formats')
274
275 subtitles.add_option('--write-sub', '--write-srt',
276 action='store_true', dest='writesubtitles',
277 help='write subtitle file', default=False)
278 subtitles.add_option('--write-auto-sub', '--write-automatic-sub',
279 action='store_true', dest='writeautomaticsub',
280 help='write automatic subtitle file (youtube only)', default=False)
281 subtitles.add_option('--all-subs',
282 action='store_true', dest='allsubtitles',
283 help='downloads all the available subtitles of the video', default=False)
284 subtitles.add_option('--list-subs',
285 action='store_true', dest='listsubtitles',
286 help='lists all available subtitles for the video', default=False)
287 subtitles.add_option('--sub-format',
288 action='store', dest='subtitlesformat', metavar='FORMAT',
289 help='subtitle format (default=srt) ([sbv/vtt] youtube only)', default='srt')
290 subtitles.add_option('--sub-lang', '--sub-langs', '--srt-lang',
291 action='callback', dest='subtitleslangs', metavar='LANGS', type='str',
292 default=[], callback=_comma_separated_values_options_callback,
293 help='languages of the subtitles to download (optional) separated by commas, use IETF language tags like \'en,pt\'')
294
295 downloader.add_option('-r', '--rate-limit',
296 dest='ratelimit', metavar='LIMIT', help='maximum download rate in bytes per second (e.g. 50K or 4.2M)')
297 downloader.add_option('-R', '--retries',
298 dest='retries', metavar='RETRIES', help='number of retries (default is %default)', default=10)
299 downloader.add_option('--buffer-size',
300 dest='buffersize', metavar='SIZE', help='size of download buffer (e.g. 1024 or 16K) (default is %default)', default="1024")
301 downloader.add_option('--no-resize-buffer',
302 action='store_true', dest='noresizebuffer',
303 help='do not automatically adjust the buffer size. By default, the buffer size is automatically resized from an initial value of SIZE.', default=False)
304 downloader.add_option('--test', action='store_true', dest='test', default=False, help=optparse.SUPPRESS_HELP)
305
306 verbosity.add_option('-q', '--quiet',
307 action='store_true', dest='quiet', help='activates quiet mode', default=False)
308 verbosity.add_option('-s', '--simulate',
309 action='store_true', dest='simulate', help='do not download the video and do not write anything to disk', default=False)
310 verbosity.add_option('--skip-download',
311 action='store_true', dest='skip_download', help='do not download the video', default=False)
312 verbosity.add_option('-g', '--get-url',
313 action='store_true', dest='geturl', help='simulate, quiet but print URL', default=False)
314 verbosity.add_option('-e', '--get-title',
315 action='store_true', dest='gettitle', help='simulate, quiet but print title', default=False)
316 verbosity.add_option('--get-id',
317 action='store_true', dest='getid', help='simulate, quiet but print id', default=False)
318 verbosity.add_option('--get-thumbnail',
319 action='store_true', dest='getthumbnail',
320 help='simulate, quiet but print thumbnail URL', default=False)
321 verbosity.add_option('--get-description',
322 action='store_true', dest='getdescription',
323 help='simulate, quiet but print video description', default=False)
324 verbosity.add_option('--get-duration',
325 action='store_true', dest='getduration',
326 help='simulate, quiet but print video length', default=False)
327 verbosity.add_option('--get-filename',
328 action='store_true', dest='getfilename',
329 help='simulate, quiet but print output filename', default=False)
330 verbosity.add_option('--get-format',
331 action='store_true', dest='getformat',
332 help='simulate, quiet but print output format', default=False)
333 verbosity.add_option('-j', '--dump-json',
334 action='store_true', dest='dumpjson',
335 help='simulate, quiet but print JSON information', default=False)
336 verbosity.add_option('--newline',
337 action='store_true', dest='progress_with_newline', help='output progress bar as new lines', default=False)
338 verbosity.add_option('--no-progress',
339 action='store_true', dest='noprogress', help='do not print progress bar', default=False)
340 verbosity.add_option('--console-title',
341 action='store_true', dest='consoletitle',
342 help='display progress in console titlebar', default=False)
343 verbosity.add_option('-v', '--verbose',
344 action='store_true', dest='verbose', help='print various debugging information', default=False)
345 verbosity.add_option('--dump-intermediate-pages',
346 action='store_true', dest='dump_intermediate_pages', default=False,
347 help='print downloaded pages to debug problems (very verbose)')
348 verbosity.add_option('--write-pages',
349 action='store_true', dest='write_pages', default=False,
350 help='Write downloaded intermediary pages to files in the current directory to debug problems')
351 verbosity.add_option('--youtube-print-sig-code',
352 action='store_true', dest='youtube_print_sig_code', default=False,
353 help=optparse.SUPPRESS_HELP)
354 verbosity.add_option('--print-traffic',
355 dest='debug_printtraffic', action='store_true', default=False,
356 help='Display sent and read HTTP traffic')
357
358
359 filesystem.add_option('-t', '--title',
360 action='store_true', dest='usetitle', help='use title in file name (default)', default=False)
361 filesystem.add_option('--id',
362 action='store_true', dest='useid', help='use only video ID in file name', default=False)
363 filesystem.add_option('-l', '--literal',
364 action='store_true', dest='usetitle', help='[deprecated] alias of --title', default=False)
365 filesystem.add_option('-A', '--auto-number',
366 action='store_true', dest='autonumber',
367 help='number downloaded files starting from 00000', default=False)
368 filesystem.add_option('-o', '--output',
369 dest='outtmpl', metavar='TEMPLATE',
370 help=('output filename template. Use %(title)s to get the title, '
371 '%(uploader)s for the uploader name, %(uploader_id)s for the uploader nickname if different, '
372 '%(autonumber)s to get an automatically incremented number, '
373 '%(ext)s for the filename extension, '
374 '%(format)s for the format description (like "22 - 1280x720" or "HD"), '
375 '%(format_id)s for the unique id of the format (like Youtube\'s itags: "137"), '
376 '%(upload_date)s for the upload date (YYYYMMDD), '
377 '%(extractor)s for the provider (youtube, metacafe, etc), '
378 '%(id)s for the video id, %(playlist)s for the playlist the video is in, '
379 '%(playlist_index)s for the position in the playlist and %% for a literal percent. '
380 'Use - to output to stdout. Can also be used to download to a different directory, '
381 'for example with -o \'/my/downloads/%(uploader)s/%(title)s-%(id)s.%(ext)s\' .'))
382 filesystem.add_option('--autonumber-size',
383 dest='autonumber_size', metavar='NUMBER',
384 help='Specifies the number of digits in %(autonumber)s when it is present in output filename template or --auto-number option is given')
385 filesystem.add_option('--restrict-filenames',
386 action='store_true', dest='restrictfilenames',
387 help='Restrict filenames to only ASCII characters, and avoid "&" and spaces in filenames', default=False)
388 filesystem.add_option('-a', '--batch-file',
389 dest='batchfile', metavar='FILE', help='file containing URLs to download (\'-\' for stdin)')
390 filesystem.add_option('--load-info',
391 dest='load_info_filename', metavar='FILE',
392 help='json file containing the video information (created with the "--write-json" option)')
393 filesystem.add_option('-w', '--no-overwrites',
394 action='store_true', dest='nooverwrites', help='do not overwrite files', default=False)
395 filesystem.add_option('-c', '--continue',
396 action='store_true', dest='continue_dl', help='force resume of partially downloaded files. By default, youtube-dl will resume downloads if possible.', default=True)
397 filesystem.add_option('--no-continue',
398 action='store_false', dest='continue_dl',
399 help='do not resume partially downloaded files (restart from beginning)')
400 filesystem.add_option('--cookies',
401 dest='cookiefile', metavar='FILE', help='file to read cookies from and dump cookie jar in')
402 filesystem.add_option('--no-part',
403 action='store_true', dest='nopart', help='do not use .part files', default=False)
404 filesystem.add_option('--no-mtime',
405 action='store_false', dest='updatetime',
406 help='do not use the Last-modified header to set the file modification time', default=True)
407 filesystem.add_option('--write-description',
408 action='store_true', dest='writedescription',
409 help='write video description to a .description file', default=False)
410 filesystem.add_option('--write-info-json',
411 action='store_true', dest='writeinfojson',
412 help='write video metadata to a .info.json file', default=False)
413 filesystem.add_option('--write-annotations',
414 action='store_true', dest='writeannotations',
415 help='write video annotations to a .annotation file', default=False)
416 filesystem.add_option('--write-thumbnail',
417 action='store_true', dest='writethumbnail',
418 help='write thumbnail image to disk', default=False)
419
420
421 postproc.add_option('-x', '--extract-audio', action='store_true', dest='extractaudio', default=False,
422 help='convert video files to audio-only files (requires ffmpeg or avconv and ffprobe or avprobe)')
423 postproc.add_option('--audio-format', metavar='FORMAT', dest='audioformat', default='best',
424 help='"best", "aac", "vorbis", "mp3", "m4a", "opus", or "wav"; best by default')
425 postproc.add_option('--audio-quality', metavar='QUALITY', dest='audioquality', default='5',
426 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)')
427 postproc.add_option('--recode-video', metavar='FORMAT', dest='recodevideo', default=None,
428 help='Encode the video to another format if necessary (currently supported: mp4|flv|ogg|webm)')
429 postproc.add_option('-k', '--keep-video', action='store_true', dest='keepvideo', default=False,
430 help='keeps the video file on disk after the post-processing; the video is erased by default')
431 postproc.add_option('--no-post-overwrites', action='store_true', dest='nopostoverwrites', default=False,
432 help='do not overwrite post-processed files; the post-processed files are overwritten by default')
433 postproc.add_option('--embed-subs', action='store_true', dest='embedsubtitles', default=False,
434 help='embed subtitles in the video (only for mp4 videos)')
435 postproc.add_option('--add-metadata', action='store_true', dest='addmetadata', default=False,
436 help='write metadata to the video file')
437 postproc.add_option('--xattrs', action='store_true', dest='xattrs', default=False,
438 help='write metadata to the video file\'s xattrs (using dublin core and xdg standards)')
439 postproc.add_option('--prefer-avconv', action='store_false', dest='prefer_ffmpeg',
440 help='Prefer avconv over ffmpeg for running the postprocessors (default)')
441 postproc.add_option('--prefer-ffmpeg', action='store_true', dest='prefer_ffmpeg',
442 help='Prefer ffmpeg over avconv for running the postprocessors')
443
444
445 parser.add_option_group(general)
446 parser.add_option_group(selection)
447 parser.add_option_group(downloader)
448 parser.add_option_group(filesystem)
449 parser.add_option_group(verbosity)
450 parser.add_option_group(video_format)
451 parser.add_option_group(subtitles)
452 parser.add_option_group(authentication)
453 parser.add_option_group(postproc)
454
455 if overrideArguments is not None:
456 opts, args = parser.parse_args(overrideArguments)
457 if opts.verbose:
458 write_string(u'[debug] Override config: ' + repr(overrideArguments) + '\n')
459 else:
460 systemConf = _readOptions('/etc/youtube-dl.conf')
461
462 xdg_config_home = os.environ.get('XDG_CONFIG_HOME')
463 if xdg_config_home:
464 userConfFile = os.path.join(xdg_config_home, 'youtube-dl', 'config')
465 if not os.path.isfile(userConfFile):
466 userConfFile = os.path.join(xdg_config_home, 'youtube-dl.conf')
467 else:
468 userConfFile = os.path.join(os.path.expanduser('~'), '.config', 'youtube-dl', 'config')
469 if not os.path.isfile(userConfFile):
470 userConfFile = os.path.join(os.path.expanduser('~'), '.config', 'youtube-dl.conf')
471 userConf = _readOptions(userConfFile, None)
472
473 if userConf is None:
474 appdata_dir = os.environ.get('appdata')
475 if appdata_dir:
476 userConf = _readOptions(
477 os.path.join(appdata_dir, 'youtube-dl', 'config'),
478 default=None)
479 if userConf is None:
480 userConf = _readOptions(
481 os.path.join(appdata_dir, 'youtube-dl', 'config.txt'),
482 default=None)
483
484 if userConf is None:
485 userConf = _readOptions(
486 os.path.join(os.path.expanduser('~'), 'youtube-dl.conf'),
487 default=None)
488 if userConf is None:
489 userConf = _readOptions(
490 os.path.join(os.path.expanduser('~'), 'youtube-dl.conf.txt'),
491 default=None)
492
493 if userConf is None:
494 userConf = []
495
496 commandLineConf = sys.argv[1:]
497 argv = systemConf + userConf + commandLineConf
498 opts, args = parser.parse_args(argv)
499 if opts.verbose:
500 write_string(u'[debug] System config: ' + repr(_hide_login_info(systemConf)) + '\n')
501 write_string(u'[debug] User config: ' + repr(_hide_login_info(userConf)) + '\n')
502 write_string(u'[debug] Command-line args: ' + repr(_hide_login_info(commandLineConf)) + '\n')
503 write_string(u'[debug] Encodings: locale %r, fs %r, out %r, pref: %r\n' %
504 (locale.getpreferredencoding(), sys.getfilesystemencoding(), sys.stdout.encoding, preferredencoding()))
505
506 return parser, opts, args
507
508
509 def _real_main(argv=None):
510 # Compatibility fixes for Windows
511 if sys.platform == 'win32':
512 # https://github.com/rg3/youtube-dl/issues/820
513 codecs.register(lambda name: codecs.lookup('utf-8') if name == 'cp65001' else None)
514
515 setproctitle(u'youtube-dl')
516
517 parser, opts, args = parseOpts(argv)
518
519 # Set user agent
520 if opts.user_agent is not None:
521 std_headers['User-Agent'] = opts.user_agent
522
523 # Set referer
524 if opts.referer is not None:
525 std_headers['Referer'] = opts.referer
526
527 # Dump user agent
528 if opts.dump_user_agent:
529 compat_print(std_headers['User-Agent'])
530 sys.exit(0)
531
532 # Batch file verification
533 batchurls = []
534 if opts.batchfile is not None:
535 try:
536 if opts.batchfile == '-':
537 batchfd = sys.stdin
538 else:
539 batchfd = open(opts.batchfile, 'r')
540 batchurls = batchfd.readlines()
541 batchurls = [x.strip() for x in batchurls]
542 batchurls = [x for x in batchurls if len(x) > 0 and not re.search(r'^[#/;]', x)]
543 if opts.verbose:
544 write_string(u'[debug] Batch file urls: ' + repr(batchurls) + u'\n')
545 except IOError:
546 sys.exit(u'ERROR: batch file could not be read')
547 all_urls = batchurls + args
548 all_urls = [url.strip() for url in all_urls]
549 _enc = preferredencoding()
550 all_urls = [url.decode(_enc, 'ignore') if isinstance(url, bytes) else url for url in all_urls]
551
552 extractors = gen_extractors()
553
554 if opts.list_extractors:
555 for ie in sorted(extractors, key=lambda ie: ie.IE_NAME.lower()):
556 compat_print(ie.IE_NAME + (' (CURRENTLY BROKEN)' if not ie._WORKING else ''))
557 matchedUrls = [url for url in all_urls if ie.suitable(url)]
558 for mu in matchedUrls:
559 compat_print(u' ' + mu)
560 sys.exit(0)
561 if opts.list_extractor_descriptions:
562 for ie in sorted(extractors, key=lambda ie: ie.IE_NAME.lower()):
563 if not ie._WORKING:
564 continue
565 desc = getattr(ie, 'IE_DESC', ie.IE_NAME)
566 if desc is False:
567 continue
568 if hasattr(ie, 'SEARCH_KEY'):
569 _SEARCHES = (u'cute kittens', u'slithering pythons', u'falling cat', u'angry poodle', u'purple fish', u'running tortoise')
570 _COUNTS = (u'', u'5', u'10', u'all')
571 desc += u' (Example: "%s%s:%s" )' % (ie.SEARCH_KEY, random.choice(_COUNTS), random.choice(_SEARCHES))
572 compat_print(desc)
573 sys.exit(0)
574
575
576 # Conflicting, missing and erroneous options
577 if opts.usenetrc and (opts.username is not None or opts.password is not None):
578 parser.error(u'using .netrc conflicts with giving username/password')
579 if opts.password is not None and opts.username is None:
580 parser.error(u'account username missing\n')
581 if opts.outtmpl is not None and (opts.usetitle or opts.autonumber or opts.useid):
582 parser.error(u'using output template conflicts with using title, video ID or auto number')
583 if opts.usetitle and opts.useid:
584 parser.error(u'using title conflicts with using video ID')
585 if opts.username is not None and opts.password is None:
586 opts.password = getpass.getpass(u'Type account password and press return:')
587 if opts.ratelimit is not None:
588 numeric_limit = FileDownloader.parse_bytes(opts.ratelimit)
589 if numeric_limit is None:
590 parser.error(u'invalid rate limit specified')
591 opts.ratelimit = numeric_limit
592 if opts.min_filesize is not None:
593 numeric_limit = FileDownloader.parse_bytes(opts.min_filesize)
594 if numeric_limit is None:
595 parser.error(u'invalid min_filesize specified')
596 opts.min_filesize = numeric_limit
597 if opts.max_filesize is not None:
598 numeric_limit = FileDownloader.parse_bytes(opts.max_filesize)
599 if numeric_limit is None:
600 parser.error(u'invalid max_filesize specified')
601 opts.max_filesize = numeric_limit
602 if opts.retries is not None:
603 try:
604 opts.retries = int(opts.retries)
605 except (TypeError, ValueError):
606 parser.error(u'invalid retry count specified')
607 if opts.buffersize is not None:
608 numeric_buffersize = FileDownloader.parse_bytes(opts.buffersize)
609 if numeric_buffersize is None:
610 parser.error(u'invalid buffer size specified')
611 opts.buffersize = numeric_buffersize
612 if opts.playliststart <= 0:
613 raise ValueError(u'Playlist start must be positive')
614 if opts.playlistend not in (-1, None) and opts.playlistend < opts.playliststart:
615 raise ValueError(u'Playlist end must be greater than playlist start')
616 if opts.extractaudio:
617 if opts.audioformat not in ['best', 'aac', 'mp3', 'm4a', 'opus', 'vorbis', 'wav']:
618 parser.error(u'invalid audio format specified')
619 if opts.audioquality:
620 opts.audioquality = opts.audioquality.strip('k').strip('K')
621 if not opts.audioquality.isdigit():
622 parser.error(u'invalid audio quality specified')
623 if opts.recodevideo is not None:
624 if opts.recodevideo not in ['mp4', 'flv', 'webm', 'ogg']:
625 parser.error(u'invalid video recode format specified')
626 if opts.date is not None:
627 date = DateRange.day(opts.date)
628 else:
629 date = DateRange(opts.dateafter, opts.datebefore)
630 if opts.default_search not in ('auto', None) and ':' not in opts.default_search:
631 parser.error(u'--default-search invalid; did you forget a colon (:) at the end?')
632
633 # Do not download videos when there are audio-only formats
634 if opts.extractaudio and not opts.keepvideo and opts.format is None:
635 opts.format = 'bestaudio/best'
636
637 # --all-sub automatically sets --write-sub if --write-auto-sub is not given
638 # this was the old behaviour if only --all-sub was given.
639 if opts.allsubtitles and (opts.writeautomaticsub == False):
640 opts.writesubtitles = True
641
642 if sys.version_info < (3,):
643 # In Python 2, sys.argv is a bytestring (also note http://bugs.python.org/issue2128 for Windows systems)
644 if opts.outtmpl is not None:
645 opts.outtmpl = opts.outtmpl.decode(preferredencoding())
646 outtmpl =((opts.outtmpl is not None and opts.outtmpl)
647 or (opts.format == '-1' and opts.usetitle and u'%(title)s-%(id)s-%(format)s.%(ext)s')
648 or (opts.format == '-1' and u'%(id)s-%(format)s.%(ext)s')
649 or (opts.usetitle and opts.autonumber and u'%(autonumber)s-%(title)s-%(id)s.%(ext)s')
650 or (opts.usetitle and u'%(title)s-%(id)s.%(ext)s')
651 or (opts.useid and u'%(id)s.%(ext)s')
652 or (opts.autonumber and u'%(autonumber)s-%(id)s.%(ext)s')
653 or u'%(title)s-%(id)s.%(ext)s')
654 if not os.path.splitext(outtmpl)[1] and opts.extractaudio:
655 parser.error(u'Cannot download a video and extract audio into the same'
656 u' file! Use "{0}.%(ext)s" instead of "{0}" as the output'
657 u' template'.format(outtmpl))
658
659 any_printing = opts.geturl or opts.gettitle or opts.getid or opts.getthumbnail or opts.getdescription or opts.getfilename or opts.getformat or opts.getduration or opts.dumpjson
660 download_archive_fn = os.path.expanduser(opts.download_archive) if opts.download_archive is not None else opts.download_archive
661
662 ydl_opts = {
663 'usenetrc': opts.usenetrc,
664 'username': opts.username,
665 'password': opts.password,
666 'videopassword': opts.videopassword,
667 'quiet': (opts.quiet or any_printing),
668 'forceurl': opts.geturl,
669 'forcetitle': opts.gettitle,
670 'forceid': opts.getid,
671 'forcethumbnail': opts.getthumbnail,
672 'forcedescription': opts.getdescription,
673 'forceduration': opts.getduration,
674 'forcefilename': opts.getfilename,
675 'forceformat': opts.getformat,
676 'forcejson': opts.dumpjson,
677 'simulate': opts.simulate,
678 'skip_download': (opts.skip_download or opts.simulate or any_printing),
679 'format': opts.format,
680 'format_limit': opts.format_limit,
681 'listformats': opts.listformats,
682 'outtmpl': outtmpl,
683 'autonumber_size': opts.autonumber_size,
684 'restrictfilenames': opts.restrictfilenames,
685 'ignoreerrors': opts.ignoreerrors,
686 'ratelimit': opts.ratelimit,
687 'nooverwrites': opts.nooverwrites,
688 'retries': opts.retries,
689 'buffersize': opts.buffersize,
690 'noresizebuffer': opts.noresizebuffer,
691 'continuedl': opts.continue_dl,
692 'noprogress': opts.noprogress,
693 'progress_with_newline': opts.progress_with_newline,
694 'playliststart': opts.playliststart,
695 'playlistend': opts.playlistend,
696 'noplaylist': opts.noplaylist,
697 'logtostderr': opts.outtmpl == '-',
698 'consoletitle': opts.consoletitle,
699 'nopart': opts.nopart,
700 'updatetime': opts.updatetime,
701 'writedescription': opts.writedescription,
702 'writeannotations': opts.writeannotations,
703 'writeinfojson': opts.writeinfojson,
704 'writethumbnail': opts.writethumbnail,
705 'writesubtitles': opts.writesubtitles,
706 'writeautomaticsub': opts.writeautomaticsub,
707 'allsubtitles': opts.allsubtitles,
708 'listsubtitles': opts.listsubtitles,
709 'subtitlesformat': opts.subtitlesformat,
710 'subtitleslangs': opts.subtitleslangs,
711 'matchtitle': decodeOption(opts.matchtitle),
712 'rejecttitle': decodeOption(opts.rejecttitle),
713 'max_downloads': opts.max_downloads,
714 'prefer_free_formats': opts.prefer_free_formats,
715 'verbose': opts.verbose,
716 'dump_intermediate_pages': opts.dump_intermediate_pages,
717 'write_pages': opts.write_pages,
718 'test': opts.test,
719 'keepvideo': opts.keepvideo,
720 'min_filesize': opts.min_filesize,
721 'max_filesize': opts.max_filesize,
722 'min_views': opts.min_views,
723 'max_views': opts.max_views,
724 'daterange': date,
725 'cachedir': opts.cachedir,
726 'youtube_print_sig_code': opts.youtube_print_sig_code,
727 'age_limit': opts.age_limit,
728 'download_archive': download_archive_fn,
729 'cookiefile': opts.cookiefile,
730 'nocheckcertificate': opts.no_check_certificate,
731 'proxy': opts.proxy,
732 'socket_timeout': opts.socket_timeout,
733 'bidi_workaround': opts.bidi_workaround,
734 'debug_printtraffic': opts.debug_printtraffic,
735 'prefer_ffmpeg': opts.prefer_ffmpeg,
736 'include_ads': opts.include_ads,
737 'default_search': opts.default_search,
738 'youtube_include_dash_manifest': opts.youtube_include_dash_manifest,
739 }
740
741 with YoutubeDL(ydl_opts) as ydl:
742 ydl.print_debug_header()
743 ydl.add_default_info_extractors()
744
745 # PostProcessors
746 # Add the metadata pp first, the other pps will copy it
747 if opts.addmetadata:
748 ydl.add_post_processor(FFmpegMetadataPP())
749 if opts.extractaudio:
750 ydl.add_post_processor(FFmpegExtractAudioPP(preferredcodec=opts.audioformat, preferredquality=opts.audioquality, nopostoverwrites=opts.nopostoverwrites))
751 if opts.recodevideo:
752 ydl.add_post_processor(FFmpegVideoConvertor(preferedformat=opts.recodevideo))
753 if opts.embedsubtitles:
754 ydl.add_post_processor(FFmpegEmbedSubtitlePP(subtitlesformat=opts.subtitlesformat))
755 if opts.xattrs:
756 ydl.add_post_processor(XAttrMetadataPP())
757
758 # Update version
759 if opts.update_self:
760 update_self(ydl.to_screen, opts.verbose)
761
762 # Maybe do nothing
763 if (len(all_urls) < 1) and (opts.load_info_filename is None):
764 if not opts.update_self:
765 parser.error(u'you must provide at least one URL')
766 else:
767 sys.exit()
768
769 try:
770 if opts.load_info_filename is not None:
771 retcode = ydl.download_with_info_file(opts.load_info_filename)
772 else:
773 retcode = ydl.download(all_urls)
774 except MaxDownloadsReached:
775 ydl.to_screen(u'--max-download limit reached, aborting.')
776 retcode = 101
777
778 sys.exit(retcode)
779
780
781 def main(argv=None):
782 try:
783 _real_main(argv)
784 except DownloadError:
785 sys.exit(1)
786 except SameFileError:
787 sys.exit(u'ERROR: fixed output name but more than one file to download')
788 except KeyboardInterrupt:
789 sys.exit(u'\nERROR: Interrupted by user')