Repository: streamlink/streamlink

Issue:
Twitch: Playing vods of still recording streams dont start at the beginning
Hi.
Basicially when you want to watch a vod via
streamlink twitch.tv/someguy/v/12344321 high
and the vod you are referencing is still getting recorded aka the streamer is still live and the stream is recorded to that vod ( 12344321 ) streamlink will just stream whatever is currently streamed by the streamer.
I expected that streamlink would start from the vod beginning tho. If I wanted to watch the current stream, i wouldnt specifiy the vod.


Discussion:
The `HLSStream` class assumes that it's a live stream if the stream is incomplete. As the VOD is still recording it looks the same as a live stream to streamlink, and so plays it from the end. This is normally what you want, except of course, in this case where you are requesting a VOD and you reasonably expect it to start from the beginning. 

I'll put together a PR to offer a solution. 

Resolving patch:
diff --git a/src/streamlink/plugins/twitch.py b/src/streamlink/plugins/twitch.py
--- a/src/streamlink/plugins/twitch.py
+++ b/src/streamlink/plugins/twitch.py
@@ -496,7 +496,10 @@ def _get_hls_streams(self, stream_type="live"):
             return {}
 
         try:
-            streams = HLSStream.parse_variant_playlist(self.session, url)
+            # If the stream is a VOD that is still being recorded the stream should start at the
+            # beginning of the recording
+            streams = HLSStream.parse_variant_playlist(self.session, url,
+                                                       force_restart=not stream_type == "live")
         except IOError as err:
             err = str(err)
             if "404 Client Error" in err or "Failed to parse playlist" in err:
diff --git a/src/streamlink/stream/hls.py b/src/streamlink/stream/hls.py
--- a/src/streamlink/stream/hls.py
+++ b/src/streamlink/stream/hls.py
@@ -189,7 +189,7 @@ def process_sequences(self, playlist, sequences):
             self.playlist_end = last_sequence.num
 
         if self.playlist_sequence < 0:
-            if self.playlist_end is None:
+            if self.playlist_end is None and not self.stream.force_restart:
                 edge_index = -(min(len(sequences), max(int(self.live_edge), 1)))
                 edge_sequence = sequences[edge_index]
                 self.playlist_sequence = edge_sequence.num
@@ -252,8 +252,9 @@ class HLSStream(HTTPStream):
 
     __shortname__ = "hls"
 
-    def __init__(self, session_, url, **args):
+    def __init__(self, session_, url, force_restart=False, **args):
         HTTPStream.__init__(self, session_, url, **args)
+        self.force_restart = force_restart
 
     def __repr__(self):
         return "<HLSStream({0!r})>".format(self.url)
@@ -276,6 +277,7 @@ def open(self):
     @classmethod
     def parse_variant_playlist(cls, session_, url, name_key="name",
                                name_prefix="", check_streams=False,
+                               force_restart=False,
                                **request_params):
         """Attempts to parse a variant playlist and return its streams.
 
@@ -283,6 +285,7 @@ def parse_variant_playlist(cls, session_, url, name_key="name",
         :param name_key: Prefer to use this key as stream name, valid keys are:
                          name, pixels, bitrate.
         :param name_prefix: Add this prefix to the stream names.
+        :param force_restart: Start at the first segment even for a live stream
         :param check_streams: Only allow streams that are accesible.
         """
 
@@ -338,7 +341,7 @@ def parse_variant_playlist(cls, session_, url, name_key="name",
                 except Exception:
                     continue
 
-            stream = HLSStream(session_, playlist.uri, **request_params)
+            stream = HLSStream(session_, playlist.uri, force_restart=force_restart, **request_params)
             streams[name_prefix + stream_name] = stream
 
         return streams


Test patch: