1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
from livestreamer.compat import str, bytes
from livestreamer.packages.flashmedia import AMF0Packet, AMFError
from livestreamer.plugins import Plugin, PluginError, NoStreamsError
from livestreamer.stream import HLSStream, RTMPStream
from livestreamer.utils import urlget
from io import BytesIO
import re
class UStreamTV(Plugin):
AMFURL = "http://cgw.ustream.tv/Viewer/getStream/1/{0}.amf"
SWFURL = "http://static-cdn1.ustream.tv/swf/live/viewer3:50.swf"
@classmethod
def can_handle_url(self, url):
return "ustream.tv" in url
def _get_channel_id(self, url):
res = urlget(url)
match = re.search("\"cid\":(\d+)", res.text)
if match:
return int(match.group(1))
def _create_stream(self, cdn, streamname):
url = "{0}/{1}".format(cdn, streamname)
options = dict(rtmp=url, pageUrl=self.url,
swfUrl=self.SWFURL, live=True)
return RTMPStream(self.session, options)
def _get_streams(self):
channelid = self._get_channel_id(self.url)
if not channelid:
raise NoStreamsError(self.url)
self.logger.debug("Fetching stream info")
res = urlget(self.AMFURL.format(channelid))
try:
packet = AMF0Packet.deserialize(BytesIO(res.content))
except (IOError, AMFError) as err:
raise PluginError(("Failed to parse AMF packet: {0}").format(str(err)))
result = None
for message in packet.messages:
if message.target_uri == "/1/onResult":
result = message.value
break
if not result:
raise PluginError("No result found in AMF packet")
streams = {}
if "liveHttpUrl" in result:
try:
hlsstreams = HLSStream.parse_variant_playlist(self.session,
result["liveHttpUrl"])
streams.update(hlsstreams)
except IOError as err:
self.logger.warning("Failed to get variant playlist: {0}", err)
if "streamName" in result:
if "cdnUrl" in result:
cdn = result["cdnUrl"]
elif "fmsUrl" in result:
cdn = result["fmsUrl"]
else:
self.logger.warning("Missing cdnUrl and fmsUrl from result")
return streams
if "videoCodec" in result and result["videoCodec"]["height"] > 0:
streamname = "{0}p".format(int(result["videoCodec"]["height"]))
else:
streamname = "live"
streams[streamname] = self._create_stream(cdn, result["streamName"])
if "streamVersions" in result:
for version, info in result["streamVersions"].items():
if "streamVersionCdn" in info:
for name, cdn in info["streamVersionCdn"].items():
if "cdnStreamUrl" in cdn and "cdnStreamName" in cdn:
streams["cdn_" + name] = self._create_stream(cdn["cdnStreamUrl"],
cdn["cdnStreamName"])
return streams
__plugin__ = UStreamTV
|