Exemplo n.º 1
0
 def __init__(self, marionette, url, **kwargs):
     self.player = None
     super(YouTubePuppeteer,
           self).__init__(marionette,
                          url,
                          video_selector='.html5-video-player video',
                          **kwargs)
     wait = Wait(self.marionette, timeout=30)
     with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
         verbose_until(
             wait, self,
             expected.element_present(By.CLASS_NAME, 'html5-video-player'))
         self.player = self.marionette.find_element(By.CLASS_NAME,
                                                    'html5-video-player')
         self.marionette.execute_script("log('.html5-video-player "
                                        "element obtained');")
     # When an ad is playing, self.player_duration indicates the duration
     # of the spliced-in ad stream, not the duration of the main video, so
     # we attempt to skip the ad first.
     for attempt in range(5):
         sleep(1)
         self.process_ad()
         if (self.ad_inactive and self.duration
                 and not self.player_buffering):
             break
     self.update_expected_duration()
Exemplo n.º 2
0
 def __init__(self, marionette, url, autostart=True, **kwargs):
     self.player = None
     self._last_seen_player_state = None
     super(YouTubePuppeteer,
           self).__init__(marionette, url,
                          video_selector='.html5-video-player video',
                          autostart=False,
                          **kwargs)
     wait = Wait(self.marionette, timeout=30)
     with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
         verbose_until(wait, self,
                       expected.element_present(By.CLASS_NAME,
                                                'html5-video-player'))
         self.player = self.marionette.find_element(By.CLASS_NAME,
                                                    'html5-video-player')
         self.marionette.execute_script("log('.html5-video-player "
                                        "element obtained');")
     # When an ad is playing, self.player_duration indicates the duration
     # of the spliced-in ad stream, not the duration of the main video, so
     # we attempt to skip the ad first.
     for attempt in range(5):
         sleep(1)
         self.process_ad()
         if (self._last_seen_player_state.player_ad_inactive and
                 self._last_seen_video_state.duration and not
                 self._last_seen_player_state.player_buffering):
             break
     self._update_expected_duration()
     if autostart:
         self.start()
Exemplo n.º 3
0
 def __init__(self, marionette, url, video_selector='video', interval=1,
              set_duration=0, stall_wait_time=0, timeout=60,
              autostart=True):
     self.marionette = marionette
     self.test_url = url
     self.interval = interval
     self.stall_wait_time = stall_wait_time
     self.timeout = timeout
     self._set_duration = set_duration
     self.video = None
     self.expected_duration = 0
     self._first_seen_time = 0
     self._first_seen_wall_time = 0
     wait = Wait(self.marionette, timeout=self.timeout)
     with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
         self.marionette.navigate(self.test_url)
         self.marionette.execute_script("""
             log('URL: {0}');""".format(self.test_url))
         verbose_until(wait, self,
                       expected.element_present(By.TAG_NAME, 'video'))
         videos_found = self.marionette.find_elements(By.CSS_SELECTOR,
                                                      video_selector)
         if len(videos_found) > 1:
             self.marionette.log(type(self).__name__ + ': multiple video '
                                                       'elements found. '
                                                       'Using first.')
         if len(videos_found) <= 0:
             self.marionette.log(type(self).__name__ + ': no video '
                                                       'elements found.')
             return
         self.video = videos_found[0]
         self.marionette.execute_script("log('video element obtained');")
         if autostart:
             self.start()
Exemplo n.º 4
0
    def test_video_playing_in_one_tab(self):
        with self.marionette.using_context('content'):
            for url in self.video_urls:
                self.logger.info(url)
                youtube = YouTubePuppeteer(self.marionette, url)
                self.logger.info('Expected duration: %s' %
                                 youtube.expected_duration)
                youtube.deactivate_autoplay()

                final_piece = 60
                try:
                    time_left = wait_for_almost_done(youtube,
                                                     final_piece=final_piece)
                except VideoException as e:
                    raise self.failureException(e)
                duration = abs(youtube.expected_duration) + 1
                if duration > 1:
                    self.logger.info('Almost done: %s - %s seconds left.' %
                                     (youtube.movie_id, time_left))
                    if time_left > final_piece:
                        self.marionette.log('time_left greater than '
                                            'final_piece - %s' % time_left,
                                            level='WARNING')
                        self.save_screenshot()
                else:
                    self.marionette.log('Duration close to 0 - %s' % youtube,
                                        level='WARNING')
                    self.save_screenshot()
                try:
                    verbose_until(
                        Wait(youtube,
                             timeout=max(100, time_left) * 1.3,
                             interval=1), youtube, playback_done)
                except TimeoutException as e:
                    raise self.failureException(e)
    def test_video_playing_in_one_tab(self):
        with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
            for url in self.video_urls:
                self.logger.info(url)
                youtube = YouTubePuppeteer(self.marionette, url)
                self.logger.info('Expected duration: {}'.format(
                    youtube.expected_duration))

                final_piece = 60
                try:
                    time_left = youtube.wait_for_almost_done(
                        final_piece=final_piece)
                except VideoException as e:
                    raise self.failureException(e)
                duration = abs(youtube.expected_duration) + 1
                if duration > 1:
                    self.logger.info(
                        'Almost done: {} - {} seconds left.'.format(
                            url, time_left))
                    if time_left > final_piece:
                        self.logger.warn('time_left greater than '
                                         'final_piece - {}'.format(time_left))
                        self.save_screenshot()
                else:
                    self.logger.warn(
                        'Duration close to 0 - {}'.format(youtube))
                    self.save_screenshot()
                try:
                    verbose_until(
                        Wait(youtube,
                             timeout=max(100, time_left) * 1.3,
                             interval=1), youtube,
                        YouTubePuppeteer.playback_done)
                except TimeoutException as e:
                    raise self.failureException(e)
Exemplo n.º 6
0
 def start(self):
     # To get an accurate expected_duration, playback must have started
     wait = Wait(self, timeout=self.timeout)
     verbose_until(wait, self, lambda v: v.current_time > 0,
                   "Check if video current_time > 0")
     self._start_time = self.current_time
     self._start_wall_time = clock()
     self.update_expected_duration()
Exemplo n.º 7
0
 def start(self):
     # To get an accurate expected_duration, playback must have started
     wait = Wait(self, timeout=self.timeout)
     verbose_until(wait, self, lambda v: v.current_time > 0,
                   "Check if video current_time > 0")
     self._start_time = self.current_time
     self._start_wall_time = clock()
     self.update_expected_duration()
Exemplo n.º 8
0
 def check_playback_starts(self, video):
     with self.marionette.using_context('content'):
         self.logger.info(video.test_url)
         try:
             verbose_until(Wait(video, timeout=video.timeout), video,
                           playback_started)
         except TimeoutException as e:
             raise self.failureException(e)
Exemplo n.º 9
0
 def start(self):
     # To get an accurate expected_duration, playback must have started
     wait = Wait(self, timeout=self.timeout)
     verbose_until(wait, self, playback_started,
                   "Check if video has played some range")
     self._first_seen_time = self.current_time
     self._first_seen_wall_time = clock()
     self.update_expected_duration()
Exemplo n.º 10
0
 def start(self):
     # To get an accurate expected_duration, playback must have started
     wait = Wait(self, timeout=self.timeout)
     verbose_until(wait, self, playback_started,
                   "Check if video has played some range")
     self._first_seen_time = self.current_time
     self._first_seen_wall_time = clock()
     self.update_expected_duration()
Exemplo n.º 11
0
 def check_playback_starts(self, video):
     with self.marionette.using_context('content'):
         self.logger.info(video.test_url)
         try:
             verbose_until(Wait(video, timeout=video.timeout),
                           video, playback_started)
         except TimeoutException as e:
             raise self.failureException(e)
Exemplo n.º 12
0
 def run_playback(self, video):
     with self.marionette.using_context('content'):
         self.logger.info(video.test_url)
         try:
             verbose_until(Wait(video, interval=video.interval,
                                timeout=video.expected_duration * 1.3 +
                                video.stall_wait_time),
                           video, playback_done)
         except VideoException as e:
             raise self.failureException(e)
Exemplo n.º 13
0
 def run_playback(self, video):
     with self.marionette.using_context('content'):
         self.logger.info(video.test_url)
         try:
             verbose_until(
                 Wait(video,
                      interval=video.interval,
                      timeout=video.expected_duration * 1.3 +
                      video.stall_wait_time), video, playback_done)
         except VideoException as e:
             raise self.failureException(e)
Exemplo n.º 14
0
 def process_ad(self):
     if self.attempt_ad_skip() or self.ad_inactive:
         return
     ad_timeout = (self.search_ad_duration() or 30) + 5
     wait = Wait(self, timeout=ad_timeout, interval=1)
     try:
         self.marionette.log('process_ad: waiting %s s for ad' % ad_timeout)
         verbose_until(wait, self, lambda y: y.ad_ended, "Check if ad ended")
     except TimeoutException:
         self.marionette.log('Waiting for ad to end timed out',
                             level='WARNING')
Exemplo n.º 15
0
    def check_mse_src(self, mse_expected, url):
        with self.marionette.using_context('content'):
            youtube = YouTubePuppeteer(self.marionette, url)
            wait = Wait(youtube,
                        timeout=min(self.max_timeout,
                                    youtube.expected_duration * 1.3),
                        interval=1)

            def cond(y):
                return y.mse_enabled == mse_expected

            verbose_until(wait, youtube, cond)
Exemplo n.º 16
0
 def test_mse_is_enabled_by_default(self):
     with self.marionette.using_context('content'):
         youtube = YouTubePuppeteer(self.marionette, self.video_urls[0],
                                    timeout=60)
         wait = Wait(youtube,
                     timeout=min(300, youtube.expected_duration * 1.3),
                     interval=1)
         try:
             verbose_until(wait, youtube,
                           lambda y: y.video_src.startswith('mediasource'),
                           "Failed to find 'mediasource' in video src url.")
         except TimeoutException as e:
             raise self.failureException(e)
Exemplo n.º 17
0
    def check_playback_starts(self, video):
        """
        Check to see if a given video will start. Raises if the video does not
        start.

        :param video: VideoPuppeteer instance to play.
        """
        with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
            self.logger.info(video.test_url)
            try:
                verbose_until(Wait(video, timeout=video.timeout), video, VideoPuppeteer.playback_started)
            except TimeoutException as e:
                raise self.failureException(e)
Exemplo n.º 18
0
 def test_mse_is_enabled_by_default(self):
     with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
         youtube = YouTubePuppeteer(self.marionette, self.video_urls[0],
                                    timeout=60)
         wait = Wait(youtube,
                     timeout=min(300, youtube.expected_duration * 1.3),
                     interval=1)
         try:
             verbose_until(wait, youtube,
                           YouTubePuppeteer.mse_enabled,
                           "Failed to find 'blob' in video src url.")
         except TimeoutException as e:
             raise self.failureException(e)
Exemplo n.º 19
0
    def check_playback_starts(self, video):
        """
        Check to see if a given video will start. Raises if the video does not
        start.

        :param video: VideoPuppeteer instance to play.
        """
        with self.marionette.using_context('content'):
            self.logger.info(video.test_url)
            try:
                verbose_until(Wait(video, timeout=video.timeout), video,
                              playback_started)
            except TimeoutException as e:
                raise self.failureException(e)
Exemplo n.º 20
0
 def test_mse_is_enabled_by_default(self):
     with self.marionette.using_context('content'):
         youtube = YouTubePuppeteer(self.marionette,
                                    self.video_urls[0],
                                    timeout=60)
         wait = Wait(youtube,
                     timeout=min(300, youtube.expected_duration * 1.3),
                     interval=1)
         try:
             verbose_until(
                 wait, youtube,
                 lambda y: y.video_src.startswith('mediasource'),
                 "Failed to find 'mediasource' in video src url.")
         except TimeoutException as e:
             raise self.failureException(e)
Exemplo n.º 21
0
    def run_playback(self, video):
        """
        Play the video all of the way through, or for the requested duration,
        whichever comes first. Raises if the video stalls for too long.

        :param video: VideoPuppeteer instance to play.
        """
        with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
            self.logger.info(video.test_url)
            try:
                verbose_until(Wait(video, interval=video.interval,
                                   timeout=video.expected_duration * 1.3 +
                                   video.stall_wait_time),
                              video, VideoPuppeteer.playback_done)
            except VideoException as e:
                raise self.failureException(e)
Exemplo n.º 22
0
    def check_src(self, src_type, url):
        # Why wait to check src until initial ad is done playing?
        # - src attribute in video element is sometimes null during ad playback
        # - many ads still don't use MSE even if main video does
        with self.marionette.using_context('content'):
            youtube = YouTubePuppeteer(self.marionette, url)
            youtube.attempt_ad_skip()
            wait = Wait(youtube,
                        timeout=min(self.max_timeout,
                                    youtube.player_duration * 1.3),
                        interval=1)

            def cond(y):
                return y.video_src.startswith(src_type)

            verbose_until(wait, youtube, cond)
Exemplo n.º 23
0
    def run_playback(self, video):
        """
        Play the video all of the way through, or for the requested duration,
        whichever comes first. Raises if the video stalls for too long.

        :param video: VideoPuppeteer instance to play.
        """
        with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
            self.logger.info(video.test_url)
            try:
                verbose_until(Wait(video, interval=video.interval,
                                   timeout=video.expected_duration * 1.3 +
                                   video.stall_wait_time),
                              video, VideoPuppeteer.playback_done)
            except VideoException as e:
                raise self.failureException(e)
Exemplo n.º 24
0
 def process_ad(self):
     """
     Try to skip this ad. If not, wait for this ad to finish.
     """
     if self.attempt_ad_skip() or self.ad_inactive:
         return
     ad_timeout = (self.search_ad_duration() or 30) + 5
     wait = Wait(self, timeout=ad_timeout, interval=1)
     try:
         self.marionette.log(
             'process_ad: waiting {} s for ad'.format(ad_timeout))
         verbose_until(wait, self, lambda y: y.ad_ended,
                       "Check if ad ended")
     except TimeoutException:
         self.marionette.log('Waiting for ad to end timed out',
                             level='WARNING')
Exemplo n.º 25
0
 def __init__(self,
              marionette,
              url,
              video_selector='video',
              interval=1,
              set_duration=0,
              stall_wait_time=0,
              timeout=60):
     self.marionette = marionette
     self.test_url = url
     self.interval = interval
     self.stall_wait_time = stall_wait_time
     self.timeout = timeout
     self._set_duration = set_duration
     self.video = None
     self.expected_duration = 0
     self._start_time = 0
     self._start_wall_time = 0
     wait = Wait(self.marionette, timeout=self.timeout)
     with self.marionette.using_context('content'):
         self.marionette.navigate(self.test_url)
         self.marionette.execute_script("""
             log('URL: {0}');""".format(self.test_url))
         verbose_until(wait, self,
                       expected.element_present(By.TAG_NAME, 'video'))
         videos_found = self.marionette.find_elements(
             By.CSS_SELECTOR, video_selector)
         if len(videos_found) > 1:
             self.marionette.log(
                 type(self).__name__ + ': multiple video '
                 'elements found. '
                 'Using first.')
         if len(videos_found) <= 0:
             self.marionette.log(
                 type(self).__name__ + ': no video '
                 'elements found.')
             return
         self.video = videos_found[0]
         self.marionette.execute_script("log('video element obtained');")
         # To get an accurate expected_duration, playback must have started
         wait = Wait(self, timeout=self.timeout)
         verbose_until(wait, self, lambda v: v.current_time > 0,
                       "Check if video current_time > 0")
         self._start_time = self.current_time
         self._start_wall_time = clock()
         self.update_expected_duration()
Exemplo n.º 26
0
 def process_ad(self):
     """
     Wait for this ad to finish. Refreshes state.
     """
     self._refresh_state()
     if self._last_seen_player_state.player_ad_inactive:
         return
     ad_timeout = (self._search_ad_duration() or 30) + 5
     wait = Wait(self, timeout=ad_timeout, interval=1)
     try:
         self.marionette.log(
             'process_ad: waiting {} s for ad'.format(ad_timeout))
         verbose_until(wait, self, YouTubePuppeteer._check_if_ad_ended,
                       "Check if ad ended")
     except TimeoutException:
         self.marionette.log('Waiting for ad to end timed out',
                             level='WARNING')
 def __init__(self, marionette, url, autostart=True,
              set_duration=10.0, **kwargs):
     self.player = None
     self._last_seen_player_state = None
     super(TwitchPuppeteer,
           self).__init__(marionette, url, set_duration=set_duration,
                          autostart=False, **kwargs)
     wait = Wait(self.marionette, timeout=30)
     with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
         verbose_until(wait, self,
                       expected.element_present(By.CLASS_NAME,
                                                'player'))
         self.player = self.marionette.find_element(By.CLASS_NAME,
                                                    'player')
         self.marionette.execute_script("log('.player "
                                        "element obtained');")
         if autostart:
             self.start()
Exemplo n.º 28
0
 def __init__(self, marionette, url, autostart=True,
              set_duration=10.0, **kwargs):
     self.player = None
     self._last_seen_player_state = None
     super(TwitchPuppeteer,
           self).__init__(marionette, url, set_duration=set_duration,
                          autostart=False, **kwargs)
     wait = Wait(self.marionette, timeout=30)
     with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
         verbose_until(wait, self,
                       expected.element_present(By.CLASS_NAME,
                                                'player'))
         self.player = self.marionette.find_element(By.CLASS_NAME,
                                                    'player')
         self.marionette.execute_script("log('.player "
                                        "element obtained');")
         if autostart:
             self.start()
Exemplo n.º 29
0
 def __init__(self,
              marionette,
              url,
              video_selector='video',
              interval=1,
              set_duration=0,
              stall_wait_time=0,
              timeout=60,
              autostart=True):
     self.marionette = marionette
     self.test_url = url
     self.interval = interval
     self.stall_wait_time = stall_wait_time
     self.timeout = timeout
     self._set_duration = set_duration
     self.video = None
     self.expected_duration = 0
     self._first_seen_time = 0
     self._first_seen_wall_time = 0
     self._fetch_state_script_string = None
     self._last_seen_video_state = None
     wait = Wait(self.marionette, timeout=self.timeout)
     with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
         self.marionette.navigate(self.test_url)
         self.marionette.execute_script("""
             log('URL: {0}');""".format(self.test_url))
         verbose_until(wait, self,
                       expected.element_present(By.TAG_NAME, 'video'))
         videos_found = self.marionette.find_elements(
             By.CSS_SELECTOR, video_selector)
         if len(videos_found) > 1:
             self.marionette.log(
                 type(self).__name__ + ': multiple video '
                 'elements found. '
                 'Using first.')
         if len(videos_found) <= 0:
             self.marionette.log(
                 type(self).__name__ + ': no video '
                 'elements found.')
             return
         self.video = videos_found[0]
         self.marionette.execute_script("log('video element obtained');")
         if autostart:
             self.start()
Exemplo n.º 30
0
 def process_ad(self):
     """
     Wait for this ad to finish. Refreshes state.
     """
     self._refresh_state()
     if self._last_seen_player_state.player_ad_inactive:
         return
     ad_timeout = (self._search_ad_duration() or 30) + 5
     wait = Wait(self, timeout=ad_timeout, interval=1)
     try:
         self.marionette.log('process_ad: waiting {} s for ad'
                             .format(ad_timeout))
         verbose_until(wait,
                       self,
                       YouTubePuppeteer._check_if_ad_ended,
                       "Check if ad ended")
     except TimeoutException:
         self.marionette.log('Waiting for ad to end timed out',
                             level='WARNING')
Exemplo n.º 31
0
 def __init__(self, marionette, url, video_selector='video', interval=1,
              set_duration=0, stall_wait_time=0, timeout=60):
     self.marionette = marionette
     self.test_url = url
     self.interval = interval
     self.stall_wait_time = stall_wait_time
     self.timeout = timeout
     self._set_duration = set_duration
     self.video = None
     self.expected_duration = 0
     self._start_time = 0
     self._start_wall_time = 0
     wait = Wait(self.marionette, timeout=self.timeout)
     with self.marionette.using_context('content'):
         self.marionette.navigate(self.test_url)
         self.marionette.execute_script("""
             log('URL: {0}');""".format(self.test_url))
         verbose_until(wait, self,
                       expected.element_present(By.TAG_NAME, 'video'))
         videos_found = self.marionette.find_elements(By.CSS_SELECTOR,
                                                      video_selector)
         if len(videos_found) > 1:
             self.marionette.log(type(self).__name__ + ': multiple video '
                                                       'elements found. '
                                                       'Using first.')
         if len(videos_found) <= 0:
             self.marionette.log(type(self).__name__ + ': no video '
                                                       'elements found.')
             return
         self.video = videos_found[0]
         self.marionette.execute_script("log('video element obtained');")
         # To get an accurate expected_duration, playback must have started
         wait = Wait(self, timeout=self.timeout)
         verbose_until(wait, self, lambda v: v.current_time > 0,
                       "Check if video current_time > 0")
         self._start_time = self.current_time
         self._start_wall_time = clock()
         self.update_expected_duration()
Exemplo n.º 32
0
 def __init__(self, marionette, url, **kwargs):
     self.player = None
     super(YouTubePuppeteer,
           self).__init__(marionette, url,
                          video_selector='#movie_player video',
                          **kwargs)
     wait = Wait(self.marionette, timeout=30)
     with self.marionette.using_context('content'):
         verbose_until(wait, self,
                       expected.element_present(By.ID, 'movie_player'))
         self.player = self.marionette.find_element(By.ID, 'movie_player')
         self.marionette.execute_script("log('#movie_player "
                                        "element obtained');")
     # When an ad is playing, self.player_duration indicates the duration
     # of the spliced-in ad stream, not the duration of the main video, so
     # we attempt to skip the ad first.
     for attempt in range(5):
         sleep(1)
         self.process_ad()
         if (self.ad_inactive and self.duration and not
                 self.player_buffering):
             break
     self.update_expected_duration()
Exemplo n.º 33
0
    def test_video_playing_in_one_tab(self):
        with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
            for url in self.video_urls:
                self.logger.info(url)
                youtube = YouTubePuppeteer(self.marionette, url)
                self.logger.info('Expected duration: {}'
                                 .format(youtube.expected_duration))

                final_piece = 60
                try:
                    time_left = youtube.wait_for_almost_done(
                        final_piece=final_piece)
                except VideoException as e:
                    raise self.failureException(e)
                duration = abs(youtube.expected_duration) + 1
                if duration > 1:
                    self.logger.info('Almost done: {} - {} seconds left.'
                                     .format(url, time_left))
                    if time_left > final_piece:
                        self.marionette.log('time_left greater than '
                                            'final_piece - {}'
                                            .format(time_left),
                                            level='WARNING')
                        self.save_screenshot()
                else:
                    self.marionette.log('Duration close to 0 - {}'
                                        .format(youtube),
                                        level='WARNING')
                    self.save_screenshot()
                try:
                    verbose_until(Wait(youtube,
                                       timeout=max(100, time_left) * 1.3,
                                       interval=1),
                                  youtube,
                                  YouTubePuppeteer.playback_done)
                except TimeoutException as e:
                    raise self.failureException(e)
Exemplo n.º 34
0
    def test_video_playing_in_one_tab(self):
        with self.marionette.using_context('content'):
            for url in self.video_urls:
                self.logger.info(url)
                youtube = YouTubePuppeteer(self.marionette, url)
                self.logger.info('Expected duration: %s' %
                                 youtube.expected_duration)
                youtube.deactivate_autoplay()

                final_piece = 60
                try:
                    time_left = wait_for_almost_done(youtube,
                                                     final_piece=final_piece)
                except VideoException as e:
                    raise self.failureException(e)
                duration = abs(youtube.expected_duration) + 1
                if duration > 1:
                    self.logger.info('Almost done: %s - %s seconds left.' %
                                     (youtube.movie_id, time_left))
                    if time_left > final_piece:
                        self.marionette.log('time_left greater than '
                                            'final_piece - %s' % time_left,
                                            level='WARNING')
                        self.save_screenshot()
                else:
                    self.marionette.log('Duration close to 0 - %s' % youtube,
                                        level='WARNING')
                    self.save_screenshot()
                try:
                    verbose_until(Wait(youtube,
                                       timeout=max(100, time_left) * 1.3,
                                       interval=1),
                                  youtube,
                                  playback_done)
                except TimeoutException as e:
                    raise self.failureException(e)