From f3ddaac7d981ed5acfdacaf73f178fcd3abb53d5 Mon Sep 17 00:00:00 2001 From: MoojMidge <56883549+MoojMidge@users.noreply.github.com> Date: Sun, 25 Feb 2024 00:36:02 +1100 Subject: [PATCH] Fix Youtube progress tracking #581 --- .../kodion/utils/player_monitor.py | 57 ++++++++------- .../youtube_plugin/youtube/client/youtube.py | 69 +++++++++++-------- .../youtube/helper/video_info.py | 20 ++---- 3 files changed, 73 insertions(+), 73 deletions(-) diff --git a/resources/lib/youtube_plugin/kodion/utils/player_monitor.py b/resources/lib/youtube_plugin/kodion/utils/player_monitor.py index a9afb3650..459003200 100644 --- a/resources/lib/youtube_plugin/kodion/utils/player_monitor.py +++ b/resources/lib/youtube_plugin/kodion/utils/player_monitor.py @@ -35,7 +35,6 @@ def __init__(self, player, provider, context, monitor, playback_json): self.total_time = 0.0 self.current_time = 0.0 - self.segment_start = 0.0 self.progress = 0 self.daemon = True @@ -90,9 +89,6 @@ def run(self): self._context, self.video_id, report_url, - st=0, - et='N/A', - state=state ) access_manager = self._context.get_access_manager() @@ -101,6 +97,7 @@ def run(self): video_id_param = 'video_id=%s' % self.video_id report_url = use_remote_history and playback_stats.get('watchtime_url') + segment_start = 0 played_time = -1.0 wait_interval = 0.5 report_period = waited = 10 @@ -153,38 +150,37 @@ def run(self): state = 'playing' played_time = self.current_time - # refresh client, tokens may need refreshing if logged_in and report_url: - self._provider.reset_client() - client = self._provider.get_client(self._context) - logged_in = self._provider.is_logged_in() - - if self.segment_start < 0: - self.segment_start = 0.0 - if state == 'playing': segment_end = self.current_time else: - segment_end = self.segment_start + segment_end = segment_start - if self.segment_start > segment_end: - segment_end = self.segment_start + report_period + if segment_start > segment_end: + segment_end = segment_start + report_period if segment_end > self.total_time: segment_end = self.total_time # only report state='paused' once if state == 'playing' or last_state == 'playing': - client.update_watch_history( - self._context, - self.video_id, - report_url, - st=format(self.segment_start, '.3f'), - et=format(segment_end, '.3f'), - state=state - ) - - self.segment_start = segment_end + # refresh client, tokens may need refreshing + self._provider.reset_client() + client = self._provider.get_client(self._context) + logged_in = self._provider.is_logged_in() + + if logged_in: + client.update_watch_history( + self._context, + self.video_id, + report_url, + status=(self.current_time, + segment_start, + segment_end, + state), + ) + + segment_start = segment_end self._monitor.waitForAbort(wait_interval) waited += wait_interval @@ -212,9 +208,9 @@ def run(self): if self.progress >= settings.get_play_count_min_percent(): play_count += 1 self.current_time = 0.0 - segment_end = format(self.total_time, '.3f') + segment_end = self.total_time else: - segment_end = format(self.current_time, '.3f') + segment_end = self.current_time refresh_only = True if logged_in and report_url: @@ -222,9 +218,10 @@ def run(self): self._context, self.video_id, report_url, - st=segment_end, - et=segment_end, - state=state + status=(segment_end, + segment_end, + segment_end, + state), ) if use_local_history: play_data = { diff --git a/resources/lib/youtube_plugin/youtube/client/youtube.py b/resources/lib/youtube_plugin/youtube/client/youtube.py index 45c7fd1bc..42b67b14c 100644 --- a/resources/lib/youtube_plugin/youtube/client/youtube.py +++ b/resources/lib/youtube_plugin/youtube/client/youtube.py @@ -155,42 +155,51 @@ def calculate_next_page_token(page, max_result): return 'C%s%s%sAA' % (high[high_iteration], low[low_iteration], overflow_token) - def update_watch_history(self, - context, - video_id, - url, - st=None, - et=None, - state=None): - if None not in (st, et, state): - url.format(st=st, et=et, state=state) + def update_watch_history(self, context, video_id, url, status=None): + if status is None: + cmt = st = et = state = None else: - st = et = state = 'N/A' + cmt, st, et, state = status context.log_debug('Playback reported [{video_id}]:' - ' {st} segment start,' - ' {et} segment end,' + ' current time={cmt},' + ' segment start={st},' + ' segment end={et},' ' state={state}'.format( - video_id=video_id, st=st, et=et, state=state + video_id=video_id, cmt=cmt, st=st, et=et, state=state )) - headers = {'Host': 'www.youtube.com', - 'Connection': 'keep-alive', - 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.36 Safari/537.36', - 'Accept': 'image/webp,*/*;q=0.8', - 'DNT': '1', - 'Referer': 'https://www.youtube.com/tv', - 'Accept-Encoding': 'gzip, deflate', - 'Accept-Language': 'en-US,en;q=0.8,de;q=0.6'} - params = {'noflv': '1', - 'html5': '1', - 'video_id': video_id, - 'referrer': '', - 'eurl': 'https://www.youtube.com/tv#/watch?v=%s' % video_id, - 'skl': 'false', - 'ns': 'yt', - 'el': 'leanback', - 'ps': 'leanback'} + headers = { + 'Host': 's.youtube.com', + 'Connection': 'keep-alive', + 'Accept-Encoding': 'gzip, deflate', + 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', + 'Accept': '*/*', + 'Accept-Language': 'en-US,en;q=0.5', + 'DNT': '1', + 'Referer': 'https://www.youtube.com/watch?v={0}'.format(video_id), + 'User-Agent': ('Mozilla/5.0 (Linux; Android 10; SM-G981B)' + ' AppleWebKit/537.36 (KHTML, like Gecko)' + ' Chrome/80.0.3987.162 Mobile Safari/537.36'), + } + params = { + 'docid': video_id, + 'referrer': 'https://accounts.google.com/', + 'ns': 'yt', + 'el': 'detailpage', + 'ver': '2', + 'fs': '0', + 'volume': '100', + 'muted': '0', + } + if cmt is not None: + params['cmt'] = format(cmt, '.3f') + if st is not None: + params['st'] = format(st, '.3f') + if et is not None: + params['et'] = format(et, '.3f') + if state is not None: + params['state'] = state if self._access_token: params['access_token'] = self._access_token diff --git a/resources/lib/youtube_plugin/youtube/helper/video_info.py b/resources/lib/youtube_plugin/youtube/helper/video_info.py index 386227ffc..e86f03606 100644 --- a/resources/lib/youtube_plugin/youtube/helper/video_info.py +++ b/resources/lib/youtube_plugin/youtube/helper/video_info.py @@ -1188,24 +1188,18 @@ def _get_video_info(self): if _settings.use_remote_history(): playback_stats = { - 'playback_url': ( - 'videostatsPlaybackUrl', - '{0}&ver=2&fs=0&volume=100&muted=0&cpn={1}', - ), - 'watchtime_url': ( - 'videostatsWatchtimeUrl', - ('{0}&ver=2&fs=0&volume=100&muted=0&cpn={1}' - '&st={{st}}&et={{et}}&state={{state}}'), - ) + 'playback_url': 'videostatsPlaybackUrl', + 'watchtime_url': 'videostatsWatchtimeUrl', } playback_tracking = response.get('playbackTracking', {}) cpn = self._generate_cpn() - for key, (url, url_template) in playback_stats.items(): - url = playback_tracking.get(url, {}).get('baseUrl') - if not url or not url.startswith('http'): + for key, url_key in playback_stats.items(): + url = playback_tracking.get(url_key, {}).get('baseUrl') + if url and url.startswith('http'): + playback_stats[key] = '&cpn='.join((url, cpn)) + else: playback_stats[key] = '' - playback_stats[key] = url_template.format(url, cpn) else: playback_stats = { 'playback_url': '',