mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-12-14 23:32:33 +00:00
[extractor/youtube] Add support for Shorts audio pivot feed (#4932)
This feed shows Shorts using the audio of a given video. ytshortsap: prefix can be used as a shortcut until YouTube implements an official view. Closes #4911 Authored by: coletdjnz
This commit is contained in:
parent
4cca2eb1bf
commit
80eb0bd9b9
2 changed files with 40 additions and 2 deletions
|
@ -21,6 +21,7 @@ from .youtube import ( # Youtube is moved to the top to improve performance
|
||||||
YoutubeYtBeIE,
|
YoutubeYtBeIE,
|
||||||
YoutubeYtUserIE,
|
YoutubeYtUserIE,
|
||||||
YoutubeWatchLaterIE,
|
YoutubeWatchLaterIE,
|
||||||
|
YoutubeShortsAudioPivotIE
|
||||||
)
|
)
|
||||||
|
|
||||||
from .abc import (
|
from .abc import (
|
||||||
|
|
|
@ -4327,8 +4327,8 @@ class YoutubeTabBaseInfoExtractor(YoutubeBaseInfoExtractor):
|
||||||
yield self._extract_video(renderer)
|
yield self._extract_video(renderer)
|
||||||
|
|
||||||
def _rich_entries(self, rich_grid_renderer):
|
def _rich_entries(self, rich_grid_renderer):
|
||||||
renderer = try_get(
|
renderer = traverse_obj(
|
||||||
rich_grid_renderer, lambda x: x['content']['videoRenderer'], dict) or {}
|
rich_grid_renderer, ('content', ('videoRenderer', 'reelItemRenderer')), get_all=False) or {}
|
||||||
video_id = renderer.get('videoId')
|
video_id = renderer.get('videoId')
|
||||||
if not video_id:
|
if not video_id:
|
||||||
return
|
return
|
||||||
|
@ -5640,6 +5640,16 @@ class YoutubeTabIE(YoutubeTabBaseInfoExtractor):
|
||||||
'playlist_mincount': 1,
|
'playlist_mincount': 1,
|
||||||
'params': {'extractor_args': {'youtube': {'lang': ['ja']}}},
|
'params': {'extractor_args': {'youtube': {'lang': ['ja']}}},
|
||||||
'expected_warnings': ['Preferring "ja"'],
|
'expected_warnings': ['Preferring "ja"'],
|
||||||
|
}, {
|
||||||
|
# shorts audio pivot for 2GtVksBMYFM.
|
||||||
|
'url': 'https://www.youtube.com/feed/sfv_audio_pivot?bp=8gUrCikSJwoLMkd0VmtzQk1ZRk0SCzJHdFZrc0JNWUZNGgsyR3RWa3NCTVlGTQ==',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'sfv_audio_pivot',
|
||||||
|
'title': 'sfv_audio_pivot',
|
||||||
|
'tags': [],
|
||||||
|
},
|
||||||
|
'playlist_mincount': 50,
|
||||||
|
|
||||||
}]
|
}]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -6307,6 +6317,33 @@ class YoutubeStoriesIE(InfoExtractor):
|
||||||
ie=YoutubeTabIE, video_id=playlist_id)
|
ie=YoutubeTabIE, video_id=playlist_id)
|
||||||
|
|
||||||
|
|
||||||
|
class YoutubeShortsAudioPivotIE(InfoExtractor):
|
||||||
|
IE_DESC = 'YouTube Shorts audio pivot (Shorts using audio of a given video); "ytshortsap:" prefix'
|
||||||
|
IE_NAME = 'youtube:shorts:pivot:audio'
|
||||||
|
_VALID_URL = f'(?x)^ytshortsap:{YoutubeIE._VALID_URL[5:]}'
|
||||||
|
_TESTS = [{
|
||||||
|
'url': 'ytshortsap:https://www.youtube.com/shorts/Lyj-MZSAA9o?feature=share',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'ytshortsap:Lyj-MZSAA9o',
|
||||||
|
'only_matching': True,
|
||||||
|
}]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _generate_audio_pivot_params(video_id):
|
||||||
|
"""
|
||||||
|
Generates sfv_audio_pivot browse params for this video id
|
||||||
|
"""
|
||||||
|
pb_params = b'\xf2\x05+\n)\x12\'\n\x0b%b\x12\x0b%b\x1a\x0b%b' % ((video_id.encode(),) * 3)
|
||||||
|
return urllib.parse.quote(base64.b64encode(pb_params).decode())
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
video_id = self._match_id(url)
|
||||||
|
return self.url_result(
|
||||||
|
f'https://www.youtube.com/feed/sfv_audio_pivot?bp={self._generate_audio_pivot_params(video_id)}',
|
||||||
|
ie=YoutubeTabIE)
|
||||||
|
|
||||||
|
|
||||||
class YoutubeTruncatedURLIE(InfoExtractor):
|
class YoutubeTruncatedURLIE(InfoExtractor):
|
||||||
IE_NAME = 'youtube:truncated_url'
|
IE_NAME = 'youtube:truncated_url'
|
||||||
IE_DESC = False # Do not list
|
IE_DESC = False # Do not list
|
||||||
|
|
Loading…
Reference in a new issue