2 # -*- coding: utf-8 -*-
5 'Ricardo Garcia Gonzalez',
13 'Philipp Hagemeister',
21 'Jaime Marquínez Ferrándiz',
25 'M. Yasoob Ullah Khalid',
33 'Steffan \'Ruirize\' James',
40 __license__
= 'Public Domain'
66 from .update
import update_self
67 from .FileDownloader
import (
70 from .extractor
import gen_extractors
71 from .version
import __version__
72 from .YoutubeDL
import YoutubeDL
73 from .PostProcessor
import (
77 FFmpegEmbedSubtitlePP
,
81 def parseOpts(overrideArguments
=None):
82 def _readOptions(filename_bytes
):
84 optionf
= open(filename_bytes
)
86 return [] # silently skip if file is not present
90 res
+= shlex
.split(l
, comments
=True)
95 def _format_option_string(option
):
96 ''' ('-o', '--option') -> -o, --format METAVAR'''
100 if option
._short
_opts
:
101 opts
.append(option
._short
_opts
[0])
102 if option
._long
_opts
:
103 opts
.append(option
._long
_opts
[0])
107 if option
.takes_value(): opts
.append(' %s' % option
.metavar
)
111 def _comma_separated_values_options_callback(option
, opt_str
, value
, parser
):
112 setattr(parser
.values
, option
.dest
, value
.split(','))
114 def _find_term_columns():
115 columns
= os
.environ
.get('COLUMNS', None)
120 sp
= subprocess
.Popen(['stty', 'size'], stdout
=subprocess
.PIPE
, stderr
=subprocess
.PIPE
)
121 out
,err
= sp
.communicate()
122 return int(out
.split()[1])
127 def _hide_login_info(opts
):
129 for private_opt
in ['-p', '--password', '-u', '--username', '--video-password']:
131 i
= opts
.index(private_opt
)
132 opts
[i
+1] = '<PRIVATE>'
138 max_help_position
= 80
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
144 fmt
= optparse
.IndentedHelpFormatter(width
=max_width
, max_help_position
=max_help_position
)
145 fmt
.format_option_strings
= _format_option_string
148 'version' : __version__
,
150 'usage' : '%prog [options] url [url...]',
151 'conflict_handler' : 'resolve',
154 parser
= optparse
.OptionParser(**kw
)
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')
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.')
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 .')
198 '--no-cache-dir', action
='store_const', const
=None, dest
='cachedir',
199 help='Disable filesystem caching')
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.')
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)')
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)')
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\'')
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
)
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
)
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)
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')
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
)
410 if overrideArguments
is not None:
411 opts
, args
= parser
.parse_args(overrideArguments
)
413 write_string(u
'[debug] Override config: ' + repr(overrideArguments
) + '\n')
415 xdg_config_home
= os
.environ
.get('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')
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
)
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')
434 return parser
, opts
, args
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)
442 parser
, opts
, args
= parseOpts(argv
)
445 if opts
.user_agent
is not None:
446 std_headers
['User-Agent'] = opts
.user_agent
449 if opts
.referer
is not None:
450 std_headers
['Referer'] = opts
.referer
453 if opts
.dump_user_agent
:
454 compat_print(std_headers
['User-Agent'])
457 # Batch file verification
459 if opts
.batchfile
is not None:
461 if opts
.batchfile
== '-':
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
)]
469 write_string(u
'[debug] Batch file urls: ' + repr(batchurls
) + u
'\n')
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
]
475 extractors
= gen_extractors()
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
)
485 if opts
.list_extractor_descriptions
:
486 for ie
in sorted(extractors
, key
=lambda ie
: ie
.IE_NAME
.lower()):
489 desc
= getattr(ie
, 'IE_DESC', ie
.IE_NAME
)
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
))
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:
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
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')
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
)
561 date
= DateRange(opts
.dateafter
, opts
.datebefore
)
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
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
''))
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
,
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
,
641 'keepvideo': opts
.keepvideo
,
642 'min_filesize': opts
.min_filesize
,
643 'max_filesize': opts
.max_filesize
,
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
,
653 with YoutubeDL(ydl_opts
) as ydl
:
654 ydl
.print_debug_header()
655 ydl
.add_default_info_extractors()
658 # Add the metadata pp first, the other pps will copy it
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
))
664 ydl
.add_post_processor(FFmpegVideoConvertor(preferedformat
=opts
.recodevideo
))
665 if opts
.embedsubtitles
:
666 ydl
.add_post_processor(FFmpegEmbedSubtitlePP(subtitlesformat
=opts
.subtitlesformat
))
670 update_self(ydl
.to_screen
, opts
.verbose
)
673 if len(all_urls
) < 1:
674 if not opts
.update_self
:
675 parser
.error(u
'you must provide at least one URL')
680 retcode
= ydl
.download(all_urls
)
681 except MaxDownloadsReached
:
682 ydl
.to_screen(u
'--max-download limit reached, aborting.')
691 except DownloadError
:
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')