[arch-commits] Commit in livestreamer/trunk (2 files)

Evangelos Foutras foutrelis at archlinux.org
Sun Feb 8 16:16:01 UTC 2015


    Date: Sunday, February 8, 2015 @ 17:16:00
  Author: foutrelis
Revision: 127300

upgpkg: livestreamer 1.11.1-2

Add upstream fix for the hitbox plugin.

Added:
  livestreamer/trunk/plugins-hitbox-Refactor-to-use-the-StreamMapper.patch
Modified:
  livestreamer/trunk/PKGBUILD

-------------------------------------------------------+
 PKGBUILD                                              |   15 -
 plugins-hitbox-Refactor-to-use-the-StreamMapper.patch |  197 ++++++++++++++++
 2 files changed, 209 insertions(+), 3 deletions(-)

Modified: PKGBUILD
===================================================================
--- PKGBUILD	2015-02-08 14:20:49 UTC (rev 127299)
+++ PKGBUILD	2015-02-08 16:16:00 UTC (rev 127300)
@@ -3,7 +3,7 @@
 # Contributor: Christopher Rosell <chrippa at tanuki.se>
 pkgname=livestreamer
 pkgver=1.11.1
-pkgrel=1
+pkgrel=2
 pkgdesc='CLI program that launches streams from various streaming services in a custom video player'
 arch=('any')
 url='https://github.com/chrippa/livestreamer'
@@ -10,9 +10,18 @@
 license=('BSD')
 depends=('python-requests' 'rtmpdump' 'python-setuptools')
 makedepends=('python-sphinx')
-source=(https://pypi.python.org/packages/source/l/$pkgname/$pkgname-$pkgver.tar.gz)
-sha256sums=('84dd83d301518ffcf96f30cbffc0e0598e0756e7ab8e7498d11285d42fe17f9c')
+source=(https://pypi.python.org/packages/source/l/$pkgname/$pkgname-$pkgver.tar.gz
+        plugins-hitbox-Refactor-to-use-the-StreamMapper.patch)
+sha256sums=('84dd83d301518ffcf96f30cbffc0e0598e0756e7ab8e7498d11285d42fe17f9c'
+            '1a305add9db98912f0cdb16862d1296588b2ed299587de26d93c5be53f9fd572')
 
+prepare() {
+  cd "$srcdir/$pkgname-$pkgver"
+
+  # https://github.com/chrippa/livestreamer/issues/648
+  patch -Np1 -i ../plugins-hitbox-Refactor-to-use-the-StreamMapper.patch
+}
+
 build() {
   cd "$srcdir/$pkgname-$pkgver"
   python setup.py build_sphinx -b man

Added: plugins-hitbox-Refactor-to-use-the-StreamMapper.patch
===================================================================
--- plugins-hitbox-Refactor-to-use-the-StreamMapper.patch	                        (rev 0)
+++ plugins-hitbox-Refactor-to-use-the-StreamMapper.patch	2015-02-08 16:16:00 UTC (rev 127300)
@@ -0,0 +1,197 @@
+From 3cd7f604b9f3327f7626b719a3035c47a68ea9a2 Mon Sep 17 00:00:00 2001
+From: Christopher Rosell <chrippa at tanuki.se>
+Date: Tue, 16 Dec 2014 23:03:17 +0100
+Subject: [PATCH] plugins.hitbox: Refactor to use the StreamMapper.
+
+Also add support for HLS streams.
+
+Resolves #648.
+---
+ src/livestreamer/plugins/hitbox.py | 139 ++++++++++++++++++++++++-------------
+ 1 file changed, 92 insertions(+), 47 deletions(-)
+
+diff --git a/src/livestreamer/plugins/hitbox.py b/src/livestreamer/plugins/hitbox.py
+index 306a318..556a3d9 100644
+--- a/src/livestreamer/plugins/hitbox.py
++++ b/src/livestreamer/plugins/hitbox.py
+@@ -1,10 +1,13 @@
+ import re
+ 
++from itertools import chain
++
+ from livestreamer.compat import urlparse
+ from livestreamer.plugin import Plugin
+-from livestreamer.plugin.api import http, validate
++from livestreamer.plugin.api import StreamMapper, http, validate
+ from livestreamer.stream import HLSStream, HTTPStream, RTMPStream
+ 
++HLS_PLAYLIST_BASE = "http://www.hitbox.tv{0}"
+ LIVE_API = "http://www.hitbox.tv/api/media/live/{0}?showHidden=true"
+ PLAYER_API = "http://www.hitbox.tv/api/player/config/{0}/{1}?embed=false&showHidden=true"
+ SWF_BASE = "http://edge.vie.hitbox.tv/static/player/flowplayer/"
+@@ -43,7 +46,7 @@
+                 validate.filter(lambda b: b.get("url") and b.get("label")),
+                 [{
+                     "label": validate.text,
+-                    "url": validate.text
++                    "url": validate.text,
+                 }],
+             )
+         },
+@@ -52,15 +55,20 @@
+             validate.optional("netConnectionUrl"): validate.text,
+             validate.optional("bitrates"): [{
+                 "label": validate.text,
+-                "url": validate.text
++                "url": validate.text,
++                "provider": validate.text
+             }]
+         }],
+-        "plugins": {
+-            validate.optional("clustering"): {
+-                "netConnectionUrl": validate.text,
+-                "url": validate.text
++        "plugins": validate.all(
++            dict,
++            validate.filter(lambda k, v: k in ["rtmp", "rtmpHitbox", "hls"]),
++            {
++                validate.text: {
++                    validate.optional("netConnectionUrl"): validate.text,
++                    "url": validate.text
++                }
+             }
+-        }
++        )
+     }
+ )
+ 
+@@ -77,6 +85,79 @@ def _get_quality(self, label):
+ 
+         return "live"
+ 
++    def _create_hls_streams(self, bitrate):
++        url = bitrate["url"]
++        quality = self._get_quality(bitrate["label"])
++
++        if not url.startswith("http"):
++            url = HLS_PLAYLIST_BASE.format(url)
++
++        if bitrate["label"] == "Auto":
++            try:
++                streams = HLSStream.parse_variant_playlist(self.session, url)
++                return streams.items()
++            except IOError as err:
++                self.logger.warning("Failed to extract HLS streams: {0}", err)
++        else:
++            return quality, HLSStream(self.session, url)
++
++    def _create_rtmp_stream(self, rtmp, swf_url, bitrate):
++        quality = self._get_quality(bitrate["label"])
++        url = bitrate["url"]
++        stream = RTMPStream(self.session, {
++            "rtmp": rtmp,
++            "pageUrl": self.url,
++            "playpath": url,
++            "swfVfy": swf_url,
++            "live": True
++        })
++
++        return quality, stream
++
++    def _get_live_streams(self, player):
++        mappers = []
++        swf_url = SWF_URL
++        for playlist in player.get("playlist", []):
++            bitrates = playlist.get("bitrates")
++            provider = playlist.get("connectionProvider")
++            rtmp = None
++
++            if bitrates:
++                rtmp = playlist.get("netConnectionUrl")
++            elif provider and provider in player["plugins"]:
++                provider = player["plugins"][provider]
++                swf_name = provider["url"]
++                swf_url = SWF_BASE + swf_name
++                rtmp = provider["netConnectionUrl"]
++                bitrates = player["clip"]["bitrates"]
++            else:
++                continue
++
++            mapper = StreamMapper(
++                cmp=lambda provider, bitrate: bitrate["provider"].startswith(provider)
++            )
++            mapper.map("hls", self._create_hls_streams)
++            mapper.map("rtmp", self._create_rtmp_stream, rtmp, swf_url)
++            mappers.append(mapper(bitrates))
++
++        return chain.from_iterable(mappers)
++
++    def _create_video_stream(self, cls, base_url, bitrate):
++        url = base_url + "/" + bitrate["url"]
++        quality = self._get_quality(bitrate["label"])
++        return quality, cls(self.session, url)
++
++    def _get_video_streams(self, player):
++        base_url = player["clip"]["baseUrl"] or VOD_BASE_URL
++        mapper = StreamMapper(
++            cmp=lambda ext, bitrate: urlparse(bitrate["url"]).path.endswith(ext)
++        )
++        mapper.map(".m3u8", self._create_video_stream, HLSStream, base_url)
++        mapper.map(".mp4", self._create_video_stream, HTTPStream, base_url)
++        mapper.map(".flv", self._create_video_stream, HTTPStream, base_url)
++
++        return mapper(player["clip"]["bitrates"])
++
+     def _get_streams(self):
+         match = _url_re.match(self.url)
+         if not match:
+@@ -96,46 +177,10 @@ def _get_streams(self):
+ 
+         res = http.get(PLAYER_API.format(media_type, media_id))
+         player = http.json(res, schema=_player_schema)
++
+         if media_type == "live":
+-            swf_url = SWF_URL
+-            for playlist in player.get("playlist", []):
+-                bitrates = playlist.get("bitrates")
+-                provider = playlist.get("connectionProvider")
+-                rtmp = None
+-
+-                if bitrates:
+-                    rtmp = playlist.get("netConnectionUrl")
+-                elif provider and provider in player["plugins"]:
+-                    provider = player["plugins"][provider]
+-                    swf_name = provider["url"]
+-                    swf_url = SWF_BASE + swf_name
+-                    rtmp = provider["netConnectionUrl"]
+-                    bitrates = player["clip"]["bitrates"]
+-                else:
+-                    continue
+-
+-                for bitrate in bitrates:
+-                    quality = self._get_quality(bitrate["label"])
+-                    url = bitrate["url"]
+-                    stream = RTMPStream(self.session, {
+-                        "rtmp": rtmp,
+-                        "pageUrl": self.url,
+-                        "playpath": url,
+-                        "swfVfy": swf_url,
+-                        "live": True
+-                    })
+-                    yield quality, stream
++            return self._get_live_streams(player)
+         else:
+-            base_url = player["clip"]["baseUrl"] or VOD_BASE_URL
+-            for bitrate in player["clip"]["bitrates"]:
+-                url = base_url + "/" + bitrate["url"]
+-                quality = self._get_quality(bitrate["label"])
+-
+-                if urlparse(url).path.endswith("m3u8"):
+-                    stream = HLSStream(self.session, url)
+-                else:
+-                    stream = HTTPStream(self.session, url)
+-
+-                yield quality, stream
++            return self._get_video_streams(player)
+ 
+ __plugin__ = Hitbox



More information about the arch-commits mailing list