simulate: Do not download the video files.
format: Video format code. see "FORMAT SELECTION" for more details.
allow_unplayable_formats: Allow unplayable formats to be extracted and downloaded.
+ ignore_no_formats_error: Ignore "No video formats" error. Usefull for
+ extracting metadata even if the video is not actually
+ available for download (experimental)
format_sort: How to sort the video formats. see "Sorting Formats"
for more details.
format_sort_force: Force the given format_sort. see "Sorting Formats"
formats = info_dict['formats']
if not formats:
- raise ExtractorError('No video formats found!')
+ if not self.params.get('ignore_no_formats_error'):
+ raise ExtractorError('No video formats found!')
+ else:
+ self.report_warning('No video formats found!')
def is_wellformed(f):
url = f.get('url')
# TODO Central sorting goes here
- if formats[0] is not info_dict:
+ if formats and formats[0] is not info_dict:
# only set the 'formats' fields if the original info_dict list them
# otherwise we end up with a circular reference, the first (and unique)
# element in the 'formats' field in info_dict is info_dict itself,
# which can't be exported to json
info_dict['formats'] = formats
if self.params.get('listformats'):
+ if not info_dict.get('formats'):
+ raise ExtractorError('No video formats found', expected=True)
self.list_formats(info_dict)
return
formats_to_download = list(format_selector(ctx))
if not formats_to_download:
- raise ExtractorError('requested format not available',
- expected=True)
-
- if download:
- self.to_screen('[info] Downloading format(s) %s' % ", ".join([f['format_id'] for f in formats_to_download]))
+ if not self.params.get('ignore_no_formats_error'):
+ raise ExtractorError('Requested format is not available', expected=True)
+ else:
+ self.report_warning('Requested format is not available')
+ elif download:
+ self.to_screen(
+ '[info] %s: Downloading format(s) %s'
+ % (info_dict['id'], ", ".join([f['format_id'] for f in formats_to_download])))
if len(formats_to_download) > 1:
- self.to_screen('[info] %s: downloading video in %s formats' % (info_dict['id'], len(formats_to_download)))
- for format in formats_to_download:
+ self.to_screen(
+ '[info] %s: Downloading video in %s formats'
+ % (info_dict['id'], len(formats_to_download)))
+ for fmt in formats_to_download:
new_info = dict(info_dict)
- new_info.update(format)
+ new_info.update(fmt)
self.process_info(new_info)
# We update the info dict with the best quality format (backwards compatibility)
- info_dict.update(formats_to_download[-1])
+ if formats_to_download:
+ info_dict.update(formats_to_download[-1])
return info_dict
def process_subtitles(self, video_id, normal_subtitles, automatic_captions):
'skip_download': opts.skip_download,
'format': opts.format,
'allow_unplayable_formats': opts.allow_unplayable_formats,
+ 'ignore_no_formats_error': opts.ignore_no_formats_error,
'format_sort': opts.format_sort,
'format_sort_force': opts.format_sort_force,
'allow_multiple_video_streams': opts.allow_multiple_video_streams,
'url': file_url,
'format_id': 'http',
}]
- if not formats:
+ if not formats and not self._downloader.params.get('ignore_no_formats'):
continue
self._sort_formats(formats)
file_info = common_entry.copy()
if not formats:
if fsk:
- raise ExtractorError(
+ self.raise_no_formats(
'This video is only available after 20:00', expected=True)
elif media_info.get('_geoblocked'):
self.raise_geo_restricted(
'This video is not available due to geoblocking',
- countries=self._GEO_COUNTRIES)
+ countries=self._GEO_COUNTRIES, metadata_available=True)
self._sort_formats(formats)
entries = []
for num, media_meta in enumerate(medias, start=1):
formats, subtitles = self._extract_from_media_meta(media_meta, playlist_id)
- if not formats:
+ if not formats and not self._downloader.params.get('ignore_no_formats'):
continue
self._sort_formats(formats)
errors = json_data.get('errors')
if errors:
error = errors[0]
- raise ExtractorError(
+ self.raise_no_formats(
error.get('message') or error.get('error_subcode') or error['error_code'], expected=True)
- if (not self._downloader.params.get('allow_unplayable_formats')
+ elif (not self._downloader.params.get('allow_unplayable_formats')
and sources and num_drm_sources == len(sources)):
raise ExtractorError('This video is DRM protected.', expected=True)
from .common import InfoExtractor
from ..utils import (
clean_html,
- ExtractorError,
int_or_none,
parse_iso8601,
qualities,
'quality': quality(q, q_url),
})
- self._sort_formats(formats)
-
slides = content_data.get('Slides')
zip_file = content_data.get('ZipFile')
if not formats and not slides and not zip_file:
- raise ExtractorError(
+ self.raise_no_formats(
'None of recording, slides or zip are available for %s' % content_path)
+ self._sort_formats(formats)
subtitles = {}
for caption in content_data.get('Captions', []):
"""Report attempt to log in."""
self.to_screen('Logging in')
- @staticmethod
- def raise_login_required(msg='This video is only available for registered users'):
+ def raise_login_required(
+ self, msg='This video is only available for registered users', metadata_available=False):
+ if metadata_available and self._downloader.params.get('ignore_no_formats_error'):
+ self.report_warning(msg)
raise ExtractorError(
- '%s. Use --username and --password or --netrc to provide account credentials.' % msg,
+ '%s. Use --cookies, --username and --password or --netrc to provide account credentials' % msg,
expected=True)
- @staticmethod
- def raise_geo_restricted(msg='This video is not available from your location due to geo restriction', countries=None):
- raise GeoRestrictedError(msg, countries=countries)
+ def raise_geo_restricted(
+ self, msg='This video is not available from your location due to geo restriction',
+ countries=None, metadata_available=False):
+ if metadata_available and self._downloader.params.get('ignore_no_formats_error'):
+ self.report_warning(msg)
+ else:
+ raise GeoRestrictedError(msg, countries=countries)
+
+ def raise_no_formats(self, msg, expected=False, video_id=None):
+ if expected and self._downloader.params.get('ignore_no_formats_error'):
+ self.report_warning(msg, video_id)
+ else:
+ raise ExtractorError(msg, expected=expected, video_id=video_id)
# Methods for following #608
@staticmethod
def _sort_formats(self, formats, field_preference=[]):
if not formats:
+ if self._downloader.params.get('ignore_no_formats_error'):
+ return
raise ExtractorError('No video formats found')
format_sort = self.FormatSort() # params and to_screen are taken from the downloader
format_sort.evaluate_params(self._downloader.params, field_preference)
formats.extend(self._parse_smil_formats(
smil, smil_url, video_id, namespace))
if not formats and video.get('drm'):
- raise ExtractorError('This video is DRM protected.', expected=True)
+ self.raise_no_formats('This video is DRM protected.', expected=True)
self._sort_formats(formats)
subtitles = {}
unified_strdate,
compat_str,
determine_ext,
- ExtractorError,
update_url_query,
)
'vcodec': 'none' if (width == 0 and height == 0) else None,
})
if not formats and video_data.get('expired'):
- raise ExtractorError(
+ self.raise_no_formats(
'%s said: %s' % (self.IE_NAME, page_data['translations']['video_expired']),
expected=True)
self._sort_formats(formats)
subtitles_src = f[0].get('subtitles_src')
if subtitles_src:
subtitles.setdefault('en', []).append({'url': subtitles_src})
- if not formats:
- raise ExtractorError('Cannot find video formats')
process_formats(formats)
or 'unable to extract confirmation code')
if not formats and reason:
- raise ExtractorError(reason, expected=True)
+ self.raise_no_formats(reason, expected=True)
self._sort_formats(formats)
geo_restricted = True
continue
if not formats and geo_restricted:
- self.raise_geo_restricted(countries=['IN'])
+ self.raise_geo_restricted(countries=['IN'], metadata_available=True)
self._sort_formats(formats)
for f in formats:
extract_formats(src)
if not formats and '>GEO_IP_NOT_ALLOWED<' in playerpage:
- self.raise_geo_restricted(countries=['CZ'])
+ self.raise_geo_restricted(countries=['CZ'], metadata_available=True)
self._sort_formats(formats)
if not formats:
if 'title="This video is no longer available"' in webpage:
- raise ExtractorError(
+ self.raise_no_formats(
'Video %s is no longer available' % video_id, expected=True)
try:
from .common import InfoExtractor
from ..compat import compat_str
from ..utils import (
- ExtractorError,
int_or_none,
js_to_json,
str_or_none,
self._sort_formats(formats)
- if not formats[0].get('width'):
+ if formats and not formats[0].get('width'):
formats[0]['vcodec'] = 'none'
title = self._og_search_title(webpage)
if not formats:
archive_status = item.get('archiveStatus')
if archive_status != 'ARCHIVED':
- raise ExtractorError('this video has been ' + archive_status.lower(), expected=True)
+ self.raise_no_formats('this video has been ' + archive_status.lower(), expected=True)
self._sort_formats(formats)
info['formats'] = formats
return info
error = clip.get('error')
if not formats and error:
if error == 404:
- raise ExtractorError(
+ self.raise_no_formats(
'That clip does not exist.',
expected=True, video_id=video_id)
else:
- raise ExtractorError(
+ self.raise_no_formats(
'An unknown error occurred ({0}).'.format(error),
video_id=video_id)
})
if not formats and cloudcast.get('isExclusive'):
- self.raise_login_required()
+ self.raise_login_required(metadata_available=True)
self._sort_formats(formats)
if not formats:
if not self._downloader.params.get('allow_unplayable_formats') and drm:
- raise ExtractorError('This video is DRM protected.', expected=True)
+ self.raise_no_formats('This video is DRM protected.', expected=True)
return
self._sort_formats(formats)
if not formats:
payment_info = metadata.get('paymentInfo')
if payment_info:
- raise ExtractorError('This video is paid, subscribe to download it', expected=True)
+ self.raise_no_formats('This video is paid, subscribe to download it', expected=True)
self._sort_formats(formats)
)
from ..utils import (
determine_ext,
- ExtractorError,
float_or_none,
int_or_none,
try_get,
'fps': float_or_none(stream.get('framerate')),
})
if not formats and not auth_data.get('authorized'):
- raise ExtractorError('%s said: %s' % (
+ self.raise_no_formats('%s said: %s' % (
self.IE_NAME, auth_data['message']), expected=True)
self._sort_formats(formats)
formats.extend(self._extract_m3u8_formats(
m3u8_url, video_id, 'mp4', entry_protocol='m3u8_native',
m3u8_id='hls', fatal=False))
- if not formats:
+ if not formats and not self._downloader.params.get('ignore_no_formats'):
return
self._sort_formats(formats)
return {
})
if not formats and geoprotection is True:
- self.raise_geo_restricted(countries=self._GEO_COUNTRIES)
+ self.raise_geo_restricted(countries=self._GEO_COUNTRIES, metadata_available=True)
return dict((k, v) for k, v in {
'is_live': is_live,
if not formats:
if (not self._downloader.params.get('allow_unplayable_formats')
and xpath_text(video_xml, './Clip/DRM', default=None)):
- raise ExtractorError('This video is DRM protected.', expected=True)
+ self.raise_no_formats('This video is DRM protected.', expected=True)
ns_st_cds = pv('ns_st_cds')
if ns_st_cds != 'free':
raise ExtractorError('This video is %s.' % ns_st_cds, expected=True)
f['vcodec'] = 'none'
if not formats and info.get('policy') == 'BLOCK':
- self.raise_geo_restricted()
+ self.raise_geo_restricted(metadata_available=True)
self._sort_formats(formats)
user = info.get('user') or {}
continue
formats = self._extract_m3u8_formats(
video_url.replace('.smil', '.m3u8'), video_id, 'mp4', fatal=False)
- if not formats:
+ if not formats and not self._downloader.params.get('ignore_no_formats'):
continue
yield {
'id': video_id,
'format_id': ext + quality,
'url': video_url,
})
- if not formats:
+ if not formats and not self._downloader.params.get('ignore_no_formats'):
continue
entry['formats'] = formats
entries.append(entry)
if not formats and rights.get('geoBlockedSweden'):
self.raise_geo_restricted(
'This video is only available in Sweden',
- countries=self._GEO_COUNTRIES)
+ countries=self._GEO_COUNTRIES, metadata_available=True)
self._sort_formats(formats)
subtitles = {}
from .common import InfoExtractor
from ..utils import (
determine_ext,
- ExtractorError,
float_or_none,
int_or_none,
parse_iso8601,
for meta in (info.get('Metas') or []):
if (not self._downloader.params.get('allow_unplayable_formats')
and meta.get('Key') == 'Encryption' and meta.get('Value') == '1'):
- raise ExtractorError(
+ self.raise_no_formats(
'This video is DRM protected.', expected=True)
- # Most likely because geo-blocked
- raise ExtractorError('No downloadable videos found', expected=True)
+ # Most likely because geo-blocked if no formats and no DRM
self._sort_formats(formats)
thumbnails = []
'filesize': int_or_none(item.get('fileSize')),
})
if not formats and data.get('drmProtected'):
- raise ExtractorError('This video is DRM protected.', expected=True)
+ self.raise_no_formats('This video is DRM protected.', expected=True)
self._sort_formats(formats)
thumbnails = [{
video_id, ism_id='mss', fatal=False))
if not formats and info.get('is_geo_restricted'):
- self.raise_geo_restricted(countries=self._GEO_COUNTRIES)
+ self.raise_geo_restricted(countries=self._GEO_COUNTRIES, metadata_available=True)
self._sort_formats(formats)
if not formats and video.get('is_geo_blocked'):
self.raise_geo_restricted(
- 'This content might not be available in your country due to copyright reasons')
+ 'This content might not be available in your country due to copyright reasons',
+ metadata_available=True)
self._sort_formats(formats)
compat_urllib_parse_urlparse,
)
from ..utils import (
- ExtractorError,
int_or_none,
)
error = item.get('error')
if error:
if error in ('Данное видео недоступно для просмотра на территории этой страны', 'Данное видео доступно для просмотра только на территории России'):
- self.raise_geo_restricted(countries=['RU'])
- raise ExtractorError(error, expected=True)
+ self.raise_geo_restricted(countries=['RU'], metadata_available=True)
+ self.raise_no_formats(error, expected=True)
self._sort_formats(formats)
return {
)
from ..utils import (
int_or_none,
- ExtractorError,
)
})
formats.append(fmt)
- self._sort_formats(formats)
-
if not formats and video.get('vst') == 'dmca':
- raise ExtractorError(
+ self.raise_no_formats(
'This video has been removed in response to a complaint received under the US Digital Millennium Copyright Act.',
expected=True)
+ self._sort_formats(formats)
+
title = video['title']
description = video.get('description')
thumbnail = self._proto_relative_url(video.get('thumbnail_src'), scheme='http:')
extract_formats({delivery.get('format'): delivery.get('url')})
if not formats:
if delivery.get('drm'):
- raise ExtractorError('This video is DRM protected.', expected=True)
+ self.raise_no_formats('This video is DRM protected.', expected=True)
manifest_urls = self._download_json(
'http://www.wat.tv/get/webhtml/' + video_id, video_id, fatal=False)
if manifest_urls:
'm3u8_native', m3u8_id='hls', fatal=False))
if not formats and msg == 'geo restricted':
- self.raise_geo_restricted()
+ self.raise_geo_restricted(metadata_available=True)
self._sort_formats(formats)
if not formats:
if not self._downloader.params.get('allow_unplayable_formats') and streaming_data.get('licenseInfos'):
- raise ExtractorError(
+ self.raise_no_formats(
'This video is DRM protected.', expected=True)
pemr = try_get(
playability_status,
if not countries:
regions_allowed = search_meta('regionsAllowed')
countries = regions_allowed.split(',') if regions_allowed else None
- self.raise_geo_restricted(
- subreason, countries)
+ self.raise_geo_restricted(subreason, countries, metadata_available=True)
reason += '\n' + subreason
if reason:
- raise ExtractorError(reason, expected=True)
+ self.raise_no_formats(reason, expected=True)
self._sort_formats(formats)
from .common import InfoExtractor
from ..utils import (
- ExtractorError,
int_or_none,
)
return
msg = item['msg']
if msg == 'Sorry, this content is not available in your country.':
- self.raise_geo_restricted(countries=self._GEO_COUNTRIES)
- raise ExtractorError(msg, expected=True)
+ self.raise_geo_restricted(countries=self._GEO_COUNTRIES, metadata_available=True)
+ self.raise_no_formats(msg, expected=True)
self._sort_formats(formats)
subtitles = None
'-s', '--simulate',
action='store_true', dest='simulate', default=False,
help='Do not download the video and do not write anything to disk')
+ verbosity.add_option(
+ '--ignore-no-formats-error',
+ action='store_true', dest='ignore_no_formats_error', default=False,
+ help=(
+ 'Ignore "No video formats" error. Usefull for extracting metadata '
+ 'even if the video is not actually available for download (experimental)'))
+ verbosity.add_option(
+ '--no-ignore-no-formats-error',
+ action='store_false', dest='ignore_no_formats_error',
+ help='Throw error when no downloadable video formats are found (default)')
verbosity.add_option(
'--skip-download', '--no-download',
action='store_true', dest='skip_download', default=False,