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

Code before:
        # reference: `id-to-uri.js`
        video_uuid = uuid.uuid5(self._DNS_NAMESPACE, 'video')
        media_uuid = uuid.uuid5(video_uuid, media_id)

        return self._download_json(
            self._GRAPHQL_API, media_id, note='Downloading json from GRAPHQL API', data=json.dumps({
                'query': self._GRAPHQL_QUERY,
                'variables': {'id': f'nyt://video/{media_uuid}'},
            }, separators=(',', ':')).encode(), headers={
                'Content-Type': 'application/json',
                'Nyt-App-Type': 'vhs',
                'Nyt-App-Version': 'v3.52.21',
                'Nyt-Token': self._TOKEN,
                'Origin': 'https://cooking.nytimes.com',
            }, fatal=False) or {}

    def _real_extract(self, url):
        page_id = self._match_id(url)
        webpage = self._download_webpage(url, page_id)

        lead_video_id = self._search_regex(
            r'data-video-player-id="(\d+)"></div>', webpage, 'lead video', default=None)
        media_items = traverse_obj(
            get_elements_html_by_class('video-item', webpage), (..., {extract_attributes}, 'data-video-id'))
        title = self._html_search_meta(['og:title', 'twitter:title'], webpage)
        description = self._html_search_meta(['og:description', 'twitter:description'], webpage)

        if media_items:
            media_items.append(lead_video_id)
            return self.playlist_result(self._build_playlist(media_items), page_id, title, description)

        json_obj = traverse_obj(self._json_from_graphql(lead_video_id) or {}, ('data', 'video'))

        formats, subtitles = self._extract_media_from_json(lead_video_id, json_obj)

        return {
            'id': lead_video_id,
            'title': title,
            'description': description,
            'duration': int_or_none(json_obj.get('duration')),
            'creator': self._search_regex(
                r'<span itemprop="author">([^<]+)</span></p>', webpage, 'author', default=None),  # TODO: change to 'creators'
            'formats': formats,
            'subtitles': subtitles,
            'thumbnails': self._extract_thumbnails(
                traverse_obj(json_obj, ('promotionalMedia', 'crops', ..., 'renditions', ...))),
        }


Review comment (refactor):
I don't think `lead_video_id` should be non-fatal? Or else we need to check before appending it to `media_ids` and we should raise after the playlist_result code path
```suggestion
        title = self._html_search_meta(['og:title', 'twitter:title'], webpage)
        description = self._html_search_meta(['og:description', 'twitter:description'], webpage)

        lead_video_id = self._search_regex(
            r'data-video-player-id="(\d+)"></div>', webpage, 'lead video')
        media_ids = traverse_obj(
            get_elements_html_by_class('video-item', webpage), (..., {extract_attributes}, 'data-video-id'))
```

Code after:
            'upload_date': '20190102',
            'title': 'Overnight Oats',
            'creator': 'Genevieve Ko',
            'thumbnail': r're:https?://\w+\.nyt.com/images/.*\.jpg',
        },
    }]

    def _real_extract(self, url):
        page_id = self._match_id(url)
        webpage = self._download_webpage(url, page_id)
        recipe_data = self._search_nextjs_data(webpage, page_id)['props']['pageProps']['recipe']

        formats, subtitles = self._extract_m3u8_formats_and_subtitles(
            recipe_data['videoSrc'], page_id, 'mp4', m3u8_id='hls')

        return {
            **traverse_obj(recipe_data, {
                'id': ('id', {str_or_none}),
                'title': ('title', {str}),
                'description': ('topnote', {clean_html}),
                'timestamp': ('publishedAt', {int_or_none}),
                'creator': ('contentAttribution', 'cardByline', {str}),
            }),
            'formats': formats,
            'subtitles': subtitles,
            'thumbnails': [{'url': thumb_url} for thumb_url in traverse_obj(
                recipe_data, ('image', 'crops', 'recipe', ..., {url_or_none}))],
        }