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

Code before:
                            subtitles.setdefault(media.get('LANGUAGE'), []).append({
                                'url': media.get('URI'),
                                'ext': 'vtt'
                            })

        if metadata.get('instructor_cues'):
            subtitles['cues'] = [{
                'data': json.dumps(metadata.get('instructor_cues')),
                'ext': 'json'
            }]

        release_date = None
        if metadata['ride'].get('original_air_time'):
            release_datetime = datetime.datetime.utcfromtimestamp(metadata['ride'].get('original_air_time'))
            if release_datetime:
                release_date = release_datetime.strftime('%Y%m%d')
        creator = None
        if metadata['ride'].get('instructor') and metadata['ride'].get('instructor').get('name'):
            creator = metadata['ride'].get('instructor').get('name')
        categories = None
        if metadata['ride'].get('fitness_discipline_display_name'):
            categories = [metadata['ride'].get('fitness_discipline_display_name')]
        tags = None
        if metadata['ride'].get('equipment_tags'):
            tags = []
            for equipment in metadata['ride'].get('equipment_tags'):
                if equipment.get('name'):
                    tags.append(equipment.get('name'))
        chapters = None
        if metadata.get('segments') and metadata.get('segments').get('segment_list'):
            chapters = []
            for segment in metadata.get('segments').get('segment_list'):
                if segment.get('start_time_offset') is not None and segment.get('length') and segment.get('name'):
                    chapters.append({
                        'start_time': segment.get('start_time_offset'),
                        'end_time': segment.get('start_time_offset') + segment.get('length'),
                        'title': segment.get('name')
                    })

        return {
            'id': video_id,
            'title': metadata['ride'].get('title'),
            'formats': formats,
            'url': url,
            'manifest_url': url,
            'ext': ext,
            'thumbnail': try_get(metadata, lambda x: x['ride']['image_url'], compat_str),
            'description': try_get(metadata, lambda x: x['ride']['description'], compat_str),
            'creator': creator,
            'release_date': release_date,
            'timestamp': try_get(metadata, lambda x: x['ride']['original_air_time'], compat_integer_types),

Review comment (suggestion):
```suggestion
            for equipment in metadata['ride'].get('equipment_tags') or []:
```

Code after:
                url = 'https://members.onepeloton.com/.netlify/functions/m3u8-proxy?displayLanguage=en&acceptedSubtitles=%s&url=%s?hdnea=%s' % (
                    ','.join([re.sub('^([a-z]+)-([A-Z]+)$', r'\1', caption) for caption in ride_data['captions']]),
                    ride_data['vod_stream_url'],
                    compat_urllib_parse.quote(compat_urllib_parse.quote(token)))
            elif ride_data.get('live_stream_url'):
                url = self._MANIFEST_URL_TEMPLATE % (ride_data.get('live_stream_url'), compat_urllib_parse.quote(token))
                is_live = True
            else:
                raise ExtractorError('Missing video URL')
            formats, subtitles = self._extract_m3u8_formats_and_subtitles(url, video_id, 'mp4')

        if metadata.get('instructor_cues'):
            subtitles['cues'] = [{
                'data': json.dumps(metadata.get('instructor_cues')),
                'ext': 'json'
            }]

        category = ride_data.get('fitness_discipline_display_name')
        chapters = [{
            'start_time': segment.get('start_time_offset'),
            'end_time': segment.get('start_time_offset') + segment.get('length'),
            'title': segment.get('name')
        } for segment in traverse_obj(metadata, ('segments', 'segment_list'))]

        self._sort_formats(formats)
        return {
            'id': video_id,
            'title': ride_data.get('title'),
            'formats': formats,
            'thumbnail': url_or_none(ride_data.get('image_url')),
            'description': str_or_none(ride_data.get('description')),
            'creator': traverse_obj(ride_data, ('instructor', 'name')),
            'release_timestamp': ride_data.get('original_air_time'),
            'timestamp': ride_data.get('original_air_time'),
            'subtitles': subtitles,
            'duration': float_or_none(ride_data.get('length')),
            'categories': [category] if category else None,
            'tags': traverse_obj(ride_data, ('equipment_tags', ..., 'name')),
            'is_live': is_live,
            'chapters': chapters
        }


class PelotonLiveIE(InfoExtractor):
    IE_NAME = 'peloton:live'
    IE_DESC = 'Peloton Live'
    _VALID_URL = r'https?://members\.onepeloton\.com/player/live/(?P<id>[a-f0-9]+)'
    _TEST = {
        'url': 'https://members.onepeloton.com/player/live/eedee2d19f804a9788f53aa8bd38eb1b',
        'info_dict': {
            'id': '32edc92d28044be5bf6c7b6f1f8d1cbc',