mirror of
https://github.com/l1ving/youtube-dl
synced 2025-03-11 06:27:14 +08:00
Merge pull request #113 from ytdl-org/master
[pull] master from ytdl-org:master
This commit is contained in:
commit
c1db170e0e
@ -10,7 +10,6 @@ from .adobepass import AdobePassIE
|
|||||||
from ..compat import compat_urllib_parse_unquote
|
from ..compat import compat_urllib_parse_unquote
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
smuggle_url,
|
smuggle_url,
|
||||||
try_get,
|
|
||||||
update_url_query,
|
update_url_query,
|
||||||
int_or_none,
|
int_or_none,
|
||||||
)
|
)
|
||||||
@ -85,27 +84,41 @@ class NBCIE(AdobePassIE):
|
|||||||
permalink, video_id = re.match(self._VALID_URL, url).groups()
|
permalink, video_id = re.match(self._VALID_URL, url).groups()
|
||||||
permalink = 'http' + compat_urllib_parse_unquote(permalink)
|
permalink = 'http' + compat_urllib_parse_unquote(permalink)
|
||||||
response = self._download_json(
|
response = self._download_json(
|
||||||
'https://api.nbc.com/v3/videos', video_id, query={
|
'https://friendship.nbc.co/v2/graphql', video_id, query={
|
||||||
'filter[permalink]': permalink,
|
'query': '''{
|
||||||
'fields[videos]': 'description,entitlement,episodeNumber,guid,keywords,seasonNumber,title,vChipRating',
|
page(name: "%s", platform: web, type: VIDEO, userId: "0") {
|
||||||
'fields[shows]': 'shortTitle',
|
data {
|
||||||
'include': 'show.shortTitle',
|
... on VideoPageData {
|
||||||
|
description
|
||||||
|
episodeNumber
|
||||||
|
keywords
|
||||||
|
locked
|
||||||
|
mpxAccountId
|
||||||
|
mpxGuid
|
||||||
|
rating
|
||||||
|
seasonNumber
|
||||||
|
secondaryTitle
|
||||||
|
seriesShortTitle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}''' % permalink,
|
||||||
})
|
})
|
||||||
video_data = response['data'][0]['attributes']
|
video_data = response['data']['page']['data']
|
||||||
query = {
|
query = {
|
||||||
'mbr': 'true',
|
'mbr': 'true',
|
||||||
'manifest': 'm3u',
|
'manifest': 'm3u',
|
||||||
}
|
}
|
||||||
video_id = video_data['guid']
|
video_id = video_data['mpxGuid']
|
||||||
title = video_data['title']
|
title = video_data['secondaryTitle']
|
||||||
if video_data.get('entitlement') == 'auth':
|
if video_data.get('locked'):
|
||||||
resource = self._get_mvpd_resource(
|
resource = self._get_mvpd_resource(
|
||||||
'nbcentertainment', title, video_id,
|
'nbcentertainment', title, video_id,
|
||||||
video_data.get('vChipRating'))
|
video_data.get('rating'))
|
||||||
query['auth'] = self._extract_mvpd_auth(
|
query['auth'] = self._extract_mvpd_auth(
|
||||||
url, video_id, 'nbcentertainment', resource)
|
url, video_id, 'nbcentertainment', resource)
|
||||||
theplatform_url = smuggle_url(update_url_query(
|
theplatform_url = smuggle_url(update_url_query(
|
||||||
'http://link.theplatform.com/s/NnzsPC/media/guid/2410887629/' + video_id,
|
'http://link.theplatform.com/s/NnzsPC/media/guid/%s/%s' % (video_data.get('mpxAccountId') or '2410887629', video_id),
|
||||||
query), {'force_smil_url': True})
|
query), {'force_smil_url': True})
|
||||||
return {
|
return {
|
||||||
'_type': 'url_transparent',
|
'_type': 'url_transparent',
|
||||||
@ -117,7 +130,7 @@ class NBCIE(AdobePassIE):
|
|||||||
'season_number': int_or_none(video_data.get('seasonNumber')),
|
'season_number': int_or_none(video_data.get('seasonNumber')),
|
||||||
'episode_number': int_or_none(video_data.get('episodeNumber')),
|
'episode_number': int_or_none(video_data.get('episodeNumber')),
|
||||||
'episode': title,
|
'episode': title,
|
||||||
'series': try_get(response, lambda x: x['included'][0]['attributes']['shortTitle']),
|
'series': video_data.get('seriesShortTitle'),
|
||||||
'ie_key': 'ThePlatform',
|
'ie_key': 'ThePlatform',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ from ..utils import (
|
|||||||
NO_DEFAULT,
|
NO_DEFAULT,
|
||||||
OnDemandPagedList,
|
OnDemandPagedList,
|
||||||
parse_filesize,
|
parse_filesize,
|
||||||
qualities,
|
|
||||||
RegexNotFoundError,
|
RegexNotFoundError,
|
||||||
sanitized_Request,
|
sanitized_Request,
|
||||||
smuggle_url,
|
smuggle_url,
|
||||||
@ -211,6 +210,7 @@ class VimeoBaseInfoExtractor(InfoExtractor):
|
|||||||
video_uploader_url = owner.get('url')
|
video_uploader_url = owner.get('url')
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
'id': video_id,
|
||||||
'title': self._live_title(video_title) if is_live else video_title,
|
'title': self._live_title(video_title) if is_live else video_title,
|
||||||
'uploader': owner.get('name'),
|
'uploader': owner.get('name'),
|
||||||
'uploader_id': video_uploader_url.split('/')[-1] if video_uploader_url else None,
|
'uploader_id': video_uploader_url.split('/')[-1] if video_uploader_url else None,
|
||||||
@ -736,7 +736,6 @@ class VimeoIE(VimeoBaseInfoExtractor):
|
|||||||
channel_url = 'https://vimeo.com/channels/%s' % channel_id if channel_id else None
|
channel_url = 'https://vimeo.com/channels/%s' % channel_id if channel_id else None
|
||||||
|
|
||||||
info_dict = {
|
info_dict = {
|
||||||
'id': video_id,
|
|
||||||
'formats': formats,
|
'formats': formats,
|
||||||
'timestamp': unified_timestamp(timestamp),
|
'timestamp': unified_timestamp(timestamp),
|
||||||
'description': video_description,
|
'description': video_description,
|
||||||
@ -1067,7 +1066,6 @@ class VimeoReviewIE(VimeoBaseInfoExtractor):
|
|||||||
if source_format:
|
if source_format:
|
||||||
info_dict['formats'].append(source_format)
|
info_dict['formats'].append(source_format)
|
||||||
self._vimeo_sort_formats(info_dict['formats'])
|
self._vimeo_sort_formats(info_dict['formats'])
|
||||||
info_dict['id'] = video_id
|
|
||||||
return info_dict
|
return info_dict
|
||||||
|
|
||||||
|
|
||||||
@ -1121,94 +1119,17 @@ class VimeoLikesIE(VimeoChannelIE):
|
|||||||
return self._extract_videos(user_id, 'https://vimeo.com/%s/likes' % user_id)
|
return self._extract_videos(user_id, 'https://vimeo.com/%s/likes' % user_id)
|
||||||
|
|
||||||
|
|
||||||
class VHXEmbedIE(InfoExtractor):
|
class VHXEmbedIE(VimeoBaseInfoExtractor):
|
||||||
IE_NAME = 'vhx:embed'
|
IE_NAME = 'vhx:embed'
|
||||||
_VALID_URL = r'https?://embed\.vhx\.tv/videos/(?P<id>\d+)'
|
_VALID_URL = r'https?://embed\.vhx\.tv/videos/(?P<id>\d+)'
|
||||||
|
|
||||||
def _call_api(self, video_id, access_token, path='', query=None):
|
|
||||||
return self._download_json(
|
|
||||||
'https://api.vhx.tv/videos/' + video_id + path, video_id, headers={
|
|
||||||
'Authorization': 'Bearer ' + access_token,
|
|
||||||
}, query=query)
|
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
video_id = self._match_id(url)
|
video_id = self._match_id(url)
|
||||||
webpage = self._download_webpage(url, video_id)
|
webpage = self._download_webpage(url, video_id)
|
||||||
credentials = self._parse_json(self._search_regex(
|
config_url = self._parse_json(self._search_regex(
|
||||||
r'(?s)credentials\s*:\s*({.+?}),', webpage,
|
r'window\.OTTData\s*=\s*({.+})', webpage,
|
||||||
'config'), video_id, js_to_json)
|
'ott data'), video_id, js_to_json)['config_url']
|
||||||
access_token = credentials['access_token']
|
config = self._download_json(config_url, video_id)
|
||||||
|
info = self._parse_config(config, video_id)
|
||||||
query = {}
|
self._vimeo_sort_formats(info['formats'])
|
||||||
for k, v in credentials.items():
|
return info
|
||||||
if k in ('authorization', 'authUserToken', 'ticket') and v and v != 'undefined':
|
|
||||||
if k == 'authUserToken':
|
|
||||||
query['auth_user_token'] = v
|
|
||||||
else:
|
|
||||||
query[k] = v
|
|
||||||
files = self._call_api(video_id, access_token, '/files', query)
|
|
||||||
|
|
||||||
formats = []
|
|
||||||
for f in files:
|
|
||||||
href = try_get(f, lambda x: x['_links']['source']['href'])
|
|
||||||
if not href:
|
|
||||||
continue
|
|
||||||
method = f.get('method')
|
|
||||||
if method == 'hls':
|
|
||||||
formats.extend(self._extract_m3u8_formats(
|
|
||||||
href, video_id, 'mp4', 'm3u8_native',
|
|
||||||
m3u8_id='hls', fatal=False))
|
|
||||||
elif method == 'dash':
|
|
||||||
formats.extend(self._extract_mpd_formats(
|
|
||||||
href, video_id, mpd_id='dash', fatal=False))
|
|
||||||
else:
|
|
||||||
fmt = {
|
|
||||||
'filesize': int_or_none(try_get(f, lambda x: x['size']['bytes'])),
|
|
||||||
'format_id': 'http',
|
|
||||||
'preference': 1,
|
|
||||||
'url': href,
|
|
||||||
'vcodec': f.get('codec'),
|
|
||||||
}
|
|
||||||
quality = f.get('quality')
|
|
||||||
if quality:
|
|
||||||
fmt.update({
|
|
||||||
'format_id': 'http-' + quality,
|
|
||||||
'height': int_or_none(self._search_regex(r'(\d+)p', quality, 'height', default=None)),
|
|
||||||
})
|
|
||||||
formats.append(fmt)
|
|
||||||
self._sort_formats(formats)
|
|
||||||
|
|
||||||
video_data = self._call_api(video_id, access_token)
|
|
||||||
title = video_data.get('title') or video_data['name']
|
|
||||||
|
|
||||||
subtitles = {}
|
|
||||||
for subtitle in try_get(video_data, lambda x: x['tracks']['subtitles'], list) or []:
|
|
||||||
lang = subtitle.get('srclang') or subtitle.get('label')
|
|
||||||
for _link in subtitle.get('_links', {}).values():
|
|
||||||
href = _link.get('href')
|
|
||||||
if not href:
|
|
||||||
continue
|
|
||||||
subtitles.setdefault(lang, []).append({
|
|
||||||
'url': href,
|
|
||||||
})
|
|
||||||
|
|
||||||
q = qualities(['small', 'medium', 'large', 'source'])
|
|
||||||
thumbnails = []
|
|
||||||
for thumbnail_id, thumbnail_url in video_data.get('thumbnail', {}).items():
|
|
||||||
thumbnails.append({
|
|
||||||
'id': thumbnail_id,
|
|
||||||
'url': thumbnail_url,
|
|
||||||
'preference': q(thumbnail_id),
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
|
||||||
'id': video_id,
|
|
||||||
'title': title,
|
|
||||||
'description': video_data.get('description'),
|
|
||||||
'duration': int_or_none(try_get(video_data, lambda x: x['duration']['seconds'])),
|
|
||||||
'formats': formats,
|
|
||||||
'subtitles': subtitles,
|
|
||||||
'thumbnails': thumbnails,
|
|
||||||
'timestamp': unified_timestamp(video_data.get('created_at')),
|
|
||||||
'view_count': int_or_none(video_data.get('plays_count')),
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user