From 79372d23ce606c60de6db36b9cb744aa55591420 Mon Sep 17 00:00:00 2001 From: acgnhik <acgnhik@outlook.com> Date: Sat, 7 Oct 2023 11:27:45 +0800 Subject: [PATCH] fix: fix no auto recording for live streaming that has no flv streams fix #183 --- src/blrec/bili/live.py | 27 ++++++++++++++++++--------- src/blrec/bili/live_monitor.py | 28 ++++++++++++++++------------ 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/blrec/bili/live.py b/src/blrec/bili/live.py index 960c2ea..607103a 100644 --- a/src/blrec/bili/live.py +++ b/src/blrec/bili/live.py @@ -239,15 +239,9 @@ class Live: # the timestamp on the server at the moment in seconds return await self._webapi.get_timestamp() - async def get_live_stream_url( - self, - qn: QualityNumber = 10000, - *, - api_platform: ApiPlatform = 'web', - stream_format: StreamFormat = 'flv', - stream_codec: StreamCodec = 'avc', - select_alternative: bool = False, - ) -> str: + async def get_live_streams( + self, qn: QualityNumber = 10000, api_platform: ApiPlatform = 'web' + ) -> List[Any]: if api_platform == 'web': paly_infos = await self._webapi.get_room_play_infos(self._room_id, qn) else: @@ -257,13 +251,28 @@ class Live: self._check_room_play_info(info) streams = jsonpath(paly_infos, '$[*].playurl_info.playurl.stream[*]') + + return streams + + async def get_live_stream_url( + self, + qn: QualityNumber = 10000, + *, + api_platform: ApiPlatform = 'web', + stream_format: StreamFormat = 'flv', + stream_codec: StreamCodec = 'avc', + select_alternative: bool = False, + ) -> str: + streams = await self.get_live_streams(qn, api_platform=api_platform) if not streams: raise NoStreamAvailable(stream_format, stream_codec, qn) + formats = jsonpath( streams, f'$[*].format[?(@.format_name == "{stream_format}")]' ) if not formats: raise NoStreamFormatAvailable(stream_format, stream_codec, qn) + codecs = jsonpath(formats, f'$[*].codec[?(@.codec_name == "{stream_codec}")]') if not codecs: raise NoStreamCodecAvailable(stream_format, stream_codec, qn) diff --git a/src/blrec/bili/live_monitor.py b/src/blrec/bili/live_monitor.py index 498009a..7cd3f11 100644 --- a/src/blrec/bili/live_monitor.py +++ b/src/blrec/bili/live_monitor.py @@ -83,6 +83,9 @@ class LiveMonitor(EventEmitter[LiveEventListener], DanmakuListener, SwitchableMi def _start_checking(self) -> None: self._checking_task = asyncio.create_task(self._check_if_stream_available()) self._checking_task.add_done_callback(exception_callback) + asyncio.get_running_loop().call_later( + 1800, lambda: asyncio.create_task(self._stop_checking()) + ) logger.debug('Started checking if stream available') async def _stop_checking(self) -> None: @@ -147,19 +150,16 @@ class LiveMonitor(EventEmitter[LiveEventListener], DanmakuListener, SwitchableMi self._status_count = 0 self._stream_available = False await self._emit('live_ended', self._live) + await self._stop_checking() else: self._status_count += 1 if self._status_count == 1: assert self._previous_status != LiveStatus.LIVE - self._start_checking() await self._emit('live_began', self._live) + self._start_checking() elif self._status_count == 2: assert self._previous_status == LiveStatus.LIVE - if not self._stream_available: - self._stream_available = True - await self._stop_checking() - await self._emit('live_stream_available', self._live) elif self._status_count > 2: assert self._previous_status == LiveStatus.LIVE await self._emit('live_stream_reset', self._live) @@ -181,11 +181,15 @@ class LiveMonitor(EventEmitter[LiveEventListener], DanmakuListener, SwitchableMi @aio_task_with_room_id async def _check_if_stream_available(self) -> None: - while not self._stream_available: + while True: try: - await self._live.get_live_stream_url() - except Exception: - await asyncio.sleep(1) - else: - self._stream_available = True - await self._emit('live_stream_available', self._live) + streams = await self._live.get_live_streams() + if streams: + logger.debug('live stream available') + self._stream_available = True + await self._emit('live_stream_available', self._live) + break + except Exception as e: + logger.warning(f'Failed to get live streams: {repr(e)}') + + await asyncio.sleep(1)