mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2025-03-10 10:00:12 +01:00
Compare commits
2 Commits
7177148087
...
ba7950e79b
Author | SHA1 | Date | |
---|---|---|---|
|
ba7950e79b | ||
|
9a986b9cf3 |
@ -19,7 +19,6 @@ from ..utils import (
|
|||||||
join_nonempty,
|
join_nonempty,
|
||||||
parse_bitrate,
|
parse_bitrate,
|
||||||
parse_duration,
|
parse_duration,
|
||||||
parse_filesize,
|
|
||||||
parse_iso8601,
|
parse_iso8601,
|
||||||
parse_resolution,
|
parse_resolution,
|
||||||
qualities,
|
qualities,
|
||||||
@ -366,15 +365,10 @@ class NiconicoIE(InfoExtractor):
|
|||||||
if not audio_quality.get('isAvailable') or not video_quality.get('isAvailable'):
|
if not audio_quality.get('isAvailable') or not video_quality.get('isAvailable'):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def extract_video_quality(video_quality):
|
|
||||||
return parse_filesize('%sB' % self._search_regex(
|
|
||||||
r'\| ([0-9]*\.?[0-9]*[MK])', video_quality, 'vbr', default=''))
|
|
||||||
|
|
||||||
format_id = '-'.join(
|
format_id = '-'.join(
|
||||||
[remove_start(s['id'], 'archive_') for s in (video_quality, audio_quality)] + [dmc_protocol])
|
[remove_start(s['id'], 'archive_') for s in (video_quality, audio_quality)] + [dmc_protocol])
|
||||||
|
|
||||||
vid_qual_label = traverse_obj(video_quality, ('metadata', 'label'))
|
vid_qual_label = traverse_obj(video_quality, ('metadata', 'label'))
|
||||||
vid_quality = traverse_obj(video_quality, ('metadata', 'bitrate'))
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'url': 'niconico_dmc:%s/%s/%s' % (video_id, video_quality['id'], audio_quality['id']),
|
'url': 'niconico_dmc:%s/%s/%s' % (video_id, video_quality['id'], audio_quality['id']),
|
||||||
@ -383,8 +377,9 @@ class NiconicoIE(InfoExtractor):
|
|||||||
'ext': 'mp4', # Session API are used in HTML5, which always serves mp4
|
'ext': 'mp4', # Session API are used in HTML5, which always serves mp4
|
||||||
'acodec': 'aac',
|
'acodec': 'aac',
|
||||||
'vcodec': 'h264',
|
'vcodec': 'h264',
|
||||||
'abr': float_or_none(traverse_obj(audio_quality, ('metadata', 'bitrate')), 1000),
|
'abr': float_or_none(traverse_obj(audio_quality, ('metadata', 'bitrate')), scale=1000),
|
||||||
'vbr': float_or_none(vid_quality if vid_quality > 0 else extract_video_quality(vid_qual_label), 1000),
|
'vbr': float_or_none(traverse_obj(video_quality, ('metadata', 'bitrate')), scale=1000),
|
||||||
|
'asr': int_or_none(traverse_obj(audio_quality, ('metadata', 'samplingRate'))),
|
||||||
'height': traverse_obj(video_quality, ('metadata', 'resolution', 'height')),
|
'height': traverse_obj(video_quality, ('metadata', 'resolution', 'height')),
|
||||||
'width': traverse_obj(video_quality, ('metadata', 'resolution', 'width')),
|
'width': traverse_obj(video_quality, ('metadata', 'resolution', 'width')),
|
||||||
'quality': -2 if 'low' in video_quality['id'] else None,
|
'quality': -2 if 'low' in video_quality['id'] else None,
|
||||||
@ -439,50 +434,31 @@ class NiconicoIE(InfoExtractor):
|
|||||||
def get_video_info(*items, get_first=True, **kwargs):
|
def get_video_info(*items, get_first=True, **kwargs):
|
||||||
return traverse_obj(api_data, ('video', *items), get_all=not get_first, **kwargs)
|
return traverse_obj(api_data, ('video', *items), get_all=not get_first, **kwargs)
|
||||||
|
|
||||||
dmc_data = traverse_obj(api_data, (
|
dmc_data = traverse_obj(api_data, ('media', 'delivery', 'movie', {
|
||||||
'media', 'delivery', 'movie', {
|
'audios': ('audios', ..., {dict}),
|
||||||
'audios': 'audios',
|
'videos': ('videos', ..., {dict}),
|
||||||
'videos': 'videos',
|
'protocols': ('session', 'protocols', ..., {str}),
|
||||||
'protocols': ('session', 'protocols'),
|
}))
|
||||||
}, {lambda data: data if all(key in data for key in ['audios', 'videos', 'protocols']) else None},
|
if len(dmc_data) == 3:
|
||||||
))
|
|
||||||
if dmc_data:
|
|
||||||
for (audio_quality, video_quality, protocol) in itertools.product(
|
for (audio_quality, video_quality, protocol) in itertools.product(
|
||||||
dmc_data['audios'], dmc_data['videos'], dmc_data['protocols']):
|
dmc_data['audios'], dmc_data['videos'], dmc_data['protocols']):
|
||||||
fmt = self._extract_format_for_quality(video_id, audio_quality, video_quality, protocol)
|
fmt = self._extract_format_for_quality(video_id, audio_quality, video_quality, protocol)
|
||||||
if fmt:
|
if fmt:
|
||||||
formats.append(fmt)
|
formats.append(fmt)
|
||||||
|
|
||||||
|
# Getting all audio formats results in extracting duplicate video formats.
|
||||||
|
# Duplicate ones will be filtered out later.
|
||||||
dms_data = traverse_obj(api_data, ({
|
dms_data = traverse_obj(api_data, ({
|
||||||
'videos': ('media', 'domand', 'videos', ..., {
|
'video_ids': ('media', 'domand', 'videos', lambda _, v: v['isAvailable'], 'id', {str}),
|
||||||
lambda item: item['id'] if item['isAvailable'] else None
|
'audio_ids': ('media', 'domand', 'audios', lambda _, v: v['isAvailable'], 'id', {str}),
|
||||||
}),
|
'accessRightKey': ('media', 'domand', 'accessRightKey', {str}),
|
||||||
'audios': ('media', 'domand', 'audios', ..., {
|
'track_id': ('client', 'watchTrackId', {str}),
|
||||||
lambda item: (item['id'], {
|
|
||||||
'format_id': str(parse_bitrate(item['id'])),
|
|
||||||
'abr': float_or_none(item['bitRate'], scale=1000),
|
|
||||||
'asr': item['samplingRate'],
|
|
||||||
'acodec': 'aac',
|
|
||||||
'ext': 'm4a',
|
|
||||||
}) if item['isAvailable'] else None
|
|
||||||
}),
|
|
||||||
'accessRightKey': ('media', 'domand', 'accessRightKey'),
|
|
||||||
'track_id': ('client', 'watchTrackId'),
|
|
||||||
}, {
|
|
||||||
'videos': 'videos',
|
|
||||||
'audios': ('audios', {lambda items: dict(items)}),
|
|
||||||
'accessRightKey': 'accessRightKey',
|
|
||||||
'track_id': 'track_id',
|
|
||||||
}, {
|
|
||||||
lambda data: data if all(key in data for key in [
|
|
||||||
'videos', 'audios', 'accessRightKey', 'track_id',
|
|
||||||
]) else None
|
|
||||||
}))
|
}))
|
||||||
if dms_data:
|
if len(dms_data) == 4:
|
||||||
dms_m3u8_url = traverse_obj(self._download_json(
|
dms_m3u8_url = traverse_obj(self._download_json(
|
||||||
f'https://nvapi.nicovideo.jp/v1/watch/{video_id}/access-rights/hls', video_id,
|
f'https://nvapi.nicovideo.jp/v1/watch/{video_id}/access-rights/hls', video_id,
|
||||||
data=json.dumps({
|
data=json.dumps({
|
||||||
'outputs': list(itertools.product(dms_data['videos'], dms_data['audios']))
|
'outputs': list(itertools.product(dms_data['video_ids'], dms_data['audio_ids']))
|
||||||
}).encode(), query={'actionTrackId': dms_data['track_id']}, headers={
|
}).encode(), query={'actionTrackId': dms_data['track_id']}, headers={
|
||||||
'x-access-right-key': dms_data['accessRightKey'],
|
'x-access-right-key': dms_data['accessRightKey'],
|
||||||
'x-frontend-id': 6,
|
'x-frontend-id': 6,
|
||||||
@ -492,19 +468,30 @@ class NiconicoIE(InfoExtractor):
|
|||||||
dms_fmts = self._extract_m3u8_formats(dms_m3u8_url, video_id)
|
dms_fmts = self._extract_m3u8_formats(dms_m3u8_url, video_id)
|
||||||
|
|
||||||
# update audio formats
|
# update audio formats
|
||||||
dms_audio_fmts = [fmt for fmt in dms_fmts if fmt['vcodec'] == 'none']
|
dms_audio_info = dict(traverse_obj(api_data, (
|
||||||
for i, fmt in enumerate(dms_audio_fmts):
|
'media', 'domand', 'audios', lambda _, v: v['isAvailable'], {
|
||||||
format_id = remove_end(fmt['format_id'], '-%s' % fmt['format_note'])
|
lambda item: (item['id'], {
|
||||||
dms_audio_fmts[i].update(**(traverse_obj(dms_data, ('audios', format_id, {dict})) or {}))
|
'format_id': str(parse_bitrate(item['id'])),
|
||||||
|
'abr': float_or_none(item['bitRate'], scale=1000),
|
||||||
|
'asr': item['samplingRate'],
|
||||||
|
'acodec': 'aac',
|
||||||
|
'ext': 'm4a',
|
||||||
|
})
|
||||||
|
},
|
||||||
|
)))
|
||||||
|
dms_audio_fmts = traverse_obj(dms_fmts, (lambda _, v: v['vcodec'] == 'none', {
|
||||||
|
lambda fmt: dict(fmt, **traverse_obj(
|
||||||
|
dms_audio_info, (remove_end(fmt['format_id'], '-%s' % fmt['format_note']), {dict})
|
||||||
|
))
|
||||||
|
}))
|
||||||
|
|
||||||
# remove duplicate video formats
|
# First, pick out the non-duplicate video format with the minimal tbr.
|
||||||
dms_video_fmts = [
|
dms_video_fmts = [
|
||||||
list(fmts)[0] for _, fmts in itertools.groupby(sorted([
|
list(fmts)[0] for _, fmts in itertools.groupby(sorted([
|
||||||
fmt for fmt in dms_fmts if fmt['vcodec'] != 'none'
|
fmt for fmt in dms_fmts if fmt['vcodec'] != 'none'
|
||||||
], key=lambda fmt: fmt['tbr']), lambda fmt: fmt['url'])
|
], key=lambda fmt: fmt['tbr']), lambda fmt: fmt['url'])
|
||||||
]
|
]
|
||||||
|
# Then, correct the bitrate of all videos by minusing the minimal audio bitrate.
|
||||||
# correct video bitrate
|
|
||||||
min_abr = traverse_obj(min(dms_audio_fmts, key=lambda fmt: fmt['abr']), ('abr'), default=0)
|
min_abr = traverse_obj(min(dms_audio_fmts, key=lambda fmt: fmt['abr']), ('abr'), default=0)
|
||||||
for i, fmt in enumerate(dms_video_fmts):
|
for i, fmt in enumerate(dms_video_fmts):
|
||||||
vbr = fmt['tbr'] - min_abr
|
vbr = fmt['tbr'] - min_abr
|
||||||
|
Loading…
x
Reference in New Issue
Block a user