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

Code before:
                'https://live.erinn.biz/live.timeshift.fplayer.php', video_id,
                query={'hash': video_id},
                note='Downloading player html',
                errnote='Unable to download player html')

            # https://regex101.com/r/3AXpSA/3
            sources = self._search_regex(r'var fplayer_source = ([^;]+)', player_html, 'sources')
            sources_json = self._parse_json(sources.replace('.mp4",', '.mp4"'), video_id)

            formats = []
            for source in sources_json:
                path = source.get('file')
                formats.append({
                    'url': urljoin('https://live.erinn.biz', path),
                    'ext': 'mp4',
                    'protocol': 'm3u8_native',
                })

            return {
                'id': video_id,
                'title': title,
                'description': description,
                'timestamp': sources_json[0].get('time_start'),
                'thumbnail': thumbnail,
                'formats': formats,
            }

        raise ExtractorError('Cannot parse live stream or VOD', expected=True)


Review comment (suggestion):
I think these are not separate formats of the same video, but segments of the stream, say if the connection dropped for part of the stream.
So maybe returning this as a multi video would make sense:
```suggestion
            entries = []
            for i, segment in enumerate(sources_json):
                path = segment.get('file')
                if not path:
                    continue
                formats = [{
                    'url': urljoin('https://live.erinn.biz', path),
                    'ext': 'mp4',
                    'protocol': 'm3u8_native',
                }]
                entries.append({
                    'id': f'{video_id}_{i}',
                    'title': f'{title} (Part {i + 1})',
                    'description': description,
                    'timestamp': traverse_obj(segment, ('time_start', {int_or_none})),
                    'thumbnail': thumbnail,
                    'formats': formats,
                })
            return self.playlist_result(entries, video_id, title, description, multi_video=True)
```
Potentially, we would want some additional logic to return it as a single video if there is only one segment.

Code after:
                quality_meta = self._get_quality_meta(video_id, desc, code)
                self._add_quality_formats(formats, quality_meta)
                if desc == 'high' and traverse_obj(quality_meta, ('vcodec', 0)) == 'HEVC':
                    self._add_quality_formats(
                        formats, self._get_quality_meta(video_id, desc, code, force_h264='1'))

            return {
                'id': video_id,
                'title': title,
                'description': description,
                'thumbnail': thumbnail,
                'is_live': True,
                'formats': formats,
            }

        # VOD extraction
        player_html = self._download_webpage(
            'https://live.erinn.biz/live.timeshift.fplayer.php', video_id,
            'Downloading player html', 'Unable to download player html', query={'hash': video_id})

        sources = traverse_obj(self._search_json(
            r'var\s+fplayer_source\s*=', player_html, 'stream data', video_id,
            contains_pattern=r'\[(?s:.+)\]', transform_source=js_to_json), lambda _, v: v['file'])

        def entries(segments, playlist=True):
            for i, segment in enumerate(segments, 1):
                yield {
                    'id': f'{video_id}_{i}' if playlist else video_id,
                    'title': f'{title} (Part {i})' if playlist else title,
                    'description': description,
                    'timestamp': traverse_obj(segment, ('time_start', {int_or_none})),
                    'thumbnail': thumbnail,
                    'formats': [{
                        'url': urljoin('https://live.erinn.biz', segment['file']),
                        'ext': 'mp4',
                        'protocol': 'm3u8_native',
                    }],
                }

        if len(sources) == 1:
            return next(entries(sources, playlist=False))

        return self.playlist_result(entries(sources), video_id, title, description, multi_video=True)