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

Code before:

    def _real_extract(self, url):
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)
        nuxt_data = self._search_nuxt_data(webpage, video_id)

        parent = {
            'title': nuxt_data.get('title'),
            'descripion': nuxt_data.get('description'),
            'reply': nuxt_data.get('thanks'),
            'uploader': traverse_obj(nuxt_data, ('creator', 'name')),
            'uploader_id': traverse_obj(nuxt_data, ('creator', 'screen_name')),
            'age_limit': 18 if nuxt_data.get('nsfw') else 0,
            'tags': nuxt_data.get('tag_list'),
        }

        entries = []
        for item in nuxt_data.get('previews') or []:
            vid_url = item.get('url')
            given_ext = traverse_obj(item, ('information', 'extension'))
            mimetype = ext2mimetype(given_ext)
            if mimetype != 'image/gif' and mimetype.partition('/')[0] != 'video':
                continue
            entries.append({
                **parent,
                'id': compat_str(item.get('id')),
                'url': vid_url,
                'thumbnail': item.get('poster_url'),
                'subtitles': {
                    'jpn': [{
                        'url': item.get('vtt_url'),
                        'ext': 'vtt',
                    }]
                } if item.get('vtt_url') else None,
                'width': traverse_obj(item, ('information', 'width')),
                'height': traverse_obj(item, ('information', 'height')),
                'duration': traverse_obj(item, ('information', 'duration')),
                'filesize': traverse_obj(item, ('information', 'byte_size')),
                'fps': traverse_obj(item, ('information', 'frame_rate')),
                'ext': determine_ext(vid_url) or given_ext,
            })

        if not entries:
            raise ExtractorError('No video attachment found in this commission.', expected=True)
        elif len(entries) == 1:
            entries['id'] = parent['id']
            return entries[0]
        else:
            parent.update({
                '_type': 'multi_video',
                'entries': entries,

Review comment (suggestion):
id should be fatal or since this is a playlist, append only if id exists.
also just use `str` instead of `compat_str` so it's not a lazy backport to ytdl 😈 

Code after:
    _TESTS = [{
        'url': 'https://skeb.jp/@riiru_wm/works/10',
        'info_dict': {
            'id': '466853',
            'title': '内容はおまかせします！ by 姫ノ森りぃる@一周年',
            'descripion': 'md5:1ec50901efc3437cfbfe3790468d532d',
            'uploader': '姫ノ森りぃる@一周年',
            'uploader_id': 'riiru_wm',
            'age_limit': 0,
            'tags': [],
            'url': r're:https://skeb.+',
            'thumbnail': r're:https://skeb.+',
            'subtitles': {
                'jpn': [{
                    'url': r're:https://skeb.+',
                    'ext': 'vtt'
                }]
            },
            'width': 720,
            'height': 405,
            'duration': 313,
            'fps': 30,
            'ext': 'mp4',
        },
    }, {
        'url': 'https://skeb.jp/@furukawa_nob/works/3',
        'info_dict': {
            'id': '489408',
            'title': 'いつもお世話になってお... by 古川ノブ@音楽とVlo...',
            'descripion': 'md5:5adc2e41d06d33b558bf7b1faeb7b9c2',
            'uploader': '古川ノブ@音楽とVlogのVtuber',
            'uploader_id': 'furukawa_nob',
            'age_limit': 0,
            'tags': [
                'よろしく', '大丈夫', 'お願い', 'でした',
                '是非', 'O', 'バー', '遊び', 'おはよう',
                'オーバ', 'ボイス',
            ],
            'url': r're:https://skeb.+',
            'thumbnail': r're:https://skeb.+',
            'subtitles': {
                'jpn': [{
                    'url': r're:https://skeb.+',
                    'ext': 'vtt'
                }]
            },
            'duration': 98,
            'ext': 'mp3',
            'vcodec': 'none',
            'abr': 128,
        },