diff options
-rw-r--r-- | .github/workflows/build.yml | 2 | ||||
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | youtube_dlc/downloader/common.py | 11 | ||||
-rw-r--r-- | youtube_dlc/extractor/skyitalia.py | 4 | ||||
-rw-r--r-- | youtube_dlc/extractor/viki.py | 20 | ||||
-rw-r--r-- | youtube_dlc/extractor/youtube.py | 125 | ||||
-rw-r--r-- | youtube_dlc/options.py | 2 |
7 files changed, 96 insertions, 73 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f5d94dc49..2bf54cd58 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: '3.x' + python-version: '3.8' - name: Install packages run: sudo apt-get -y install zip pandoc man - name: Bump version @@ -1,6 +1,5 @@ [](https://travis-ci.com/blackjack4494/yt-dlc) [](https://pypi.org/project/youtube-dlc) -[](https://pepy.tech/project/youtube-dlc) [](https://gitter.im/youtube-dlc) [](https://github.com/blackjack4494/youtube-dlc/blob/master/LICENSE) @@ -44,6 +43,10 @@ You may want to use `python3` instead of `python` python -m pip install --upgrade youtube-dlc +If you want to install the current master branch + + python -m pip install git+https://github.com/blackjack4494/yt-dlc + **UNIX** (Linux, macOS, etc.) Using wget: diff --git a/youtube_dlc/downloader/common.py b/youtube_dlc/downloader/common.py index 460364a0b..c65500d61 100644 --- a/youtube_dlc/downloader/common.py +++ b/youtube_dlc/downloader/common.py @@ -364,11 +364,12 @@ class FileDownloader(object): else '%.2f' % sleep_interval)) time.sleep(sleep_interval) else: - sleep_interval_sub = self.params.get('sleep_interval_subtitles') - self.to_screen( - '[download] Sleeping %s seconds...' % ( - int(sleep_interval_sub))) - time.sleep(sleep_interval_sub) + if self.params.get('sleep_interval_subtitles') > 0: + sleep_interval_sub = self.params.get('sleep_interval_subtitles') + self.to_screen( + '[download] Sleeping %s seconds...' % ( + sleep_interval_sub)) + time.sleep(sleep_interval_sub) return self.real_download(filename, info_dict) def real_download(self, filename, info_dict): diff --git a/youtube_dlc/extractor/skyitalia.py b/youtube_dlc/extractor/skyitalia.py index 3c7bd465d..22a6be2be 100644 --- a/youtube_dlc/extractor/skyitalia.py +++ b/youtube_dlc/extractor/skyitalia.py @@ -13,6 +13,7 @@ class SkyItaliaBaseIE(InfoExtractor): 'high': [854, 480], 'hd': [1280, 720] } + _GEO_BYPASS = False def _extract_video_id(self, url): webpage = self._download_webpage(url, 'skyitalia') @@ -43,6 +44,9 @@ class SkyItaliaBaseIE(InfoExtractor): 'height': r[1] }) + if not formats and video_data.get('geob') == 1: + self.raise_geo_restricted(countries=['IT']) + self._sort_formats(formats) title = video_data.get('title') thumb = video_data.get('thumb') diff --git a/youtube_dlc/extractor/viki.py b/youtube_dlc/extractor/viki.py index f8e360338..0f188f84d 100644 --- a/youtube_dlc/extractor/viki.py +++ b/youtube_dlc/extractor/viki.py @@ -308,19 +308,17 @@ class VikiIE(VikiBaseIE): 'url': thumbnail.get('url'), }) - stream_ids = [] - for f in formats: - s_id = f.get('stream_id') - if s_id is not None: - stream_ids.append(s_id) + new_video = self._download_json( + 'https://www.viki.com/api/videos/%s' % video_id, video_id, + 'Downloading new video JSON to get subtitles', headers={'x-viki-app-ver': '2.2.5.1428709186'}, expected_status=[200, 400, 404]) subtitles = {} - for subtitle_lang, _ in video.get('subtitle_completions', {}).items(): - subtitles[subtitle_lang] = [{ - 'ext': subtitles_format, - 'url': self._prepare_call( - 'videos/%s/subtitles/%s.%s?stream_id=%s' % (video_id, subtitle_lang, subtitles_format, stream_ids[0])), - } for subtitles_format in ('srt', 'vtt')] + for sub in new_video.get('streamSubtitles').get('dash'): + subtitles[sub.get('srclang')] = [{ + 'ext': 'vtt', + 'url': sub.get('src'), + 'completion': sub.get('percentage'), + }] result = { 'id': video_id, diff --git a/youtube_dlc/extractor/youtube.py b/youtube_dlc/extractor/youtube.py index d8f0dab1f..2e70ad6fa 100644 --- a/youtube_dlc/extractor/youtube.py +++ b/youtube_dlc/extractor/youtube.py @@ -1399,6 +1399,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor): # https://github.com/ytdl-org/youtube-dl/pull/7599) r';ytplayer\.config\s*=\s*({.+?});ytplayer', r';ytplayer\.config\s*=\s*({.+?});', + r'ytInitialPlayerResponse\s*=\s*({.+?});var meta' ) config = self._search_regex( patterns, webpage, 'ytplayer.config', default=None) @@ -1454,10 +1455,11 @@ class YoutubeIE(YoutubeBaseInfoExtractor): self._downloader.report_warning(err_msg) return {} try: - args = player_config['args'] - caption_url = args.get('ttsurl') - if caption_url: + if "args" in player_config and "ttsurl" in player_config["args"]: + args = player_config['args'] + caption_url = args['ttsurl'] timestamp = args['timestamp'] + # We get the available subtitles list_params = compat_urllib_parse_urlencode({ 'type': 'list', @@ -1513,40 +1515,50 @@ class YoutubeIE(YoutubeBaseInfoExtractor): return captions # New captions format as of 22.06.2017 - player_response = args.get('player_response') - if player_response and isinstance(player_response, compat_str): - player_response = self._parse_json( - player_response, video_id, fatal=False) - if player_response: - renderer = player_response['captions']['playerCaptionsTracklistRenderer'] - caption_tracks = renderer['captionTracks'] - for caption_track in caption_tracks: - if 'kind' not in caption_track: - # not an automatic transcription - continue - base_url = caption_track['baseUrl'] - sub_lang_list = [] - for lang in renderer['translationLanguages']: - lang_code = lang.get('languageCode') - if lang_code: - sub_lang_list.append(lang_code) - return make_captions(base_url, sub_lang_list) - - self._downloader.report_warning("Couldn't find automatic captions for %s" % video_id) - return {} - # Some videos don't provide ttsurl but rather caption_tracks and - # caption_translation_languages (e.g. 20LmZk1hakA) - # Does not used anymore as of 22.06.2017 - caption_tracks = args['caption_tracks'] - caption_translation_languages = args['caption_translation_languages'] - caption_url = compat_parse_qs(caption_tracks.split(',')[0])['u'][0] - sub_lang_list = [] - for lang in caption_translation_languages.split(','): - lang_qs = compat_parse_qs(compat_urllib_parse_unquote_plus(lang)) - sub_lang = lang_qs.get('lc', [None])[0] - if sub_lang: - sub_lang_list.append(sub_lang) - return make_captions(caption_url, sub_lang_list) + if "args" in player_config: + player_response = player_config["args"].get('player_response') + else: + # New player system (ytInitialPlayerResponse) as of October 2020 + player_response = player_config + + if player_response: + if isinstance(player_response, compat_str): + player_response = self._parse_json( + player_response, video_id, fatal=False) + + renderer = player_response['captions']['playerCaptionsTracklistRenderer'] + caption_tracks = renderer['captionTracks'] + for caption_track in caption_tracks: + if 'kind' not in caption_track: + # not an automatic transcription + continue + base_url = caption_track['baseUrl'] + sub_lang_list = [] + for lang in renderer['translationLanguages']: + lang_code = lang.get('languageCode') + if lang_code: + sub_lang_list.append(lang_code) + return make_captions(base_url, sub_lang_list) + + self._downloader.report_warning("Couldn't find automatic captions for %s" % video_id) + return {} + + if "args" in player_config: + args = player_config["args"] + + # Some videos don't provide ttsurl but rather caption_tracks and + # caption_translation_languages (e.g. 20LmZk1hakA) + # Does not used anymore as of 22.06.2017 + caption_tracks = args['caption_tracks'] + caption_translation_languages = args['caption_translation_languages'] + caption_url = compat_parse_qs(caption_tracks.split(',')[0])['u'][0] + sub_lang_list = [] + for lang in caption_translation_languages.split(','): + lang_qs = compat_parse_qs(compat_urllib_parse_unquote_plus(lang)) + sub_lang = lang_qs.get('lc', [None])[0] + if sub_lang: + sub_lang_list.append(sub_lang) + return make_captions(caption_url, sub_lang_list) # An extractor error can be raise by the download process if there are # no automatic captions but there are subtitles except (KeyError, IndexError, ExtractorError): @@ -1822,21 +1834,24 @@ class YoutubeIE(YoutubeBaseInfoExtractor): # Try looking directly into the video webpage ytplayer_config = self._get_ytplayer_config(video_id, video_webpage) if ytplayer_config: - args = ytplayer_config['args'] - if args.get('url_encoded_fmt_stream_map') or args.get('hlsvp'): - # Convert to the same format returned by compat_parse_qs - video_info = dict((k, [v]) for k, v in args.items()) - add_dash_mpd(video_info) - # Rental video is not rented but preview is available (e.g. - # https://www.youtube.com/watch?v=yYr8q0y5Jfg, - # https://github.com/ytdl-org/youtube-dl/issues/10532) - if not video_info and args.get('ypc_vid'): - return self.url_result( - args['ypc_vid'], YoutubeIE.ie_key(), video_id=args['ypc_vid']) - if args.get('livestream') == '1' or args.get('live_playback') == 1: - is_live = True - if not player_response: - player_response = extract_player_response(args.get('player_response'), video_id) + args = ytplayer_config.get("args") + if args is not None: + if args.get('url_encoded_fmt_stream_map') or args.get('hlsvp'): + # Convert to the same format returned by compat_parse_qs + video_info = dict((k, [v]) for k, v in args.items()) + add_dash_mpd(video_info) + # Rental video is not rented but preview is available (e.g. + # https://www.youtube.com/watch?v=yYr8q0y5Jfg, + # https://github.com/ytdl-org/youtube-dl/issues/10532) + if not video_info and args.get('ypc_vid'): + return self.url_result( + args['ypc_vid'], YoutubeIE.ie_key(), video_id=args['ypc_vid']) + if args.get('livestream') == '1' or args.get('live_playback') == 1: + is_live = True + if not player_response: + player_response = extract_player_response(args.get('player_response'), video_id) + elif not player_response: + player_response = ytplayer_config if not video_info or self._downloader.params.get('youtube_include_dash_manifest', True): add_dash_mpd_pr(player_response) else: @@ -1866,8 +1881,8 @@ class YoutubeIE(YoutubeBaseInfoExtractor): age_gate = False # Try looking directly into the video webpage ytplayer_config = self._get_ytplayer_config(video_id, video_webpage) - if ytplayer_config: - args = ytplayer_config['args'] + args = ytplayer_config.get("args") + if args is not None: if args.get('url_encoded_fmt_stream_map') or args.get('hlsvp'): # Convert to the same format returned by compat_parse_qs video_info = dict((k, [v]) for k, v in args.items()) @@ -1882,6 +1897,8 @@ class YoutubeIE(YoutubeBaseInfoExtractor): is_live = True if not player_response: player_response = extract_player_response(args.get('player_response'), video_id) + elif not player_response: + player_response = ytplayer_config if not video_info or self._downloader.params.get('youtube_include_dash_manifest', True): add_dash_mpd_pr(player_response) diff --git a/youtube_dlc/options.py b/youtube_dlc/options.py index 66b45220c..3c8a1305e 100644 --- a/youtube_dlc/options.py +++ b/youtube_dlc/options.py @@ -582,7 +582,7 @@ def parseOpts(overrideArguments=None): 'along with --min-sleep-interval.')) workarounds.add_option( '--sleep-subtitles', - dest='sleep_interval_subtitles', action='store_true', default=0, + dest='sleep_interval_subtitles', default=0, type=int, help='Enforce sleep interval on subtitles as well') verbosity = optparse.OptionGroup(parser, 'Verbosity / Simulation Options') |