Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/youtube/_video.py (Python)

Code before:
                    'duration': min(fragment_duration, duration - (j * fragment_duration)),
                } for j in range(math.ceil(fragment_count))],
            }

    def _download_initial_webpage(self, webpage_url, webpage_client, video_id):
        webpage = None
        if webpage_url and 'webpage' not in self._configuration_arg('player_skip'):
            query = {'bpctr': '9999999999', 'has_verified': '1'}
            pp = (
                self._configuration_arg('player_params', [None], casesense=True)[0]
                or traverse_obj(INNERTUBE_CLIENTS, (webpage_client, 'PLAYER_PARAMS', {str}))
            )
            if pp:
                query['pp'] = pp
            webpage = self._download_webpage_with_retries(
                webpage_url, video_id, query=query,
                headers=traverse_obj(self._get_default_ytcfg(webpage_client), {
                    'User-Agent': ('INNERTUBE_CONTEXT', 'client', 'userAgent', {str}),
                }))
        return webpage

    def _parse_instream_ad_renderer(self, renderer):
        instream_renderer = traverse_obj(renderer, ('instreamVideoAdRenderer', {dict})) or {}
        length_ms = traverse_obj(instream_renderer, ('skipOffsetMilliseconds', {int}))
        if length_ms is not None:
            self.write_debug(f'Detected a {length_ms}ms skippable ad')
            return length_ms
        length_ms = traverse_obj(instream_renderer, ('playerVars', {urllib.parse.parse_qs}, 'length_seconds', -1, {int_or_none(invscale=1000)}))
        if length_ms is not None:
            self.write_debug(f'Detected a {length_ms}ms non-skippable ad')
            return length_ms
        return None

    def _get_preroll_length(self, ad_slot_lists):
        for slot_renderer in traverse_obj(ad_slot_lists, ('adSlots', ..., 'adSlotRenderer', {dict})):
            if traverse_obj(slot_renderer, ('adSlotMetadata', 'triggerEvent')) != 'SLOT_TRIGGER_EVENT_BEFORE_CONTENT':
                continue
            rendering_content = traverse_obj(slot_renderer, (
                'fulfillmentContent', 'fulfilledLayout', 'playerBytesAdLayoutRenderer',
                'renderingContent', {dict})) or {}
            if 'instreamVideoAdRenderer' in rendering_content:
                length = self._parse_instream_ad_renderer(rendering_content)
                if length is not None:
                    return length
            if 'playerBytesSequentialLayoutRenderer' in rendering_content:
                total = 0
                for layout in traverse_obj(rendering_content, ('playerBytesSequentialLayoutRenderer', 'sequentialLayouts'), []):
                    total += self._parse_instream_ad_renderer(traverse_obj(layout, ('playerBytesAdLayoutRenderer', 'renderingContent', {dict}))) or 0
                return total
        return 0


Review comment (bug):
Should we humanize the wait time? a la
```suggestion
            length = length_ms / 1000 if length_ms % 1000 else length_ms // 1000
            self.write_debug(f'Detected a {length}s skippable ad')
```

Code after:
                if itag in ('616', '235'):
                    f['format_note'] = join_nonempty(f.get('format_note'), 'Premium', delim=' ')
                    f['source_preference'] += 100

                f['quality'] = q(itag_qualities.get(try_get(f, lambda f: f['format_id'].split('-')[0]), -1))
                if f['quality'] == -1 and f.get('height'):
                    f['quality'] = q(res_qualities[min(res_qualities, key=lambda x: abs(x - f['height']))])
                if self.get_param('verbose') or all_formats:
                    f['format_note'] = join_nonempty(
                        f.get('format_note'), short_client_name(client_name), delim=', ')
                if f.get('fps') and f['fps'] <= 1:
                    del f['fps']

                if proto == 'hls' and f.get('has_drm'):
                    f['has_drm'] = 'maybe'
                    f['source_preference'] -= 5
                return True

            hls_manifest_url = 'hls' not in skip_manifests and streaming_data.get('hlsManifestUrl')
            if hls_manifest_url:
                pot_policy: GvsPoTokenPolicy = self._get_default_ytcfg(
                    client_name)['GVS_PO_TOKEN_POLICY'][StreamingProtocol.HLS]
                require_po_token = gvs_pot_required(pot_policy, is_premium_subscriber, player_token_provided)
                po_token = gvs_pots.get(client_name, fetch_po_token_func(required=require_po_token or pot_policy.recommended))
                if po_token:
                    hls_manifest_url = hls_manifest_url.rstrip('/') + f'/pot/{po_token}'
                    if client_name not in gvs_pots:
                        gvs_pots[client_name] = po_token
                if require_po_token and not po_token and 'missing_pot' not in self._configuration_arg('formats'):
                    self._report_pot_format_skipped(video_id, client_name, 'hls')
                else:
                    fmts, subs = self._extract_m3u8_formats_and_subtitles(
                        hls_manifest_url, video_id, 'mp4', fatal=False, live=live_status == 'is_live')
                    for sub in traverse_obj(subs, (..., ..., {dict})):
                        # TODO: If HLS video requires a PO Token, do the subs also require pot?
                        # Save client name for debugging
                        sub[STREAMING_DATA_CLIENT_NAME] = client_name
                    subtitles = self._merge_subtitles(subs, subtitles)
                    for f in fmts:
                        if process_manifest_format(f, 'hls', client_name, self._search_regex(
                                r'/itag/(\d+)', f['url'], 'itag', default=None), require_po_token and not po_token):
                            yield f

            dash_manifest_url = 'dash' not in skip_manifests and streaming_data.get('dashManifestUrl')
            if dash_manifest_url:
                pot_policy: GvsPoTokenPolicy = self._get_default_ytcfg(
                    client_name)['GVS_PO_TOKEN_POLICY'][StreamingProtocol.DASH]
                require_po_token = gvs_pot_required(pot_policy, is_premium_subscriber, player_token_provided)
                po_token = gvs_pots.get(client_name, fetch_po_token_func(required=require_po_token or pot_policy.recommended))
                if po_token:
                    dash_manifest_url = dash_manifest_url.rstrip('/') + f'/pot/{po_token}'