mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-11-30 12:01:28 +00:00
[youtube,twitch] Allow waiting for channels to become live
Closes #2597
This commit is contained in:
parent
3bec830a59
commit
693f060040
|
@ -80,6 +80,7 @@
|
||||||
RejectedVideoReached,
|
RejectedVideoReached,
|
||||||
SameFileError,
|
SameFileError,
|
||||||
UnavailableVideoError,
|
UnavailableVideoError,
|
||||||
|
UserNotLive,
|
||||||
YoutubeDLCookieProcessor,
|
YoutubeDLCookieProcessor,
|
||||||
YoutubeDLHandler,
|
YoutubeDLHandler,
|
||||||
YoutubeDLRedirectHandler,
|
YoutubeDLRedirectHandler,
|
||||||
|
@ -1456,7 +1457,7 @@ def wrapper(self, *args, **kwargs):
|
||||||
break
|
break
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
def _wait_for_video(self, ie_result):
|
def _wait_for_video(self, ie_result={}):
|
||||||
if (not self.params.get('wait_for_video')
|
if (not self.params.get('wait_for_video')
|
||||||
or ie_result.get('_type', 'video') != 'video'
|
or ie_result.get('_type', 'video') != 'video'
|
||||||
or ie_result.get('formats') or ie_result.get('url')):
|
or ie_result.get('formats') or ie_result.get('url')):
|
||||||
|
@ -1480,7 +1481,7 @@ def progress(msg):
|
||||||
if diff is None and ie_result.get('live_status') == 'is_upcoming':
|
if diff is None and ie_result.get('live_status') == 'is_upcoming':
|
||||||
diff = round(random.uniform(min_wait, max_wait) if (max_wait and min_wait) else (max_wait or min_wait), 0)
|
diff = round(random.uniform(min_wait, max_wait) if (max_wait and min_wait) else (max_wait or min_wait), 0)
|
||||||
self.report_warning('Release time of video is not known')
|
self.report_warning('Release time of video is not known')
|
||||||
elif (diff or 0) <= 0:
|
elif ie_result and (diff or 0) <= 0:
|
||||||
self.report_warning('Video should already be available according to extracted info')
|
self.report_warning('Video should already be available according to extracted info')
|
||||||
diff = min(max(diff or 0, min_wait or 0), max_wait or float('inf'))
|
diff = min(max(diff or 0, min_wait or 0), max_wait or float('inf'))
|
||||||
self.to_screen(f'[wait] Waiting for {format_dur(diff)} - Press Ctrl+C to try now')
|
self.to_screen(f'[wait] Waiting for {format_dur(diff)} - Press Ctrl+C to try now')
|
||||||
|
@ -1504,7 +1505,14 @@ def progress(msg):
|
||||||
|
|
||||||
@_handle_extraction_exceptions
|
@_handle_extraction_exceptions
|
||||||
def __extract_info(self, url, ie, download, extra_info, process):
|
def __extract_info(self, url, ie, download, extra_info, process):
|
||||||
|
try:
|
||||||
ie_result = ie.extract(url)
|
ie_result = ie.extract(url)
|
||||||
|
except UserNotLive as e:
|
||||||
|
if process:
|
||||||
|
if self.params.get('wait_for_video'):
|
||||||
|
self.report_warning(e)
|
||||||
|
self._wait_for_video()
|
||||||
|
raise
|
||||||
if ie_result is None: # Finished already (backwards compatibility; listformats and friends should be moved here)
|
if ie_result is None: # Finished already (backwards compatibility; listformats and friends should be moved here)
|
||||||
self.report_warning(f'Extractor {ie.IE_NAME} returned nothing{bug_reports_message()}')
|
self.report_warning(f'Extractor {ie.IE_NAME} returned nothing{bug_reports_message()}')
|
||||||
return
|
return
|
||||||
|
|
|
@ -12,10 +12,11 @@
|
||||||
compat_urllib_parse_urlparse,
|
compat_urllib_parse_urlparse,
|
||||||
)
|
)
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
|
ExtractorError,
|
||||||
|
UserNotLive,
|
||||||
base_url,
|
base_url,
|
||||||
clean_html,
|
clean_html,
|
||||||
dict_get,
|
dict_get,
|
||||||
ExtractorError,
|
|
||||||
float_or_none,
|
float_or_none,
|
||||||
int_or_none,
|
int_or_none,
|
||||||
parse_duration,
|
parse_duration,
|
||||||
|
@ -940,7 +941,7 @@ def _real_extract(self, url):
|
||||||
stream = user['stream']
|
stream = user['stream']
|
||||||
|
|
||||||
if not stream:
|
if not stream:
|
||||||
raise ExtractorError('%s is offline' % channel_name, expected=True)
|
raise UserNotLive(video_id=channel_name)
|
||||||
|
|
||||||
access_token = self._download_access_token(
|
access_token = self._download_access_token(
|
||||||
channel_name, 'stream', 'channelName')
|
channel_name, 'stream', 'channelName')
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
NO_DEFAULT,
|
NO_DEFAULT,
|
||||||
ExtractorError,
|
ExtractorError,
|
||||||
|
UserNotLive,
|
||||||
bug_reports_message,
|
bug_reports_message,
|
||||||
classproperty,
|
classproperty,
|
||||||
clean_html,
|
clean_html,
|
||||||
|
@ -5383,9 +5384,8 @@ def get_mobj(url):
|
||||||
selected_tab_name = 'featured'
|
selected_tab_name = 'featured'
|
||||||
requested_tab_name = mobj['tab'][1:]
|
requested_tab_name = mobj['tab'][1:]
|
||||||
if 'no-youtube-channel-redirect' not in compat_opts:
|
if 'no-youtube-channel-redirect' not in compat_opts:
|
||||||
if requested_tab_name == 'live':
|
if requested_tab_name == 'live': # Live tab should have redirected to the video
|
||||||
# Live tab should have redirected to the video
|
raise UserNotLive(video_id=mobj['id'])
|
||||||
raise ExtractorError('The channel is not currently live', expected=True)
|
|
||||||
if requested_tab_name not in ('', selected_tab_name):
|
if requested_tab_name not in ('', selected_tab_name):
|
||||||
redirect_warning = f'The channel does not have a {requested_tab_name} tab'
|
redirect_warning = f'The channel does not have a {requested_tab_name} tab'
|
||||||
if not original_tab_name:
|
if not original_tab_name:
|
||||||
|
|
|
@ -1072,6 +1072,14 @@ def __init__(self, msg, countries=None, **kwargs):
|
||||||
self.countries = countries
|
self.countries = countries
|
||||||
|
|
||||||
|
|
||||||
|
class UserNotLive(ExtractorError):
|
||||||
|
"""Error when a channel/user is not live"""
|
||||||
|
|
||||||
|
def __init__(self, msg=None, **kwargs):
|
||||||
|
kwargs['expected'] = True
|
||||||
|
super().__init__(msg or 'The channel is not currently live', **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class DownloadError(YoutubeDLError):
|
class DownloadError(YoutubeDLError):
|
||||||
"""Download Error exception.
|
"""Download Error exception.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue