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

Code before:
            'thumbnail': r're:https://.+\.webp.*',
            'like_count': int,
            'view_count': int,
            'comment_count': int,
            'repost_count': int,
            'uploader_url': 'https://www.tiktok.com/@MS4wLjABAAAAXcNoOEOxVyBzuII_E--T0MeCrLP0ay1Sm6x_n3dluiWEoWZD0VlQOytwad4W0i0n',
        }
    }, {
        'url': 'https://vt.tiktok.com/ZSe4FqkKd',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        new_url = self._request_webpage(
            HEADRequest(url), self._match_id(url), headers={'User-Agent': 'facebookexternalhit/1.1'}).geturl()
        if self.suitable(new_url):  # Prevent infinite loop in case redirect fails
            raise UnsupportedError(new_url)
        return self.url_result(new_url)


class TikTokLiveIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?tiktok\.com/@(?P<id>[\w\.-]+)/live'
    IE_NAME = 'tiktok:live'

    def _real_extract(self, url):
        uploader_id = self._match_id(url)
        webpage = self._download_webpage(url, uploader_id, headers={'User-Agent': 'User-Agent:Mozilla/5.0'})
        room_id = self._html_search_regex(r'snssdk\d*://live\?room_id=(\d+)', webpage, 'room ID', default=None)
        if room_id:
            live_detail_url = f'https://www.tiktok.com/api/live/detail/?aid=1988&roomID={room_id}'
            # live_detail_url from https://github.com/Pauloo27/tiktok-live/blob/master/index.js#L23
            video_js_data = self._download_json(live_detail_url, room_id)
            title = (traverse_obj(video_js_data, ('LiveRoomInfo', 'title'), expected_type=str)
                     or self._html_search_meta(['og:title', 'twitter:title'], webpage, fatal=True))
            # thumbnail = traverse_obj(video_js_data, ('LiveRoomInfo', 'coverUrl'))
            status = traverse_obj(video_js_data, ('LiveRoomInfo', 'status'), expected_type=int) or 4
            is_live = status == 2  # Not currently live is 4, other numbers have not been encountered for the time being

            base_dict = {
                'title': title,
                'uploader_id': uploader_id,
                'is_live': is_live,
            }

            if is_live:
                liveUrl = traverse_obj(video_js_data, ('LiveRoomInfo', 'liveUrl'), expected_type=str)
                if self.suitable(liveUrl):  # Prevent infinite loop in case redirect fails
                    raise UnsupportedError(liveUrl)
                formats = self._extract_m3u8_formats(
                    liveUrl, room_id, 'mp4')
                infodict = {

Review comment (suggestion):
IMO we should try to keep the metadata fields consistent with the other TikTok IEs, in which case the `@username`/`unique_id`/`uniqueId` would instead be `uploader`
```suggestion
        uploader = self._match_id(url)
```

Code after:
    _UPLOADER_URL_FORMAT = 'https://www.douyin.com/user/%s'
    _WEBPAGE_HOST = 'https://www.douyin.com/'

    def _real_extract(self, url):
        video_id = self._match_id(url)

        try:
            return self._extract_aweme_app(video_id)
        except ExtractorError as e:
            e.expected = True
            self.to_screen(f'{e}; trying with webpage')

        webpage = self._download_webpage(url, video_id)
        render_data_json = self._search_regex(
            r'<script [^>]*\bid=[\'"]RENDER_DATA[\'"][^>]*>(%7B.+%7D)</script>',
            webpage, 'render data', default=None)
        if not render_data_json:
            # TODO: Run verification challenge code to generate signature cookies
            cookies = self._get_cookies(self._WEBPAGE_HOST)
            expected = not cookies.get('s_v_web_id') or not cookies.get('ttwid')
            raise ExtractorError(
                'Fresh cookies (not necessarily logged in) are needed', expected=expected)

        render_data = self._parse_json(
            render_data_json, video_id, transform_source=compat_urllib_parse_unquote)
        return self._parse_aweme_video_web(get_first(render_data, ('aweme', 'detail')), url)


class TikTokVMIE(InfoExtractor):
    _VALID_URL = r'https?://(?:(?:vm|vt)\.tiktok\.com|(?:www\.)tiktok\.com/t)/(?P<id>\w+)'
    IE_NAME = 'vm.tiktok'

    _TESTS = [{
        'url': 'https://www.tiktok.com/t/ZTRC5xgJp',
        'info_dict': {
            'id': '7170520270497680683',
            'ext': 'mp4',
            'title': 'md5:c64f6152330c2efe98093ccc8597871c',
            'uploader_id': '6687535061741700102',
            'upload_date': '20221127',
            'view_count': int,
            'like_count': int,
            'comment_count': int,
            'uploader_url': 'https://www.tiktok.com/@MS4wLjABAAAAObqu3WCTXxmw2xwZ3iLEHnEecEIw7ks6rxWqOqOhaPja9BI7gqUQnjw8_5FSoDXX',
            'album': 'Wave of Mutilation: Best of Pixies',
            'thumbnail': r're:https://.+\.webp.*',
            'duration': 5,
            'timestamp': 1669516858,
            'repost_count': int,
            'artist': 'Pixies',
            'track': 'Where Is My Mind?',