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