1
0
mirror of https://github.com/yt-dlp/yt-dlp.git synced 2025-06-28 09:28:33 +00:00

revry extractor

This commit is contained in:
Max 2025-05-11 00:37:30 +01:00
parent b26bc32579
commit 59a52beefa
2 changed files with 111 additions and 0 deletions

View File

@ -1730,6 +1730,7 @@
from .restudy import RestudyIE from .restudy import RestudyIE
from .reuters import ReutersIE from .reuters import ReutersIE
from .reverbnation import ReverbNationIE from .reverbnation import ReverbNationIE
from .revry import RevryIE
from .rheinmaintv import RheinMainTVIE from .rheinmaintv import RheinMainTVIE
from .ridehome import RideHomeIE from .ridehome import RideHomeIE
from .rinsefm import ( from .rinsefm import (

110
yt_dlp/extractor/revry.py Normal file
View File

@ -0,0 +1,110 @@
from .brightcove import BrightcoveNewIE
from .common import InfoExtractor
from ..networking.exceptions import HTTPError
from ..utils import (
ExtractorError,
random_uuidv4,
smuggle_url,
time_seconds,
)
class RevryIE(InfoExtractor):
_VALID_URL = r'https?://watch\.revry\.tv/player/(?P<id>[0-9]+)'
_GEO_COUNTRIES = ['US']
_TESTS = [{
'url': 'https://watch.revry.tv/player/43772/stream?assetType=episodes',
'info_dict': {
'id': '6368611770112',
'ext': 'mp4',
'title': 'Full Stop',
'description': 'md5:4590409cef76b6500f96760c4b658aae',
'thumbnail': r're:^https?://.*\.jpg$',
'timestamp': 1739235272,
'upload_date': '20250211',
'uploader_id': '6122285389001',
'duration': 1638.955,
'tags': 'count:18',
},
'params': {
'skip_download': True,
},
}]
_ACCOUNT_ID = '6122285389001'
_AUTH_URL = 'https://beacon.playback.api.brightcove.com/revry/api/account/anonymous_login?device_type=web&duid={duid}'
_ASSET_INFO_URL = 'https://beacon.playback.api.brightcove.com/revry/api/account/{account_token}/asset_info/{video_id}?device_type=web&ngsw-bypass=1'
_BRIGHTCOVE_URL_TEMPLATE = 'https://players.brightcove.net/{account_id}/default_default/index.html?videoId={video_id}'
_AUTH_CACHE_NAMESPACE = 'revry'
_AUTH_CACHE_KEY = 'auth_token'
_DEVICE_ID_CACHE_KEY = 'device_id'
def _get_auth_token(self):
auth_data = self.cache.load(self._AUTH_CACHE_NAMESPACE, self._AUTH_CACHE_KEY)
if auth_data and auth_data.get('expires_at', 0) > time_seconds():
return auth_data.get('auth_token'), auth_data.get('account_token')
device_id = self.cache.load(self._AUTH_CACHE_NAMESPACE, self._DEVICE_ID_CACHE_KEY)
if not device_id:
device_id = random_uuidv4()
self.cache.store(self._AUTH_CACHE_NAMESPACE, self._DEVICE_ID_CACHE_KEY, device_id)
auth_response = self._download_json(
self._AUTH_URL.format(duid=device_id),
None, 'Downloading authentication token', data=b'{}',
headers={
'Content-Type': 'application/json',
'Accept': 'application/json',
})
auth_token = auth_response.get('auth_token')
account_token = auth_response.get('account_token')
if not auth_token:
self.report_warning('Failed to get authentication token')
return None, None
expires_at = time_seconds(seconds=auth_response.get('expires_in', 604800)) # Default to 7 days
auth_data = {
'auth_token': auth_token,
'account_token': account_token,
'expires_at': expires_at,
}
self.cache.store(self._AUTH_CACHE_NAMESPACE, self._AUTH_CACHE_KEY, auth_data)
return auth_token, account_token
def _real_extract(self, url):
video_id = self._match_id(url)
auth_token, account_token = self._get_auth_token()
if not auth_token:
self.raise_login_required('Failed to get authentication token')
try:
asset_info = self._download_json(
self._ASSET_INFO_URL.format(account_token=account_token, video_id=video_id),
video_id, 'Downloading asset info',
headers={
'Authorization': f'Bearer {auth_token}',
'Accept': 'application/json, text/plain, */*',
})
except ExtractorError as e:
if isinstance(e.cause, HTTPError) and e.cause.status == 404:
self.raise_geo_restricted(countries=self._GEO_COUNTRIES)
raise
video_playback_details = asset_info.get('data', {}).get('video_playback_details', [])
if not video_playback_details:
raise ExtractorError('No video playback details found', expected=True)
brightcove_video_id = video_playback_details[0].get('video_id')
if not brightcove_video_id:
raise ExtractorError('No Brightcove video ID found', expected=True)
brightcove_url = self._BRIGHTCOVE_URL_TEMPLATE.format(
account_id=self._ACCOUNT_ID,
video_id=brightcove_video_id)
return self.url_result(
smuggle_url(brightcove_url, {'referrer': url}),
ie=BrightcoveNewIE.ie_key(), video_id=brightcove_video_id)