Skip to content

stream.hls: remove Sequence named tuple wrapper #5526

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

bastimeyer
Copy link
Member

@bastimeyer bastimeyer commented Sep 1, 2023

Ref #5498

  1. Turn Segment and Playlist into dataclasses, so they can be subclassed

    • Make TwitchSegment inherit from Segment
    • Update TwitchM3U8Parser accordingly
    • Fix ltv_lsm_lv plugin (previously cloned the Segment named tuple, now simply updates the uri attribute)
  2. Remove Sequence named tuple wrapper, so HLSStream{Writer,Worker} operate on the Segment directly

    • Add num attribute to Segment and initialize with -1
    • Move sequence number logic from HLSStreamWorker to M3U8Parser
    • Update various Sequence references in HLSStream{Writer,Worker}
    • Update generic typevar of HLSStream{Writer,Worker,Reader}
    • Update HLS subclasses accordingly in various plugins

    I was thinking about adding a segment compatibility property with a deprecation warning to Segment, so third-party plugin implementations which subclass HLSStream{Writer,Worker} don't break when they still implement logic for the Sequence wrapper (where the actual segment was accessed via the segment attribute), but I decided against it, because (3) changes the names and signatures of some methods anyway. As said in Refactor segmented streams and use a common BaseSegment #5498, these are not public interfaces, so I don't care.

  3. Update class attributes and method names/signatures of HLSStream{Writer,Worker} after the removal of Sequence

    • Change names from sequence(s) to segment(s)
    • Remove sequences arg from HLSStreamWorker.process_segments() as it's not needed anymore after the sequence number logic was moved to the parser
    • Keep "Sequence" names and log messages for everything that's about the order of segments in the playlist or the position in the stream
    • Update HLS subclasses accordingly in various plugins
  4. Refactor M3U8 playlist loading and update/fix typing

    • Rename stream.hls_playlist.load to stream.hls_playlist.parse_m3u8
    • Replace HLSStreamWorker._reload_playlist() and HLSStream._get_variant_playlist() with direct parse_m3u8() calls, using dependency injection and the HLSStream.__parser__ reference
    • Turn M3U8 into a generic class and add covariant type-vars for the Segment and Playlist dataclasses
    • Turn M3U8Parser into a generic class and add covariant type-vars for the M3U8 class, as well as Segment and Playlist
    • Update HLS Twitch subclasses accordingly

    There are still some typing issues left, but I didn't manage to fix it (yet). I believe there are currently some restrictions (PEP 696 - default values for TypeVars), so unless the whole design of the parser and stuff gets rewritten, this can't be improved further. But I'm not 100% sure. Should be good enough though.


I was also thinking about finally moving the HLS and DASH stuff into their own sub-packages, so we don't have multiple modules lying around in the stream package. This would even make more sense with my plans for the BaseSegment stuff, so the HLS and DASH parsers don't have to import the segmented stream implementations, as the BaseSegment definition would have to go there otherwise. Those changes don't belong in this PR though.


Btw, I'm not expecting any reviews here, because it requires knowledge of the details of the HLS classes. I will merge this when I feel ready.

@bastimeyer bastimeyer added WIP Work in process stream: HLS labels Sep 1, 2023
@bastimeyer bastimeyer force-pushed the stream/hls/refactor-segment branch from 8e23005 to f2b4b9c Compare September 1, 2023 23:22
@bastimeyer bastimeyer removed the WIP Work in process label Sep 3, 2023
@bastimeyer bastimeyer marked this pull request as ready for review September 3, 2023 14:11
@bastimeyer bastimeyer force-pushed the stream/hls/refactor-segment branch from 6f17f38 to 4bb8cc1 Compare September 7, 2023 21:02
@bastimeyer bastimeyer force-pushed the stream/hls/refactor-segment branch from 4bb8cc1 to 134dc65 Compare September 15, 2023 16:03
- Turn `Segment` and `Playlist` into dataclasses,
  so they can be subclassed
- Update `TwitchSegment` and inherit from the default HLS `Segment`
- Update `TwitchM3U8Parser` accordingly
- Fix segment URL updates in `LTVHLSStreamWorker`
- Add `num` attribute to `Segment` and initialize with `-1`
- Move sequence number logic from `HLSStreamWorker` to `M3U8Parser`:
  Update the `num` attribute of each playlist `Segment` after parsing
  instead of wrapping it in a new `Sequence` named tuple
- Remove `Sequence` named tuple wrapper
- Update various `Sequence` references in `HLSStream{Writer,Worker}`
- Update generic typevar of `HLSStream{Writer,Worker,Reader}`
- Update HLS subclasses accordingly in various plugins
- Update tests
- Update method and attribute names after the removal of `Sequence`
- Update method signatures
  - Change argument/keyword names from sequence(s) to segment(s)
  - Remove `sequences` arg from `HLSStreamWorker.process_segments()`
    as it's not needed anymore after the sequence number logic was moved
    to the parser
- Keep "Sequence" names and log messages for everything that's about
  the order of segments in the playlist or the position in the stream
- Update HLS subclasses accordingly in various plugins
- Update tests
- Rename `stream.hls_playlist.load` to `stream.hls_playlist.parse_m3u8`
- Replace `HLSStreamWorker._reload_playlist()`
  and `HLSStream._get_variant_playlist()`
  with direct `parse_m3u8()` calls, using dependency injection
  and the `HLSStream.__parser__` reference
- Turn `M3U8` into a generic class and add covariant type-vars
  for the `Segment` and `Playlist` dataclasses
- Turn `M3U8Parser` into a generic class and add covariant type-vars
  for the `M3U8` class, as well as for `Segment` and `Playlist`
- Update `M3U8Parser.get_{segment,playlist}()`
  and add `M3U8Parser.__{segment,playlist}__` references, to avoid
  having to copy data when subclassing `Segment`/`Playlist` dataclasses
- Update `TwitchHLSStream` and related classes:
  - Set concrete types for `TwitchM3U8`
  - Set concrete types for `TwitchM3U8Parser`
  - Set `TwitchM3U8Parser.__m3u8__` to `TwitchM3U8`
  - Set `TwitchM3U8Parser.__segment__` to `TwitchSegment`
  - Set `TwitchHLSStream.__parser__` to `TwitchM3U8Parser`

Note:
Some typing issues are still unresolved due to shortcomings of current
PEP revisions and typing implementations.
@bastimeyer bastimeyer force-pushed the stream/hls/refactor-segment branch from 134dc65 to 640b668 Compare October 7, 2023 16:09
@bastimeyer
Copy link
Member Author

Rebased to master and fixed merge conflicts. Going to merge now, so I can finally open the follow-up PRs.

As explained, some HLS internals got renamed. Here's a quick summary of the relevant stuff which could potentially be accessed by 3rd party plugins:

  • hls_playlist.load() -> hls_playlist.parse_m3u8()
  • hls.HLSStreamWriter.should_filter_sequence() -> hls.HLSStreamWriter.should_filter_segment()
  • hls.HLSStreamWorker.playlist_sequences -> hls.HLSStreamWorker.playlist_segments
  • hls.HLSStreamWorker.process_sequences() -> hls.HLSStreamWorker.process_segments()
  • hls.HLSStreamWorker.valid_sequence() -> hls.HLSStreamWorker.valid_segment()

@bastimeyer bastimeyer merged commit a13b12d into streamlink:master Oct 7, 2023
@bastimeyer bastimeyer deleted the stream/hls/refactor-segment branch October 7, 2023 16:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant