[ie/bilibili] Fix supporter-only video extraction (#11711)

Fix bug in 239f5f36fe
Closes #11702
Authored by: grqz, bashonly

Co-authored-by: bashonly <88596187+bashonly@users.noreply.github.com>
pull/11210/head
N/Ame 2 months ago committed by GitHub
parent d8fb349086
commit f05a1cd149
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -652,13 +652,6 @@ class BiliBiliIE(BilibiliBaseIE):
else: else:
video_data = initial_state['videoData'] video_data = initial_state['videoData']
if video_data.get('is_upower_exclusive'):
high_level = traverse_obj(initial_state, ('elecFullInfo', 'show_info', 'high_level', {dict})) or {}
raise ExtractorError(
'This is a supporter-only video: '
f'{join_nonempty("title", "sub_title", from_dict=high_level, delim="")}. '
f'{self._login_hint()}', expected=True)
video_id, title = video_data['bvid'], video_data.get('title') video_id, title = video_data['bvid'], video_data.get('title')
# Bilibili anthologies are similar to playlists but all videos share the same video ID as the anthology itself. # Bilibili anthologies are similar to playlists but all videos share the same video ID as the anthology itself.
@ -726,62 +719,72 @@ class BiliBiliIE(BilibiliBaseIE):
self._get_interactive_entries(video_id, cid, metainfo, headers=headers), **metainfo, self._get_interactive_entries(video_id, cid, metainfo, headers=headers), **metainfo,
duration=traverse_obj(initial_state, ('videoData', 'duration', {int_or_none})), duration=traverse_obj(initial_state, ('videoData', 'duration', {int_or_none})),
__post_extractor=self.extract_comments(aid)) __post_extractor=self.extract_comments(aid))
else:
formats = self.extract_formats(play_info) formats = self.extract_formats(play_info)
if not traverse_obj(play_info, ('dash')): if video_data.get('is_upower_exclusive'):
# we only have legacy formats and need additional work high_level = traverse_obj(initial_state, ('elecFullInfo', 'show_info', 'high_level', {dict})) or {}
has_qn = lambda x: x in traverse_obj(formats, (..., 'quality')) msg = f'{join_nonempty("title", "sub_title", from_dict=high_level, delim="")}. {self._login_hint()}'
for qn in traverse_obj(play_info, ('accept_quality', lambda _, v: not has_qn(v), {int})): if not formats:
formats.extend(traverse_obj( raise ExtractorError(f'This is a supporter-only video: {msg}', expected=True)
self.extract_formats(self._download_playinfo(video_id, cid, headers=headers, qn=qn)), if '试看' in traverse_obj(play_info, ('accept_description', ..., {str})):
lambda _, v: not has_qn(v['quality']))) self.report_warning(
self._check_missing_formats(play_info, formats) f'This is a supporter-only video, only the preview will be extracted: {msg}',
flv_formats = traverse_obj(formats, lambda _, v: v['fragments']) video_id=video_id)
if flv_formats and len(flv_formats) < len(formats):
# Flv and mp4 are incompatible due to `multi_video` workaround, so drop one if not traverse_obj(play_info, 'dash'):
if not self._configuration_arg('prefer_multi_flv'): # we only have legacy formats and need additional work
dropped_fmts = ', '.join( has_qn = lambda x: x in traverse_obj(formats, (..., 'quality'))
f'{f.get("format_note")} ({f.get("format_id")})' for f in flv_formats) for qn in traverse_obj(play_info, ('accept_quality', lambda _, v: not has_qn(v), {int})):
formats = traverse_obj(formats, lambda _, v: not v.get('fragments')) formats.extend(traverse_obj(
if dropped_fmts: self.extract_formats(self._download_playinfo(video_id, cid, headers=headers, qn=qn)),
self.to_screen( lambda _, v: not has_qn(v['quality'])))
f'Dropping incompatible flv format(s) {dropped_fmts} since mp4 is available. ' self._check_missing_formats(play_info, formats)
'To extract flv, pass --extractor-args "bilibili:prefer_multi_flv"') flv_formats = traverse_obj(formats, lambda _, v: v['fragments'])
else: if flv_formats and len(flv_formats) < len(formats):
formats = traverse_obj( # Flv and mp4 are incompatible due to `multi_video` workaround, so drop one
# XXX: Filtering by extractor-arg is for testing purposes if not self._configuration_arg('prefer_multi_flv'):
formats, lambda _, v: v['quality'] == int(self._configuration_arg('prefer_multi_flv')[0]), dropped_fmts = ', '.join(
) or [max(flv_formats, key=lambda x: x['quality'])] f'{f.get("format_note")} ({f.get("format_id")})' for f in flv_formats)
formats = traverse_obj(formats, lambda _, v: not v.get('fragments'))
if traverse_obj(formats, (0, 'fragments')): if dropped_fmts:
# We have flv formats, which are individual short videos with their own timestamps and metainfo self.to_screen(
# Binary concatenation corrupts their timestamps, so we need a `multi_video` workaround f'Dropping incompatible flv format(s) {dropped_fmts} since mp4 is available. '
return { 'To extract flv, pass --extractor-args "bilibili:prefer_multi_flv"')
**metainfo, else:
'_type': 'multi_video', formats = traverse_obj(
'entries': [{ # XXX: Filtering by extractor-arg is for testing purposes
'id': f'{metainfo["id"]}_{idx}', formats, lambda _, v: v['quality'] == int(self._configuration_arg('prefer_multi_flv')[0]),
'title': metainfo['title'], ) or [max(flv_formats, key=lambda x: x['quality'])]
'http_headers': metainfo['http_headers'],
'formats': [{ if traverse_obj(formats, (0, 'fragments')):
**fragment, # We have flv formats, which are individual short videos with their own timestamps and metainfo
'format_id': formats[0].get('format_id'), # Binary concatenation corrupts their timestamps, so we need a `multi_video` workaround
}], return {
'subtitles': self.extract_subtitles(video_id, cid) if idx == 0 else None, **metainfo,
'__post_extractor': self.extract_comments(aid) if idx == 0 else None, '_type': 'multi_video',
} for idx, fragment in enumerate(formats[0]['fragments'])], 'entries': [{
'duration': float_or_none(play_info.get('timelength'), scale=1000), 'id': f'{metainfo["id"]}_{idx}',
} 'title': metainfo['title'],
else: 'http_headers': metainfo['http_headers'],
return { 'formats': [{
**metainfo, **fragment,
'formats': formats, 'format_id': formats[0].get('format_id'),
'duration': float_or_none(play_info.get('timelength'), scale=1000), }],
'chapters': self._get_chapters(aid, cid), 'subtitles': self.extract_subtitles(video_id, cid) if idx == 0 else None,
'subtitles': self.extract_subtitles(video_id, cid), '__post_extractor': self.extract_comments(aid) if idx == 0 else None,
'__post_extractor': self.extract_comments(aid), } for idx, fragment in enumerate(formats[0]['fragments'])],
} 'duration': float_or_none(play_info.get('timelength'), scale=1000),
}
return {
**metainfo,
'formats': formats,
'duration': float_or_none(play_info.get('timelength'), scale=1000),
'chapters': self._get_chapters(aid, cid),
'subtitles': self.extract_subtitles(video_id, cid),
'__post_extractor': self.extract_comments(aid),
}
class BiliBiliBangumiIE(BilibiliBaseIE): class BiliBiliBangumiIE(BilibiliBaseIE):

Loading…
Cancel
Save