1
mirror of https://github.com/streamlink/streamlink synced 2024-11-01 01:19:33 +01:00

Merge pull request #1804 from back-to/times

api.utils: hours_minutes_seconds update, twitch automate time offset
This commit is contained in:
Forrest 2018-06-24 19:41:13 -07:00 committed by GitHub
commit 3e021c548c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 105 additions and 42 deletions

View File

@ -13,6 +13,7 @@ from streamlink.plugin.api.utils import parse_json, parse_query
from streamlink.stream import (
HTTPStream, HLSStream, FLVPlaylist, extract_flv_header_tags
)
from streamlink.utils.times import hours_minutes_seconds
try:
from itertools import izip as zip
@ -55,17 +56,6 @@ _url_re = re.compile(r"""
(?P<clip_name>[\w]+)
)?
""", re.VERBOSE)
_time_re = re.compile(r"""
(?:
(?P<hours>\d+)h
)?
(?:
(?P<minutes>\d+)m
)?
(?:
(?P<seconds>\d+)s
)?
""", re.VERBOSE)
_access_token_schema = validate.Schema(
{
@ -138,18 +128,6 @@ _quality_options_schema = validate.Schema(
)
def time_to_offset(t):
match = _time_re.match(t)
if match:
offset = int(match.group("hours") or "0") * 60 * 60
offset += int(match.group("minutes") or "0") * 60
offset += int(match.group("seconds") or "0")
else:
offset = 0
return offset
class UsherService(object):
def _create_url(self, endpoint, **extra_params):
url = "https://usher.ttvnw.net{0}".format(endpoint)
@ -541,7 +519,12 @@ class Twitch(Plugin):
# start offset if needed.
time_offset = self.params.get("t")
if time_offset:
videos["start_offset"] += time_to_offset(self.params.get("t"))
try:
time_offset = hours_minutes_seconds(time_offset)
except ValueError:
time_offset = 0
videos["start_offset"] += time_offset
return self._create_playlist_streams(videos)
@ -599,10 +582,18 @@ class Twitch(Plugin):
self.logger.debug("Unknown HLS stream type: {0}".format(stream_type))
return {}
time_offset = self.params.get("t", 0)
if time_offset:
try:
time_offset = hours_minutes_seconds(time_offset)
except ValueError:
time_offset = 0
try:
# 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,
start_offset=time_offset,
force_restart=not stream_type == "live")
except IOError as err:
err = str(err)

View File

@ -0,0 +1,52 @@
import re
_hours_minutes_seconds_re = re.compile(r"""
^-?(?P<hours>\d+):(?P<minutes>\d+):(?P<seconds>\d+)$
""", re.VERBOSE)
_hours_minutes_seconds_2_re = re.compile(r"""^-?
(?:
(?P<hours>\d+)h
)?
(?:
(?P<minutes>\d+)m
)?
(?:
(?P<seconds>\d+)s
)?$
""", re.VERBOSE | re.IGNORECASE)
def hours_minutes_seconds(value):
"""converts a timestamp to seconds
- hours:minutes:seconds to seconds
- 11h22m33s to seconds
- 11h to seconds
- 20h15m to seconds
- seconds to seconds
:param value: hh:mm:ss ; 00h00m00s ; seconds
:return: seconds
"""
try:
return int(value)
except ValueError:
pass
match = (_hours_minutes_seconds_re.match(value)
or _hours_minutes_seconds_2_re.match(value))
if not match:
raise ValueError
s = 0
s += int(match.group("hours") or "0") * 60 * 60
s += int(match.group("minutes") or "0") * 60
s += int(match.group("seconds") or "0")
return s
__all__ = [
"hours_minutes_seconds",
]

View File

@ -4,6 +4,7 @@ from string import printable
from textwrap import dedent
from streamlink import logger
from streamlink.utils.times import hours_minutes_seconds
from .constants import (
LIVESTREAMER_VERSION, STREAM_PASSTHROUGH, DEFAULT_PLAYER_ARGUMENTS
)
@ -24,7 +25,6 @@ _option_re = re.compile(r"""
\s*
(?P<value>.*) # The value, anything goes.
""", re.VERBOSE)
_hours_minutes_seconds_re = re.compile(r"-?(?P<hours>\d+):(?P<minutes>\d+):(?P<seconds>\d+)")
class ArgumentParser(argparse.ArgumentParser):
@ -140,23 +140,6 @@ def boolean(value):
return value.lower() in truths
def hours_minutes_seconds(value):
"""
converts hours:minutes:seconds to seconds
:param value: hh:mm:ss
:return: seconds
"""
match = _hours_minutes_seconds_re.match(value)
if not match:
raise ValueError
s = 0
s += int(match.group("hours")) * 60 * 60
s += int(match.group("minutes")) * 60
s += int(match.group("seconds"))
return s
def build_parser():
parser = ArgumentParser(
prog="streamlink",

37
tests/test_utils_times.py Normal file
View File

@ -0,0 +1,37 @@
import unittest
from streamlink.utils.times import hours_minutes_seconds
class TestUtilsTimes(unittest.TestCase):
def test_hours_minutes_seconds(self):
self.assertEqual(hours_minutes_seconds("00:01:30"), 90)
self.assertEqual(hours_minutes_seconds("01:20:15"), 4815)
self.assertEqual(hours_minutes_seconds("26:00:00"), 93600)
self.assertEqual(hours_minutes_seconds("07"), 7)
self.assertEqual(hours_minutes_seconds("444"), 444)
self.assertEqual(hours_minutes_seconds("8888"), 8888)
self.assertEqual(hours_minutes_seconds("01h"), 3600)
self.assertEqual(hours_minutes_seconds("01h22m33s"), 4953)
self.assertEqual(hours_minutes_seconds("01H22M37S"), 4957)
self.assertEqual(hours_minutes_seconds("01h30s"), 3630)
self.assertEqual(hours_minutes_seconds("1m33s"), 93)
self.assertEqual(hours_minutes_seconds("55s"), 55)
self.assertEqual(hours_minutes_seconds("-00:01:40"), 100)
self.assertEqual(hours_minutes_seconds("-00h02m30s"), 150)
with self.assertRaises(ValueError):
hours_minutes_seconds("02:04")
with self.assertRaises(ValueError):
hours_minutes_seconds("FOO")
with self.assertRaises(ValueError):
hours_minutes_seconds("BAR")
with self.assertRaises(ValueError):
hours_minutes_seconds("11:ERR:00")