From 25836db6bea78501c514bfbe5840f305b33afdcd Mon Sep 17 00:00:00 2001 From: pukkandan Date: Thu, 18 Aug 2022 21:35:18 +0530 Subject: [PATCH] [extractor/youtube] Add fallback to phantomjs Related #4635 --- yt_dlp/extractor/youtube.py | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/yt_dlp/extractor/youtube.py b/yt_dlp/extractor/youtube.py index a642f0705d..c624d8c8c0 100644 --- a/yt_dlp/extractor/youtube.py +++ b/yt_dlp/extractor/youtube.py @@ -17,6 +17,7 @@ import urllib.parse from .common import InfoExtractor, SearchInfoExtractor +from .openload import PhantomJSwrapper from ..compat import functools from ..jsinterp import JSInterpreter from ..utils import ( @@ -2624,8 +2625,23 @@ def _decrypt_nsig(self, s, video_id, player_url): if self.get_param('youtube_print_sig_code'): self.to_screen(f'Extracted nsig function from {player_id}:\n{func_code[1]}\n') - extract_nsig = self._cached(self._extract_n_function_from_code, 'nsig func', player_url) - ret = extract_nsig(jsi, func_code)(s) + try: + extract_nsig = self._cached(self._extract_n_function_from_code, 'nsig func', player_url) + ret = extract_nsig(jsi, func_code)(s) + except JSInterpreter.Exception as e: + try: + jsi = PhantomJSwrapper(self) + except ExtractorError: + raise e + self.report_warning( + f'Native nsig extraction failed: Trying with PhantomJS\n' + f' n = {s} ; player = {player_url}', video_id) + self.write_debug(e) + + args, func_body = func_code + ret = jsi.execute( + f'console.log(function({", ".join(args)}) {{ {func_body} }}({s!r}));', + video_id=video_id, note='Executing signature code').strip() self.write_debug(f'Decrypted nsig {s} => {ret}') return ret @@ -2655,9 +2671,15 @@ def _extract_n_function_from_code(self, jsi, func_code): func = jsi.extract_function_from_code(*func_code) def extract_nsig(s): - ret = func([s]) + try: + ret = func([s]) + except JSInterpreter.Exception: + raise + except Exception as e: + raise JSInterpreter.Exception(traceback.format_exc(), cause=e) + if ret.startswith('enhanced_except_'): - raise ExtractorError('Signature function returned an exception') + raise JSInterpreter.Exception('Signature function returned an exception') return ret return extract_nsig @@ -3240,9 +3262,12 @@ def _extract_formats_and_subtitles(self, streaming_data, video_id, player_url, i 'n': decrypt_nsig(query['n'][0], video_id, player_url) }) except ExtractorError as e: + phantomjs_hint = '' + if isinstance(e, JSInterpreter.Exception): + phantomjs_hint = f' Install {self._downloader._format_err("PhantomJS", self._downloader.Styles.EMPHASIS)} to workaround the issue\n' self.report_warning( - 'nsig extraction failed: You may experience throttling for some formats\n' - f'n = {query["n"][0]} ; player = {player_url}', video_id=video_id, only_once=True) + f'nsig extraction failed: You may experience throttling for some formats\n{phantomjs_hint}' + f' n = {query["n"][0]} ; player = {player_url}', video_id=video_id, only_once=True) self.write_debug(e, only_once=True) throttled = True