]> jfr.im git - yt-dlp.git/commitdiff
Add option `--ignore-no-formats-error`
authorpukkandan <redacted>
Sat, 17 Apr 2021 00:09:58 +0000 (05:39 +0530)
committerpukkandan <redacted>
Sat, 17 Apr 2021 03:10:30 +0000 (08:40 +0530)
* Ignores the "no video format" and similar errors
* Experimental - Some extractors may still throw these errors

39 files changed:
yt_dlp/YoutubeDL.py
yt_dlp/__init__.py
yt_dlp/extractor/afreecatv.py
yt_dlp/extractor/ard.py
yt_dlp/extractor/bbc.py
yt_dlp/extractor/brightcove.py
yt_dlp/extractor/channel9.py
yt_dlp/extractor/common.py
yt_dlp/extractor/corus.py
yt_dlp/extractor/disney.py
yt_dlp/extractor/facebook.py
yt_dlp/extractor/googledrive.py
yt_dlp/extractor/hotstar.py
yt_dlp/extractor/iprima.py
yt_dlp/extractor/keezmovies.py
yt_dlp/extractor/line.py
yt_dlp/extractor/medaltv.py
yt_dlp/extractor/mixcloud.py
yt_dlp/extractor/npo.py
yt_dlp/extractor/odnoklassniki.py
yt_dlp/extractor/ooyala.py
yt_dlp/extractor/philharmoniedeparis.py
yt_dlp/extractor/rai.py
yt_dlp/extractor/ruutu.py
yt_dlp/extractor/soundcloud.py
yt_dlp/extractor/sportdeutschland.py
yt_dlp/extractor/steam.py
yt_dlp/extractor/svt.py
yt_dlp/extractor/toggle.py
yt_dlp/extractor/tv2.py
yt_dlp/extractor/tv4.py
yt_dlp/extractor/tvplay.py
yt_dlp/extractor/videomore.py
yt_dlp/extractor/vube.py
yt_dlp/extractor/wat.py
yt_dlp/extractor/yahoo.py
yt_dlp/extractor/youtube.py
yt_dlp/extractor/zingmp3.py
yt_dlp/options.py

index d7cbdd04736d48c6adba1c9700511ab574cded72..7cda3fc8f2e3fbbd90e8313e4f6b610985b0fd64 100644 (file)
@@ -191,6 +191,9 @@ class YoutubeDL(object):
     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"
@@ -1884,7 +1887,10 @@ def sanitize_numeric_fields(info):
             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')
@@ -1948,13 +1954,15 @@ def is_wellformed(f):
 
         # 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
 
@@ -1994,19 +2002,25 @@ def is_wellformed(f):
 
         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):
index 90a3116ea47dc21453466930c69b96bb7e3dbf63..4f0684236ed692dfb653ad3f6e22ef50f712299a 100644 (file)
@@ -466,6 +466,7 @@ def report_args_compat(arg, name):
         '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,
index af0587ae60fcbc51fd153e756ca13946b2305816..016a4d24aa22f23f62b31e309baa6d4c645e007c 100644 (file)
@@ -323,7 +323,7 @@ def _real_extract(self, url):
                         '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()
index 294da7c51ad7beb60a344f253a7d3e5add64c7ea..4d90be7140d4f8403d5329ed6416c7cff2d014ac 100644 (file)
@@ -36,12 +36,12 @@ def _parse_media_info(self, media_info, video_id, fsk):
 
         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)
 
index e8d000bbb513a36fb8fb0bdfe66bd1611c039e67..333796c80b8f43b3da277a44a09a1d060687d2f0 100644 (file)
@@ -1242,7 +1242,7 @@ def extract_all(pattern):
         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)
 
index 8b29ca99375daaeaa7de0dd4dc8e065d4abde357..d2fd10064c3e58aba8c40d14c4dda9bb42eed700 100644 (file)
@@ -545,9 +545,9 @@ def build_format_id(kind):
             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)
 
index 09cacf6d3b7e56029ef675b93c970c7860660ada..258e96ca69053c503f9598c8a4b3fb6b8e09e921 100644 (file)
@@ -5,7 +5,6 @@
 from .common import InfoExtractor
 from ..utils import (
     clean_html,
-    ExtractorError,
     int_or_none,
     parse_iso8601,
     qualities,
@@ -187,14 +186,13 @@ def quality(quality_id, format_url):
                     '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', []):
index 40ea9339f0dff727258e571723e30a52604c4d42..9ead6db2d4dd8561e59b3b15d6606225c09dfff3 100644 (file)
@@ -968,15 +968,27 @@ def report_login(self):
         """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
@@ -1670,6 +1682,8 @@ def calculate_preference(self, format):
 
     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)
index e11aadf14fe960be6d9e8c583cf103f0b75ec057..de61f42e4191c15c065efe4fd38b06fb91d26893 100644 (file)
@@ -131,7 +131,7 @@ def _real_extract(self, url):
             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 = {}
index 0eee82fd6b6e79c9aa309f4a18080a3039d82208..e1ae62ac6565f182be29899446034d1e2f11ffc3 100644 (file)
@@ -9,7 +9,6 @@
     unified_strdate,
     compat_str,
     determine_ext,
-    ExtractorError,
     update_url_query,
 )
 
@@ -140,7 +139,7 @@ def _real_extract(self, url):
                 '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)
index 7a76dbb220f9b3e51e455fb551e4acbb8c9320c9..b68b90bd319c8f7e4b1919678c40b75671266b28 100644 (file)
@@ -625,8 +625,6 @@ def parse_attachment(attachment, key='media'):
             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)
 
index 4eefcb70cceeac37bc270fbbd62158f6e28a4b3a..7b5bf280ff05477753ba7d151ee566594f7150b8 100644 (file)
@@ -253,7 +253,7 @@ def add_source_format(urlh):
                             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)
 
index e2e92353987ac6b767aeebe89c61b29757d85650..22cccf2b265dbc0d3853ef597ea6e4482de9b600 100644 (file)
@@ -184,7 +184,7 @@ def _real_extract(self, url):
                     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:
index 648ae6741f11f27ae297aed06f41b0584972b395..28e6609723e814d016ac0e549062558d31aca1f1 100644 (file)
@@ -136,7 +136,7 @@ def extract_formats(format_url, format_key=None, lang=None):
                 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)
 
index c3eb74c1742bedc23ae125384b9ba39965f6cd95..cfdd0eb8e772c4e7c935cc756128c86e91890dbd 100644 (file)
@@ -101,7 +101,7 @@ def extract_format(format_url, height=None):
 
         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:
index 2526daa7716274ac31521b8d7b81d74f5bc9f9cb..41ac8d422e714e9d91021949e6f2f9d9647b6fda 100644 (file)
@@ -6,7 +6,6 @@
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
-    ExtractorError,
     int_or_none,
     js_to_json,
     str_or_none,
@@ -77,7 +76,7 @@ def _real_extract(self, url):
 
         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)
@@ -183,7 +182,7 @@ def _real_extract(self, url):
         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
index 1603b55f6f403106c4c9a0476ed3f4bb524ea3ee..4bca6f053c981f702f4708815134af955cea9305 100644 (file)
@@ -97,11 +97,11 @@ def add_item(container, item_url, height, id_key='format_id', item_id=None):
         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)
 
index 69319857dfb872fee9137d78cd89c433d812a594..b8ccd0ab4c7d4581d786ecd6ed76d36c6432197b 100644 (file)
@@ -157,7 +157,7 @@ def _real_extract(self, url):
                 })
 
         if not formats and cloudcast.get('isExclusive'):
-            self.raise_login_required()
+            self.raise_login_required(metadata_available=True)
 
         self._sort_formats(formats)
 
index ca6dbfc817ce0b8b9a2846da81426945f4a5cb6e..573a89092cdf0cef4495238d4f07cece8456f083 100644 (file)
@@ -247,7 +247,7 @@ def _get_info(self, url, video_id):
 
         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)
index 7ed9fac5510f5f69b9eb23c07163bd50f91fdca9..0ce2e37762c103c86544ea52c130ea19907ece75 100644 (file)
@@ -260,7 +260,7 @@ def _real_extract(self, url):
         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)
 
index eb957b8fefc9dd4fbbbad0279b4d87687a501b07..7204dfecd85edf80a843bd1dca1ea3aea9c59247 100644 (file)
@@ -10,7 +10,6 @@
 )
 from ..utils import (
     determine_ext,
-    ExtractorError,
     float_or_none,
     int_or_none,
     try_get,
@@ -85,7 +84,7 @@ def _extract(self, content_tree_url, video_id, domain=None, supportedformats=Non
                     '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)
 
index 03da64b116128f01893f047e747a1fb40af1e2df..9545adebf86e201263420a38b27ea67b72cb1786 100644 (file)
@@ -79,7 +79,7 @@ def extract_entry(source):
                 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 {
index 6c2191bb31acee2fc9375e9ebe5c8534c78aed74..05cf84ba5275092f7aaca60bdfdec40d65059730 100644 (file)
@@ -94,7 +94,7 @@ def _extract_relinker_info(self, relinker_url, video_id):
                 })
 
         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,
index f9f30e3dd2cf6b8dcff90fddd8398a378f3d1b67..5030c01cd6f6f6beb072684039521378ddd976f9 100644 (file)
@@ -202,7 +202,7 @@ def pv(name):
         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)
index 103b23bf7bdd7e4e68fc76814aa9d89f520451e9..35d34af0275e801ba9aee1e0767b35814a80edb4 100644 (file)
@@ -498,7 +498,7 @@ def add_format(f, protocol, is_preview=False):
             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 {}
index 3e497a9393ea99dc1962848ce1020e0ac5b59de3..e70d1a477840c25a7301e8e9af4f34304bc1233d 100644 (file)
@@ -77,7 +77,7 @@ def entries():
                         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,
index a6a191cebb4b98e46627ecc9ae8bd70071193ea6..c70bdefe28dfcce08ad1c44d282312f624c8064a 100644 (file)
@@ -139,7 +139,7 @@ def _real_extract(self, url):
                                         '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)
index aba9bb4474fac257f57d20558f160712aa3f19c5..5b377ea838add3a5bc046b58590906eb74995455 100644 (file)
@@ -49,7 +49,7 @@ def _extract_video(self, video_info, video_id):
         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 = {}
index 1e2a2d819c3990db8fcf3252a143f710014acb61..fe18410812885b02b7f66aa4e3b97886ce4d8776 100644 (file)
@@ -7,7 +7,6 @@
 from .common import InfoExtractor
 from ..utils import (
     determine_ext,
-    ExtractorError,
     float_or_none,
     int_or_none,
     parse_iso8601,
@@ -156,10 +155,9 @@ def _real_extract(self, url):
             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 = []
index 334b7d540499e047f14381f879abf9a443e3c999..f3480de56d22f3fb2f1309303f125586a6d62cef 100644 (file)
@@ -103,7 +103,7 @@ def _real_extract(self, url):
                         '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 = [{
index b73bab9a8be9f495a4cf7a8a1041f714639d9587..b8ad4fafc4aa29a963f5e94298cb3d5477732c88 100644 (file)
@@ -107,7 +107,7 @@ def _real_extract(self, url):
             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)
 
index 0d858c02599670fa76a1760314c3ede4af672d2d..739c61cdd4c2b70a06792818fe1d94c51242ef4c 100644 (file)
@@ -298,7 +298,8 @@ def _real_extract(self, url):
 
         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)
 
index e0c10aa5b011b9695ee0150db1f328a9ef80d8b7..05ae74e333cbd2446c3f071c353aea4e6189666b 100644 (file)
@@ -10,7 +10,6 @@
     compat_urllib_parse_urlparse,
 )
 from ..utils import (
-    ExtractorError,
     int_or_none,
 )
 
@@ -193,8 +192,8 @@ def _real_extract(self, url):
             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 {
index 8ce3a6b81b6ed69e5fd4960ab4721ecd45bf750e..c92b47e6346566b7eb8afecbffadaf5b66271307 100644 (file)
@@ -8,7 +8,6 @@
 )
 from ..utils import (
     int_or_none,
-    ExtractorError,
 )
 
 
@@ -125,13 +124,13 @@ def _real_extract(self, url):
                 })
             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:')
index f1bccc2d6b2ac79f93e53e3e67f3294bcf21a8e9..05dcc1f17eefb0e60a8dabf7bee3a885f4f9b2fc 100644 (file)
@@ -87,7 +87,7 @@ def extract_formats(manifest_urls):
         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:
index a17b10d6eb867a5db42755aa45dde14e35f5c6fa..ecf2f5f48bdea3b5949cbc5ddc46260109a03e22 100644 (file)
@@ -239,7 +239,7 @@ def _extract_yahoo_video(self, video_id, country):
                 '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)
 
index 6d5ef0193c3d12365053f1c834660d00d3bdc03d..6c1a5b8819889377277a496fbbb984dcc986bf38 100644 (file)
@@ -2050,7 +2050,7 @@ def feed_entry(name):
 
         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,
@@ -2065,11 +2065,10 @@ def feed_entry(name):
                     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)
 
index 207c04f5ea54797e732740b365fbe3ef6211dfd8..a3edc158fdd868273f5c155d26b84181999a7b76 100644 (file)
@@ -3,7 +3,6 @@
 
 from .common import InfoExtractor
 from ..utils import (
-    ExtractorError,
     int_or_none,
 )
 
@@ -48,8 +47,8 @@ def _extract_item(self, item, fatal):
                 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
index cced9fb898aabc2fe1ec9f8d9893c2409a0dfe13..fef1e4b1521dfbefba965e80a4b14edf0342270c 100644 (file)
@@ -749,6 +749,16 @@ def _dict_from_multiple_values_options_callback(
         '-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,