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

Code before:
        # TODO: add support for TikTok Live events, see https://github.com/isaackogan/TikTokLive for reference
        webpage = self._download_webpage(url, self._match_id(url), 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 not room_id:
            raise ExtractorError('The user is not currently live', expected=True)
        video_js_data = self._download_json(
            'https://www.tiktok.com/api/live/detail/', room_id, query={
                'aid': '1988',
                'roomID': room_id,
            })
        # status = 2 if live else 4
        is_live = traverse_obj(video_js_data, ('LiveRoomInfo', 'status'), expected_type=int, default=4) == 2
        if not is_live:
            raise ExtractorError('The user is not currently live', expected=True)
        live_url = traverse_obj(video_js_data, ('LiveRoomInfo', 'liveUrl'), expected_type=url_or_none)
        if not live_url:
            raise ExtractorError('No stream URL found')

        return {
            'id': room_id,
            'title': (traverse_obj(video_js_data, ('LiveRoomInfo', 'title'), expected_type=str)
                      or self._html_search_meta(['og:title', 'twitter:title'], webpage, default='')),
            'uploader': traverse_obj(video_js_data, ('LiveRoomInfo', 'ownerInfo', 'uniqueId'), default=''),
            'uploader_id': traverse_obj(video_js_data, ('LiveRoomInfo', 'ownerInfo', 'id'), default=''),
            'creator': traverse_obj(video_js_data, ('LiveRoomInfo', 'ownerInfo', 'nickname'), default=''),
            'thumbnail': traverse_obj(video_js_data, ('LiveRoomInfo', 'coverUrl'), default='').replace("720x720", "gcp"),
            'concurrent_view_count': traverse_obj(video_js_data, ('LiveRoomInfo', 'liveRoomStats', 'userCount'), expected_type=int),
            'formats': self._extract_m3u8_formats(live_url, room_id, 'mp4', live=is_live),
            'is_live': is_live,
        }


Review comment (suggestion):
the `thumbnail` workaround is too much of an unknown to include it, IMO.

we want `uploader_id` and `creator` to be `None` if not found in the JSON response.
and if we set the var `uploader` above, it can be used as fallback value
```suggestion
            'uploader': traverse_obj(video_js_data, ('LiveRoomInfo', 'ownerInfo', 'uniqueId')) or uploader,
            'uploader_id': traverse_obj(video_js_data, ('LiveRoomInfo', 'ownerInfo', 'id')),
            'creator': traverse_obj(video_js_data, ('LiveRoomInfo', 'ownerInfo', 'nickname')),
```

Code after:
    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?',
            'description': 'md5:c64f6152330c2efe98093ccc8597871c',
            'uploader': 'sigmachaddeus',
            'creator': 'SigmaChad',
        },
    }, {
        'url': 'https://vm.tiktok.com/ZTR45GpSF/',
        'info_dict': {
            'id': '7106798200794926362',
            'ext': 'mp4',
            'title': 'md5:edc3e7ea587847f8537468f2fe51d074',
            'uploader_id': '6997695878846268418',
            'upload_date': '20220608',
            'view_count': int,
            'like_count': int,
            'comment_count': int,
            'thumbnail': r're:https://.+\.webp.*',
            'uploader_url': 'https://www.tiktok.com/@MS4wLjABAAAAdZ_NcPPgMneaGrW0hN8O_J_bwLshwNNERRF5DxOw2HKIzk0kdlLrR8RkVl1ksrMO',
            'duration': 29,
            'timestamp': 1654680400,
            'repost_count': int,
            'artist': 'Akihitoko',
            'track': 'original sound',
            'description': 'md5:edc3e7ea587847f8537468f2fe51d074',
            'uploader': 'akihitoko1',
            'creator': 'Akihitoko',
        },
    }, {
        'url': 'https://vt.tiktok.com/ZSe4FqkKd',
        'only_matching': True,
    }]